利用Velero對K8S備份還原與叢集遷移實戰

2023-04-23 12:00:57

一、簡介

Velero 是一款雲原生時代的災難恢復和遷移工具,採用 Go 語言編寫,並在 github 上進行了開源,利用 velero 使用者可以安全的備份、恢復和遷移 Kubernetes 叢集資源和持久卷。

1.1 支援的版本列表

1.2 Velero元件

Velero 元件一共分兩部分,分別是伺服器端和使用者端。

  • 伺服器端:執行在你 Kubernetes 的叢集中
  • 使用者端:是一些執行在原生的命令列的工具,需要已設定好 kubectl 及叢集 kubeconfig 的機器上

1.3 velero備份流程

  1. velero使用者端呼叫kubernetes API Server建立backup任務
  2. Backup控制器基於watch機制通過Api Server獲取到備份任務
  3. Backup控制器開始執行備份動作,會通過請求Api Server獲取到需要備份的資料
  4. Backup 控制器將獲取到的資料備份到指定的物件儲存server端

1.4 Velero後端儲存

Velero支援兩種關於後端儲存的CRD,分別是BackupStorageLocationVolumeSnapshotLocation

1.4.1 BackupStorageLocation

主要用來定義 Kubernetes 叢集資源的資料存放位置,也就是叢集物件資料,不是 PVC 的資料。主要支援的後端儲存是 S3 相容的儲存,比如:Mino 和阿里雲 OSS 等。

1.4.2 VolumeSnapshotLocation

主要用來給 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叢集可以存取到即可。

2.1 準備minio清單

---
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

2.2 建立minio應用

# 建立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登入驗證。

三、安裝velero v1.10.2

版本列表:https://github.com/vmware-tanzu/velero/releases

3.1 安裝velero命令程式

$ 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

3.2 建立金鑰

$ cat > credentials-velero <<EOF
[default]
aws_access_key_id = minio
aws_secret_access_key = minio123
EOF

3.3 安裝velero到k8s叢集

$ 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版本對應關係:

3.4 解除安裝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: 指定快照的位置,也就是哪一個公有云驅動

4.1 備份

4.1.1 使用官方案例建立測試應用
$ 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
4.1.2 備份測試應用
$ 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
4.1.3 檢視備份列表
$ 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控制檯檢視備份內容

4.1.4 定時備份指南
# 使用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

4.2 恢復

4.2.1 模擬災難
# 刪除nginx-example名稱空間和資源
$ kubectl delete namespace nginx-example
# 檢查是否刪除
$ kubectl get all -n nginx-example
No resources found in nginx-example namespace.
4.2.2 恢復資源
$ 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.
4.2.3 檢查恢復的資源
$ 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

五、專案遷移實戰

5.1、專案介紹

我們將使用Velero快速完成雲原生應用PV資料的遷移實踐過程,在本文範例中,我們將A叢集中的一個MOS應用遷移到叢集B中,其中資料備份採用自建Minio物件儲存服務。

5.1.1 環境要求
  1. 遷移專案最好保證兩個Kubernetes叢集版本一致。
  2. 為了保證PV資料成功遷移,兩邊需要安裝好相同名字的StorageClass
  3. 可以自己部署Minio,也可以使用公有云的物件儲存服務,如華為的OBS、阿里的OSS等。
  4. 本案例將叢集A中app-system名稱空間中的服務及PV資料遷移到叢集B中。
5.1.2 專案環境
角色 叢集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
5.1.3 專案說明

我們需要將叢集A中 app-system 空間的所有資源和資料全部遷移到叢集B中,該專案包括了deploymentstatefulsetserviceingressjobcronjobsecretconfigmappvpvc

# 專案清單資訊
$ 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

5.2 準備物件儲存

按照2.12.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

5.3 安裝velero

請確保在叢集A叢集B中已經安裝好velero使用者端,請參考3.1 安裝velero命令程式

5.3.1 在叢集A中安裝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物件儲存。

5.3.2 在叢集B種安裝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

注意:其中S3的地址指向本叢集minio物件儲存的svc地址。

5.4 備份MOS專案

$ 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控制檯上可以看到備份的檔案:

5.5 恢復到叢集B

# 到叢集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>

5.6 驗證服務和資料

$ 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