Velero 是一款雲原生時代的災難恢復和遷移工具,採用 Go 語言編寫,並在 github 上進行了開源,利用 velero 使用者可以安全的備份、恢復和遷移 Kubernetes 叢集資源和持久卷。
Velero 元件一共分兩部分,分別是伺服器端和使用者端。
Velero
支援兩種關於後端儲存的CRD
,分別是BackupStorageLocation
和VolumeSnapshotLocation
。
主要用來定義 Kubernetes 叢集資源的資料存放位置,也就是叢集物件資料,不是 PVC 的資料。主要支援的後端儲存是 S3 相容的儲存,比如:Mino 和阿里雲 OSS 等。
主要用來給 PV 做快照,需要雲提供商提供外掛。阿里雲已經提供了外掛,這個需要使用 CSI 等儲存機制。你也可以使用專門的備份工具 Restic
,把 PV 資料備份到阿里雲 OSS 中去(安裝時需要自定義選項)。
Restic 是一款 GO 語言開發的資料加密備份工具,顧名思義,可以將本地資料加密後傳輸到指定的倉庫。支援的倉庫有 Local、SFTP、Aws S3、Minio、OpenStack Swift、Backblaze B2、Azure BS、Google Cloud storage、Rest Server。
Velero支援很多種儲存外掛,可檢視:https://velero.io/docs/v1.10/supported-providers/獲取外掛資訊,我們這裡使用minio作為S3相容的物件儲存提供程式。您也可以在任意地方部署Minio物件儲存,只需要保證K8S叢集可以存取到即可。
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: velero
labels:
app: minio
spec:
selector:
app: minio
ports:
- name: api
port: 9000
protocol: TCP
- name: console
port: 9001
protocol: TCP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: minio
namespace: velero
labels:
app: minio
spec:
replicas: 1
serviceName: minio
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: docker.io/bitnami/minio:2023.3.22
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9000
name: api
protocol: TCP
- containerPort: 9001
name: console
protocol: TCP
env:
- name: MINIO_ROOT_USER
value: "minio"
- name: MINIO_ROOT_PASSWORD
value: "minio123"
- name: MINIO_DEFAULT_BUCKETS
value: "velero"
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
# 建立velero名稱空間
$ kubectl create namespace velero
# 建立minio資源
$ kubectl apply -f minio.yaml
# 檢視部署狀態
$ kubectl get sts,pod,svc -n velero
NAME READY AGE
statefulset.apps/minio 1/1 66s
NAME READY STATUS RESTARTS AGE
pod/minio-0 1/1 Running 0 65s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/minio ClusterIP 10.99.223.162 <none> 9000/TCP,9001/TCP 66s
# 開放NodePort埠
$ kubectl patch svc minio -n velero -p '{"spec": {"type": "NodePort"}}'
$ kubectl patch svc minio -n velero --type='json' -p='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":9000},{"op": "replace", "path": "/spec/ports/1/nodePort", "value":9001}]'
$ kubectl get svc -n velero
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio NodePort 10.99.223.162 <none> 9000:9000/TCP,9001:9001/TCP 140m
通過瀏覽器存取伺服器IP:9001
,並使用賬號minio
密碼minio123
登入驗證。
版本列表:https://github.com/vmware-tanzu/velero/releases
$ wget https://github.com/vmware-tanzu/velero/releases/download/v1.10.2/velero-v1.10.2-linux-amd64.tar.gz
$ tar zxf velero-v1.10.2-linux-amd64.tar.gz
$ mv velero-v1.10.2-linux-amd64/velero /usr/bin/
$ velero -h
# 啟用命令補全
$ source <(velero completion bash)
$ velero completion bash > /etc/bash_completion.d/velero
$ cat > credentials-velero <<EOF
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
EOF
$ velero install \
--provider aws \
--image velero/velero:v1.10.2 \
--plugins velero/velero-plugin-for-aws:v1.6.0 \
--bucket velero \
--secret-file ./credentials-velero \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio:9000 \
--wait
# 執行install命令後會建立一系列清單,包括CustomResourceDefinition、Namespace、Deployment等。
# 可使用如下命令檢視執行紀錄檔
$ kubectl logs deployment/velero -n velero
# 檢視velero建立的api物件
$ kubectl api-versions | grep velero
velero.io/v1
# 檢視備份位置
$ velero backup-location get
NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULT
default aws velero Available 2023-03-28 15:45:30 +0800 CST ReadWrite true
選項說明:
--kubeconfig
(可選):指定kubeconfig
認證檔案,預設使用.kube/config
;--provider
:定義外掛提供方;--image
:定義執行velero的映象,預設與velero使用者端一致;--plugins
:指定使用aws s3相容的外掛映象;--bucket
:指定物件儲存Bucket桶名稱;--secret-file
:指定物件儲存認證檔案;--use-node-agent
:建立Velero Node Agent守護行程,託管FSB模組;--use-volume-snapshots
:是否啟使用快照;--namespace
:指定部署的namespace名稱,預設為velero;--backup-location-config
:指定物件儲存地址資訊;aws外掛與velero版本對應關係:
如果您想從叢集中完全解除安裝Velero,則以下命令將刪除由velero install
建立的所有資源:
kubectl delete namespace/velero clusterrolebinding/velero
kubectl delete crds -l component=velero
備份命令:velero create backup NAME [flags]
backup選項:
--exclude-namespaces stringArray
: 要從備份中排除的名稱空間--exclude-resources stringArray
: 要從備份中排除的資源,如storageclasses.storage.k8s.io
--include-cluster-resources optionalBool[=true]
: 包含叢集資源型別--include-namespaces stringArray
: 要包含在備份中的名稱空間(預設'*')--include-resources stringArray
: 備份中要包括的資源--labels mapStringString
: 給這個備份加上標籤-o, --output string
: 指定輸出格式,支援'table'、'json'和'yaml';-l, --selector labelSelector
: 對指定標籤的資源進行備份--snapshot-volumes optionalBool[=true]
: 對 PV 建立快照--storage-location string
: 指定備份的位置--ttl duration
: 備份資料多久刪掉--volume-snapshot-locations strings
: 指定快照的位置,也就是哪一個公有云驅動$ kubectl apply -f examples/nginx-app/base.yaml
namespace/nginx-example created
deployment.apps/nginx-deployment created
service/my-nginx created
# 檢視資源清單
$ kubectl get all -n nginx-example
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-57d5dcb68-g42mk 1/1 Running 0 41s
pod/nginx-deployment-57d5dcb68-pcc6t 1/1 Running 0 41s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-nginx LoadBalancer 10.96.0.31 <pending> 80:27370/TCP 41s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 41s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-57d5dcb68 2 2 2 41s
$ velero backup create nginx-backup --include-namespaces nginx-example
Backup request "nginx-backup" submitted successfully.
Run `velero backup describe nginx-backup` or `velero backup logs nginx-backup` for more details.
選項:
--include-namespaces
:指定名稱空間--selector
:標籤選擇器,如app=nginx$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
nginx-backup Completed 0 0 2023-03-09 09:38:50 +0800 CST 29d default <none>
# 檢視備份詳細資訊
$ velero backup describe nginx-backup
# 檢視備份紀錄檔
$ velero backup logs nginx-backup
登入minio控制檯檢視備份內容
# 使用cron表示式備份
$ velero schedule create nginx-daily --schedule="0 1 * * *" --include-namespaces nginx-example
# 使用一些非標準的速記 cron 表示式
$ velero schedule create nginx-daily --schedule="@daily" --include-namespaces nginx-example
# 手動觸發定時任務
$ velero backup create --from-schedule nginx-daily
更多cron範例請參考:cron package’s documentation
# 刪除nginx-example名稱空間和資源
$ kubectl delete namespace nginx-example
# 檢查是否刪除
$ kubectl get all -n nginx-example
No resources found in nginx-example namespace.
$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
nginx-backup Completed 0 0 2023-03-09 09:38:50 +0800 CST 29d default <none>
$ velero restore create --from-backup nginx-backup
Restore request "nginx-backup-20230309095025" submitted successfully.
Run `velero restore describe nginx-backup-20230309095025` or `velero restore logs nginx-backup-20230309095025` for more details.
$ velero restore get
NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR
nginx-backup-20230309095025 nginx-backup Completed 2023-03-09 09:50:25 +0800 CST 2023-03-09 09:50:25 +0800 CST 0 1 2023-03-09 09:50:25 +0800 CST <none>
# 檢視詳細資訊
$ velero restore describe nginx-backup-20230309095025
# 檢查資源狀態
$ kubectl get all -n nginx-example
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-57d5dcb68-g42mk 1/1 Running 0 2m19s
pod/nginx-deployment-57d5dcb68-pcc6t 1/1 Running 0 2m19s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-nginx LoadBalancer 10.96.0.204 <pending> 80:31291/TCP 2m19s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 2m19s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-57d5dcb68 2 2 2 2m19s
我們將使用Velero
快速完成雲原生應用及PV資料的遷移實踐過程,在本文範例中,我們將A叢集中的一個MOS應用遷移到叢集B中,其中資料備份採用自建Minio物件儲存服務。
StorageClass
。角色 | 叢集IP | 叢集版本 | 部署軟體 |
---|---|---|---|
K8S 叢集A | 192.168.1.102 | v1.22.10 | openebs、velero、app-system |
K8S 叢集B | 192.168.1.103 | v1.22.10 | openebs、velero、minio |
我們需要將叢集A中 app-system 空間的所有資源和資料全部遷移到叢集B中,該專案包括了deployment
、statefulset
、service
、ingress
、job
、cronjob
、secret
、configmap
、pv
、pvc
。
# 專案清單資訊
$ kubectl get deployment,sts,pvc -n app-system
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/hasura-graphql 1/1 1 1 5h27m
deployment.apps/iot-backend 1/1 1 1 5h27m
deployment.apps/iot-gateway 1/1 1 1 5h27m
deployment.apps/iot-history 1/1 1 1 5h27m
deployment.apps/iot-observer 1/1 1 1 5h27m
deployment.apps/app-backend 1/1 1 1 5h27m
deployment.apps/app-frontend 1/1 1 1 5h27m
NAME READY AGE
statefulset.apps/minio 1/1 5h27m
statefulset.apps/mongo 1/1 5h27m
statefulset.apps/postgres 1/1 5h27m
statefulset.apps/rabbitmq 1/1 5h27m
statefulset.apps/redis 1/1 5h27m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/data-minio-0 Bound pvc-950d15a8-20a5-4e5f-8dbf-b904295355bb 50Gi RWO openebs-hostpath 5h27m
persistentvolumeclaim/data-mongo-0 Bound pvc-e435b80e-0370-4100-b223-ca841f24bd5d 50Gi RWO openebs-hostpath 5h27m
persistentvolumeclaim/data-postgres-0 Bound pvc-359ec32a-4bfc-4bc8-8cf3-38322e8ef59b 300Gi RWO openebs-hostpath 5h27m
persistentvolumeclaim/data-redis-0 Bound pvc-da718e0c-992c-4f6e-af44-abb1c7214a9e 2Gi RWO openebs-hostpath 5h27m
persistentvolumeclaim/app-backend Bound pvc-506261a9-6be4-4d95-8807-58201e31a527 10Gi RWO openebs-hostpath 5h27m
按照2.1和2.2的方法在叢集B(192.168.1.103)中建立minio
應用,用來存放備份資料。
$ kubectl get sts,svc -n velero
NAME READY AGE
statefulset.apps/minio 1/1 3h44m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/minio NodePort 10.99.223.162 <none> 9000:9000/TCP,9001:9001/TCP 3h44m
請確保在叢集A和叢集B中已經安裝好velero使用者端,請參考3.1 安裝velero命令程式
$ cat > credentials-velero <<EOF
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
EOF
$ velero install \
--provider aws \
--image velero/velero:v1.10.2 \
--plugins velero/velero-plugin-for-aws:v1.6.0 \
--bucket velero \
--secret-file ./credentials-velero \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://192.168.1.103:9000 \
--wait
注意:其中S3
的地址指向叢集B(192.168.1.103)的minio物件儲存。
$ cat > credentials-velero <<EOF
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
EOF
$ velero install \
--provider aws \
--image velero/velero:v1.10.2 \
--plugins velero/velero-plugin-for-aws:v1.6.0 \
--bucket velero \
--secret-file ./credentials-velero \
--use-node-agent \
--use-volume-snapshots=false \
--namespace velero \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio:9000 \
--wait
注意:其中S3
的地址指向本叢集minio物件儲存的svc地址。
$ velero backup create app-backup \
--default-volumes-to-fs-backup \
--include-namespaces app-system
Backup request "app-backup" submitted successfully.
Run `velero backup describe app-backup` or `velero backup logs app-backup` for more details.
# 檢視備份狀態
$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
app-backup Completed 0 0 2023-03-28 16:34:56 +0800 CST 29d default <none>
--default-volumes-to-fs-backup
:預設將所有PV捲進行備份,詳情檢視官方檔案。--include-namespaces
:指定要備份的名稱空間登入minio控制檯上可以看到備份的檔案:
# 到叢集B中檢視備份資源
$ velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
app-backup Completed 0 0 2023-03-28 16:41:55 +0800 CST 29d default <none>
# 執行恢復命令
$ velero restore create --from-backup app-backup
Restore request "app-backup-20230328164601" submitted successfully.
Run `velero restore describe app-backup-20230328164601` or `velero restore logs app-backup-20230328164601` for more details.
# 檢視恢復任務
$ velero restore get
NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR
app-backup-20230328164601 app-backup Completed 2023-03-28 16:46:01 +0800 CST 2023-03-28 17:01:26 +0800 CST 0 30 2023-03-28 16:46:01 +0800 CST <none>
$ kubectl get deploy,sts,svc,pvc -n app-system
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/hasura-graphql 1/1 1 1 29m
deployment.apps/iot-backend 1/1 1 1 29m
deployment.apps/iot-gateway 1/1 1 1 29m
deployment.apps/iot-history 1/1 1 1 29m
deployment.apps/iot-observer 1/1 1 1 29m
deployment.apps/app-backend 1/1 1 1 29m
deployment.apps/app-frontend 1/1 1 1 29m
NAME READY AGE
statefulset.apps/minio 1/1 29m
statefulset.apps/mongo 1/1 29m
statefulset.apps/postgres 1/1 29m
statefulset.apps/rabbitmq 1/1 29m
statefulset.apps/redis 1/1 29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hasura-graphql ClusterIP 10.107.231.148 <none> 8080/TCP 29m
service/iot-backend ClusterIP 10.98.78.23 <none> 3000/TCP 29m
service/iot-gateway ClusterIP 10.108.211.114 <none> 1880/TCP 29m
service/iot-history ClusterIP 10.98.217.234 <none> 3000/TCP 29m
service/iot-observer ClusterIP 10.105.75.200 <none> 3010/TCP 29m
service/minio ClusterIP 10.97.14.151 <none> 9000/TCP,9001/TCP 29m
service/mongo ClusterIP 10.97.212.84 <none> 27017/TCP 29m
service/app-backend ClusterIP 10.107.16.116 <none> 5959/TCP 29m
service/app-frontend ClusterIP 10.100.136.90 <none> 80/TCP,443/TCP 29m
service/postgres ClusterIP 10.101.235.245 <none> 5432/TCP,9187/TCP 29m
service/rabbitmq ClusterIP 10.108.29.67 <none> 15672/TCP,5672/TCP 29m
service/redis ClusterIP 10.101.105.81 <none> 6379/TCP,9121/TCP 29m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/data-minio-0 Bound pvc-ca5c63bf-9aaa-4755-ad8f-35718f51decf 50Gi RWO openebs-hostpath 29m
persistentvolumeclaim/data-mongo-0 Bound pvc-03203801-e339-44ee-bfb4-b196808c7cc5 50Gi RWO openebs-hostpath 29m
persistentvolumeclaim/data-postgres-0 Bound pvc-e2f2593e-5869-420c-bd39-54ce01dfa63f 300Gi RWO openebs-hostpath 29m
persistentvolumeclaim/data-redis-0 Bound pvc-a8e4445c-c6b5-483b-8b18-9d650daf35cc 2Gi RWO openebs-hostpath 29m
persistentvolumeclaim/app-backend Bound pvc-2b2f9747-a020-4a16-9975-2491457c4032 10Gi RWO openebs-hostpath 29m