Carina 是由博云主導(dǎo)并發(fā)起的云原生本地存儲項目(GitHub 地址為:https://github.com/carina-io/carina),目前已經(jīng)進入 CNCF 全景圖。Carina 可以為云原生環(huán)境中的有狀態(tài)應(yīng)用提供高性能、免運維的本地存儲解決方案,具有存儲卷生命周期管理、LVM/RAW盤供應(yīng)、智能調(diào)度、RAID管理、自動分層等能力,旨在為云原生有狀態(tài)服務(wù)提供極低延遲、免運維、懂數(shù)據(jù)庫的數(shù)據(jù)存儲系統(tǒng)。Carina 作為博云容器云平臺的組件之一,已經(jīng)在多個金融機構(gòu)的生產(chǎn)環(huán)境中穩(wěn)定運行多年。
傳統(tǒng)的數(shù)據(jù)備份方案主要有兩種, 一種是利用存儲數(shù)據(jù)的服務(wù)端實現(xiàn)基于快照的備份,另一種是在每臺目標服務(wù)器上部署專有備份 agent 并指定備份數(shù)據(jù)目錄,定期把數(shù)據(jù)復(fù)制到外部存儲上。這兩種方式的備份機制相對固化,在云原生時代無法適應(yīng)容器化后的彈性、池化等部署場景。
以云原生存儲插件 Carina 為例,數(shù)據(jù)庫等數(shù)據(jù)敏感場景中每個數(shù)據(jù)庫集群包括多個計算實例,實例可能在集群內(nèi)任意漂移并實現(xiàn)自動故障恢復(fù)。傳統(tǒng)數(shù)據(jù)備份方式在數(shù)據(jù)庫集群快速擴縮容、跨節(jié)點漂移等場景下無法自動跟隨計算實例遷移從而導(dǎo)致數(shù)據(jù)備份失效,因此一款貼合 k8s 容器場景的備份工具就十分重要。
Kubernetes備份恢復(fù)利器:velero
Velero 是一款云原生時代的災(zāi)難恢復(fù)和遷移工具,采用 Go 語言編寫,并在 github 上進行了開源,開源地址為:https://github.com/vmware-tanzu/velero。Velero 源于西班牙語,意思為帆船,非常符合 Kubernetes 社區(qū)的命名風格。
利用 velero 用戶可以安全的備份、恢復(fù)和遷移 Kubernetes 集群資源和持久卷。它的基本原理就是將集群的數(shù)據(jù),例如集群資源和持久化數(shù)據(jù)卷備份到對象存儲中,在恢復(fù)的時候?qū)?shù)據(jù)從對象存儲中拉取下來。除了災(zāi)備之外它還能做資源移轉(zhuǎn),支持把容器應(yīng)用從一個集群遷移到另一個集群,這也是 velero 一個非常成功的使用場景。
Velero 主要包括連個核心組件,分別為服務(wù)端和客戶端。服務(wù)端運行在具體的 Kubernetes 集群中,客戶端是運行在本地的命令行工具,只要配置好 kubectl 及 kubeconfig 即可使用,非常簡單。
Velero 基于其實現(xiàn)的 kubernetes 資源備份能力,可以輕松實現(xiàn) Kubernetes 集群的數(shù)據(jù)備份和恢復(fù)、復(fù)制 kubernetes 集群資源到其他 kubernetes 集群或者快速復(fù)制生產(chǎn)環(huán)境到測試環(huán)境等功能。
在資源備份方面,velero 支持將數(shù)據(jù)備份到眾多的云存儲中,例如AWS S3或S3兼容的存儲系統(tǒng)、Azure Blob、Google Cloud存儲、Aliyun OSS等。與備份整個 kubernetes 的數(shù)據(jù)存儲引擎 etcd 相比,velero 的控制更加細化,可以對 Kubernetes 集群內(nèi)對象級別進行備份,還可以通過對 Type、Namespace、Label 等對象進行分類備份或者恢復(fù)。
Velero工作流程
以核心的數(shù)據(jù)備份為例,當執(zhí)行velero backup create my-backup時:
- Velero 客戶端首先調(diào)用 Kubernetes API 服務(wù)器以創(chuàng)建 Backup 對象;
- BackupController 將收到通知有新的 Backup 對象被創(chuàng)建并執(zhí)行驗證;
- BackupController 開始備份過程,它通過查詢 API 服務(wù)器以獲取資源來收集數(shù)據(jù)以進行備份;
- BackupController 將調(diào)用對象存儲服務(wù),例如,AWS S3 -上傳備份文件。默認情況下,velero backup create支持任何持久卷的磁盤快照,可以通過指定其他標志來調(diào)整快照,運行velero backup create –help可以查看可用的標志,也可以使用–snapshot-volumes=false選項禁用快照。
關(guān)于備份存儲位置和卷快照,Velero 有兩個自定義資源 BackupStorageLocation 和 VolumeSnapshotLocation,用于配置 Velero 備份及其關(guān)聯(lián)的持久卷快照的存儲位置。
- BackupStorageLocation 主要支持的后端存儲是 S3 兼容的存儲,存儲所有Velero數(shù)據(jù)的存儲區(qū)中的前綴以及一組其他特定于提供程序的字段。比如:Minio 和阿里云 OSS 等 ;
- VolumeSnapshotLocation(pv 數(shù)據(jù)),主要用來給 PV 做快照,需要云提供商提供插件,完全由提供程序提供的特定的字段(例如AWS區(qū)域,Azure資源組,Portworx快照類型等)定義。以對數(shù)據(jù)一致性最為敏感的數(shù)據(jù)庫和中間件為例,開源存儲插件 Carina 也即將提供數(shù)據(jù)庫感知的 velero 卷快照功能,可以實現(xiàn)中間件數(shù)據(jù)的快速備份及恢復(fù)。
Velero安裝和使用
安裝velero客戶端
$ wget https://mirror.ghproxy.com/https://github.com/vmware-tanzu/velero/releases/download/v1.6.3/velero-v1.6.3-darwin-amd64.tar.gz $ tar -zxvf velero-v1.6.3-darwin-amd64.tar.gz && cd velero-v1.6.3-darwin-amd64 $ mv velero /usr/local/bin && chmod +x /usr/local/bin/velero $ velero version
安裝minio作為數(shù)據(jù)備份后端
Minio安裝Yaml文件如下:
apiVersion: v1 kind: Namespace metadata: name: velero — apiVersion: apps/v1 kind: Deployment metadata: namespace: velero name: minio labels: component: minio spec: strategy: type: Recreate selector: matchLabels: component: minio template: metadata: labels: component: minio spec: volumes: – name: storage emptyDir: {} – name: config emptyDir: {} containers: – name: minio image: minio/minio:latest imagePullPolicy: IfNotPresent args: – server – /storage – –config-dir=/config – –console-address=:9001 env: – name: MINIO_ACCESS_KEY value: “minio” – name: MINIO_SECRET_KEY value: “minio123” ports: – containerPort: 9000 – containerPort: 9001 volumeMounts: – name: storage mountPath: “/storage” – name: config mountPath: “/config” — apiVersion: v1 kind: Service metadata: namespace: velero name: minio labels: component: minio spec: type: NodePort ports: – name: api port: 9000 targetPort: 9000 – name: console port: 9001 targetPort: 9001 selector: component: minio — apiVersion: batch/v1 kind: Job metadata: namespace: velero name: minio-setup labels: component: minio spec: template: metadata: name: minio-setup spec: restartPolicy: OnFailure volumes: – name: config emptyDir: {} containers: – name: mc image: minio/mc:latest imagePullPolicy: IfNotPresent command: – /bin/sh – -c – “mc –config-dir=/config config host add velero http://minio:9000 minio minio123 && mc –config-dir=/config mb -p velero/velero” volumeMounts: – name: config mountPath: “/config”
安裝Mini,并檢查資源創(chuàng)建情況。
$ kubectl apply -f ./00-minio-deployment.yaml $ kubectl get pods -n velero NAME READY STATUS RESTARTS AGEminio-58dc5cf789-z2777 0/1 ContainerCreating 0 14sminio-setup-dz4jb 0/1 ContainerCreating 0 6s$ kubectl get svc -n velero NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEminio NodePort 10.96.13.35 9000:30693/TCP,9001:32351/TCP 17s
待服務(wù)都已經(jīng)啟動完畢,可以登錄 minio 查看 velero/velero 的 bucket 是否創(chuàng)建成功。
安裝 velero 服務(wù)端 ,使用s3 作為存儲
- 創(chuàng)建 minio 憑證
$ cat > credentials-velero <<EOF[default]aws_access_key_id = minioaws_secret_access_key = minio123EOF# 安裝velero$ cp velero /usr/bin/# 啟用快速補全$ velero completion bash
- 使用官方提供的 restic 組件備份 pv
$ velero install –image velero/velero:v1.6.3 –plugins velero/velero-plugin-for-aws:v1.0.0 –provider aws –bucket velero –namespace velero –secret-file ./credentials-velero –velero-pod-cpu-request 200m –velero-pod-mem-request 200Mi –velero-pod-cpu-limit 1000m –velero-pod-mem-limit 1000Mi –use-volume-snapshots=false –use-restic –restic-pod-cpu-request 200m –restic-pod-mem-request 200Mi –restic-pod-cpu-limit 1000m –restic-pod-mem-limit 1000Mi –backup-location-config region=minio,s3ForcePathStyle=”true”,s3Url=http://minio.velero.svc:9000
其中,幾個重要的參數(shù)及其說明如下:
–provider:聲明使用的 Velero 插件類型。–plugins:使用 S3 API 兼容插件 “velero-plugin-for-aws ”。–bucket:在騰訊云 COS 創(chuàng)建的存儲桶名。–secret-file:訪問 COS 的訪問憑證文件,見上面創(chuàng)建的 “credentials-velero”憑證文件。–use-restic:使用開源免費備份工具 restic 備份和還原持久卷數(shù)據(jù)。–default-volumes-to-restic:使用 restic 來備份所有Pod卷,前提是需要開啟 –use-restic 參數(shù)。–backup-location-config:備份存儲桶訪問相關(guān)配置。–region:兼容 S3 API 的 COS 存儲桶地區(qū),例如創(chuàng)建地區(qū)是廣州的話,region 參數(shù)值為“ap-guangzhou”。–s3ForcePathStyle:使用 S3 文件路徑格式。–s3Url:COS 兼容的 S3 API 訪問地址–use-volume-snapshots=false 來關(guān)閉存儲卷數(shù)據(jù)快照備份。
安裝命令執(zhí)行完成后,等待 Velero 和 restic 工作負載就緒后,查看配置的存儲位置是否可用。
$ velero backup-location get apiVersion: velero.io/v1 kind: BackupStorageLocation metadata: name: default namespace: velero spec: # 只有 aws gcp azure provider: aws objectStorage: bucket: myBucket prefix: backup config: region: us-west-2 profile: “default” s3ForcePathStyle: “false” s3Url: http://minio:9000
至此 velero 就已經(jīng)全部部署完成。
velero功能介紹
創(chuàng)建備份
velero 支持備份所有對象,也可以按類型,名稱空間和/或標簽過濾對象
$ velero create backup $NAME [flags]$ velero backup create pvc-backup-1 –snapshot-volumes –include-namespaces nginx-example –default-volumes-to-restic –volume-snapshot-locations default
其中:
–include-namespaces:備份該命名空間下的所有資源,不包括集群資源
–include-resources:要備份的資源類型
–include-cluster-resources:是否備份集群資源 此選項可以具有三個可能的值: true:包括所有集群范圍的資源; false:不包括集群范圍內(nèi)的資源; nil (“自動”或不提供)
–selector:通過標簽選擇匹配的資源備份
–exclude-namespaces:備份時該命名空間下的資源不進行備份
–exclude-resources:備份時該類型的資源不進行備份
http://–velero.io/exclude-from-backup=true:當標簽選擇器匹配到該資源時,若該資源帶有此標簽,也不進行備份
同時,也可以通過使用 –ordered-resources 參數(shù),按特定順序備份特定種類的資源,需要指定資源名稱和該資源的對象名稱列表,資源對象名稱以逗號分隔,其名稱格式為“命名空間/資源名稱”,對于集群范圍資源,只需使用資源名稱。映射中的鍵值對以分號分隔,資源類型是復(fù)數(shù)形式。
$ velero backup create backupName –include-cluster-resources=true –ordered-resources ‘pods=ns1/pod1,ns1/pod2;persistentvolumes=pv4,pv8’ –include-namespaces=ns1$ velero backup create backupName –ordered-resources ‘statefulsets=ns1/sts1,ns1/sts0’ –include-namespaces=n
定時備份:
$ velero schedule create –schedule “0 7 * * *”$ velero create schedule NAME –schedule=”@every 6h”$ velero create schedule NAME –schedule=”@every 24h” –include-namespaces web$ velero create schedule NAME –schedule=”@every 168h” –ttl 2160h0m0s
備份高級用法舉例
- 在單個Velero備份中創(chuàng)建不止一種持久卷的快照
$ velero snapshot-location create ebs-us-east-1 –provider aws –config region=us-east-1$ velero snapshot-location create portworx-cloud –provider portworx –config type=cloud$ velero backup create full-cluster-backup –volume-snapshot-locations ebs-us-east-1,portworx-cloud
- 在不同的地區(qū)將備份存儲到不同的對象存儲桶中
$ velero backup-location create default –provider aws –bucket velero-backups –config region=us-east-1$ velero backup-location create s3-alt-region –provider aws –bucket velero-backups-alt –config region=us-west-1$ velero backup create full-cluster-alternate-location-backup –storage-location s3-alt-region
- 對于公有云提供的存儲卷,將一部分快照存儲在本地,一部分存儲在公有云
$ velero snapshot-location create portworx-local –provider portworx –config type=local$ velero snapshot-location create portworx-cloud –provider portworx –config type=cloud$ velero backup create cloud-snapshot-backup –volume-snapshot-locations portworx-cloud
- 使用存儲位置
$ velero backup-location create default –provider aws –bucket velero-backups –config region=us-west-1$ velero snapshot-location create ebs-us-west-1 –provider aws –config region=us-west-1$ velero backup create full-cluster-backup
查看備份任務(wù)。
當備份任務(wù)狀態(tài)是 “Completed” ,且錯誤數(shù)為 0 ,說明備份任務(wù)完成且沒發(fā)生任何錯誤,可以通過以下命令查詢:
$ velero backup get
通過先臨時將備份存儲位置更新為只讀模式,可以防止在還原過程中在備份存儲位置中創(chuàng)建或刪除備份對象。
$ kubectl patch backupstoragelocation default –namespace velero –type merge –patch ‘{“spec”:{“accessMode”:”ReadOnly”}}’ velero backup-location getNAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULTdefault aws velero Unknown Unknown ReadWrite true
恢復(fù)備份數(shù)據(jù)
$ velero restore create –from-backup $ velero restore create –from-backup pvc-backup-1 –restore-volumes
查看恢復(fù)任務(wù)。
$ velero restore get
還原完成后,不要忘記把備份存儲位置恢復(fù)為讀寫模式,以便下次備份任務(wù)使用:
$ kubectl patch backupstoragelocation default –namespace velero –type merge –patch ‘{“spec”:{“accessMode”:”ReadWrite”}}’
備份 hooks 介紹
Velero 支持在備份任務(wù)執(zhí)行之前和執(zhí)行后在容器中執(zhí)行一些預(yù)先設(shè)定好的命令,這種方式對數(shù)據(jù)一致性等非常有效。velero 支持兩種方法指定鉤子,一種是 pod 本身的注釋聲明,另一種是在定義 Backup 任務(wù)時的 Spec 中聲明。
- Pre hooks
pre.hook.backup.velero.io/container:將要執(zhí)行命令的容器,默認為pod中的第一個容器,可選的。pre.hook.backup.velero.io/command:要執(zhí)行的命令,如果需要多個參數(shù),請將該命令指定為JSON數(shù)組。例如:[“/usr/bin/uname”, “-a”]pre.hook.backup.velero.io/on-error:如果命令返回非零退出代碼如何處理。默認為“Fail”,有效值為“Fail”和“Continue”,可選的。pre.hook.backup.velero.io/timeout:等待命令執(zhí)行的時間,如果命令超過超時,則認為該掛鉤失敗的。默認為30秒,可選的。
- Post hooks
post.hook.backup.velero.io/container:將要執(zhí)行命令的容器,默認為pod中的第一個容器,可選的。post.hook.backup.velero.io/command:要執(zhí)行的命令,如果需要多個參數(shù),請將該命令指定為JSON數(shù)組。例如:[“/usr/bin/uname”, “-a”]post.hook.backup.velero.io/on-error:如果命令返回非零退出代碼如何處理。默認為“Fail”,有效值為“Fail”和“Continue”,可選的。post.hook.backup.velero.io/timeout:等待命令執(zhí)行的時間,如果命令超過超時,則認為該掛鉤失敗的。默認為30秒,可選的
還原 hooks 介紹
Velero 支持還原 hooks,可以在還原任務(wù)執(zhí)行前或還原過程之后執(zhí)行的自定義操作。有以下兩種定義形式:
- InitContainer Restore Hooks:這些將在待還原的 Pod 的應(yīng)用程序容器啟動之前將 init 容器添加到還原的 pod 中,以執(zhí)行任何必要的設(shè)置。
init.hook.restore.velero.io/container-image:要添加的init容器的容器鏡像init.hook.restore.velero.io/container-name:要添加的init容器的名稱init.hook.restore.velero.io/command:將要在初始化容器中執(zhí)行的任務(wù)或命令
如進行備份之前,請使用以下命令將注釋添加到Pod:
kubectl annotate pod -n init.hook.restore.velero.io/container-name=restore-hook init.hook.restore.velero.io/container-image=alpine:latest init.hook.restore.velero.io/command='[“/bin/ash”, “-c”, “date”]’
- Exec Restore Hooks:可用于在已還原的Kubernetes pod的容器中執(zhí)行自定義命令或腳本。
post.hook.restore.velero.io/container:;執(zhí)行hook的容器名稱,默認為第一個容器,可選post.hook.restore.velero.io/command:將在容器中執(zhí)行的命令,必填post.hook.restore.velero.io/on-error:如何處理執(zhí)行失敗,有效值為Fail和Continue,默認為Continue,使用Continue模式,僅記錄執(zhí)行失敗;使用Fail模式時,將不會在自行其他的hook,還原的狀態(tài)將為PartiallyFailed,可選post.hook.restore.velero.io/exec-timeout:開始執(zhí)行后要等待多長時間,默認為30秒,可選post.hook.restore.velero.io/wait-timeout:等待容器準備就緒的時間,該時間應(yīng)足夠長,以使容器能夠啟動,并
如進行備份之前,請使用以下命令將注釋添加到Pod
kubectl annotate pod -n post.hook.restore.velero.io/container=postgres post.hook.restore.velero.io/command='[“/bin/bash”, “-c”, “psql < /backup/backup.sql"]' post.hook.restore.velero.io/wait-timeout=5m post.hook.restore.velero.io/exec-timeout=45s post.hook.restore.velero.io/on-error=Continue
Velero部分關(guān)鍵問題解析
Velero可以將資源還原到與其備份來源不同的命名空間中嗎?
是的,可以使用–namespace-mappings參數(shù)來指定:
velero restore create RESTORE_NAME –from-backup BACKUP_NAME –namespace-mappings old-ns-1:new-ns-1,old-ns-2:new-ns-2
執(zhí)行還原操作后,已有的 NodePort 類型的 service 如何處理?
Velero 有一個參數(shù),可讓用戶決定保留原來的 nodePorts。
velero restore create子命令具有 –preserve-nodeports標志保護服務(wù)nodePorts。此標志用于從備份中保留原始的nodePorts,可用作–preserve-nodeports或–preserve-nodeports=true 如果給定此標志,則Velero在還原Service時不會刪除nodePorts,而是嘗試使用備份時寫入的nodePorts。
velero怎么實現(xiàn)不影響業(yè)務(wù)前提下得一致性備份策略,并將備份數(shù)據(jù)上傳到對象存儲中?
如果是基于velero實現(xiàn)數(shù)據(jù)庫的一致性,需要用velero的hook,在備份前對數(shù)據(jù)庫進行quiesce操作,備份完unquiesce。對于備份本身,可以使用restic來copy數(shù)據(jù)(但不用快照),或者使用快照的方式。