摘要:近日正好有 k8s 集羣服務遷移服務的需求,使用 Velero 完成了服務的遷移,同時也每日進行集羣資源備份,其能力可以滿足容器服務的災備和遷移場景,實測可用,現已運行在所有的 k8s 集羣。Velero 將集羣資源保存在對象存儲中,默認情況下可以使用 AWS 、 Azure 、 GCP 的對象存儲,同時也給出了插件功能用來拓展其他平臺的存儲,這裏我們用到的就是阿里雲的對象存儲 OSS,阿里雲也提供了 Velero 的插件,用於將備份存儲到 OSS 中。

前言

在近日的一個風和日麗的下午,正在快樂的寫 bug 時,突然間釘釘就被 call 爆了,原來是 k8s 測試集羣的一個 namespace 突然不見了。這個 namespace 裏面有 60 多個服務,瞬間全部沒有了……雖然得益於我們的 CI/CD 系統,這些服務很快都重新部署並正常運行了,但是如果在生產環境,那後果就是不可想象的了。在排查這個問題發生的原因的同時,集羣資源的災備和恢復功能就提上日程了,這時 Velero 就出現了。

Velero

Velero 是 VMWare 開源的 k8s 集羣備份、遷移工具。可以幫助我們完成 k8s 的例行備份工作,以便在出現上面問題的時候可以快速進行恢復。同時也提供了集羣遷移功能,可以將 k8s 資源遷移到其他 k8s 集羣的功能。Velero 將集羣資源保存在對象存儲中,默認情況下可以使用 AWSAzureGCP 的對象存儲,同時也給出了插件功能用來拓展其他平臺的存儲,這裏我們用到的就是阿里雲的對象存儲 OSS,阿里雲也提供了 Velero 的插件,用於將備份存儲到 OSS 中。下面我就介紹一下如何在阿里雲容器服務 ACK 使用 Velero 完成備份和遷移。

Velero 地址: https://github.com/vmware-tanzu/velero

ACK 插件地址: https://github.com/AliyunContainerService/velero-plugin

下載 Velero 客戶端

Velero 由客戶端和服務端組成,服務器部署在目標 k8s 集羣上,而客戶端則是運行在本地的命令行工具。

  • 前往 Velero 的 Release 頁面 下載客戶端,直接在 GitHub 上下載即可
  • 解壓 release 包
  • 將 release 包中的二進制文件 velero 移動到 $PATH 中的某個目錄下
  • 執行 velero -h 測試

創建 OSS bucket

創建一個 OSS bucket 用於存儲備份文件,這裏也可以用已有的 bucket,之後會在 bucket 中創建 backupsmetadatarestores 三個目錄,這裏建議在已有的 bucket 中創建一個子目錄用於存儲備份文件。

創建 OSS 的時候一定要選對區域,要和 ACK 集羣在同一個區域,存儲類型和讀寫權限選擇 標準存儲私有

創建阿里雲 RAM 用戶

這裏需要創建一個阿里雲 RAM 的用戶,用於操作 OSS 以及 ACK 資源。

  • 新建權限策略

    策略內容:

    {
        "Version": "1",
        "Statement": [
            {
                "Action": [
                    "ecs:DescribeSnapshots",
                    "ecs:CreateSnapshot",
                    "ecs:DeleteSnapshot",
                    "ecs:DescribeDisks",
                    "ecs:CreateDisk",
                    "ecs:Addtags",
                    "oss:PutObject",
                    "oss:GetObject",
                    "oss:DeleteObject",
                    "oss:GetBucket",
                    "oss:ListObjects"
                ],
                "Resource": [
                    "*"
                ],
                "Effect": "Allow"
            }
        ]
    }
  • 新建用戶

    在新建用戶的時候要選擇 編程訪問 ,來獲取 AccessKeyIDAccessKeySecret ,這裏請創建一個新用於用於備份,不要使用老用戶的 AK 和 AS。

部署服務端

  • 拉取 Velero 插件 到本地

    git clone https://github.com/AliyunContainerService/velero-plugin
  • 配置修改

    1. 修改 install/credentials-velero 文件,將新建用戶中獲得的 AccessKeyIDAccessKeySecret 填入,這裏的 OSS EndPoint 爲之前 OSS 的訪問域名( 注:這裏需要選擇外網訪問的 EndPoint。 ):

      ALIBABA_CLOUD_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
      ALIBABA_CLOUD_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
      ALIBABA_CLOUD_OSS_ENDPOINT=<ALIBABA_CLOUD_OSS_ENDPOINT>
    2. 修改 install/01-velero.yaml ,將 OSS 配置填入:

      ---
      apiVersion: velero.io/v1
      kind: BackupStorageLocation
      metadata:
      labels:
          component: velero
      name: default
      namespace: velero
      spec:
      config: {}
      objectStorage:
          bucket: <ALIBABA_CLOUD_OSS_BUCKET>  # OSS bucket 名稱
          prefix: <OSS_PREFIX>    # bucket 子目錄
      provider: alibabacloud
      ---
      apiVersion: velero.io/v1
      kind: VolumeSnapshotLocation
      metadata:
      labels:
          component: velero
      name: default
      namespace: velero
      spec:
      config:
          region: <REGION>    # 地域,如果是華東2(上海),則爲 cn-shanghai
      provider: alibabacloud
    3. k8s 部署 Velero 服務

      # 新建 namespace
      kubectl create namespace velero
      # 部署 credentials-velero 的 secret
      kubectl create secret generic cloud-credentials --namespace velero --from-file cloud=install/credentials-velero
      # 部署 CRD
      kubectl apply -f install/00-crds.yaml
      # 部署 Velero
      kubectl apply -f install/01-velero.yaml
    4. 測試 Velero 狀態

      $ velero version
      Client:
          Version: v1.1.0
          Git commit: a357f21aec6b39a8244dd23e469cc4519f1fe608
      Server:
          Version: v1.1.0

      可以看到 Velero 的客戶端和服務端已經部署成功。

    5. 服務端清理

      在完成測試或者需要重新安裝時,執行如下命令進行清理:

      kubectl delete namespace/velero clusterrolebinding/velero
      kubectl delete crds -l component=velero

備份測試

velero-plugin 項目中已經給出 example 用於測試備份。

  • 部署測試服務

    kubectl apply -f examples/base.yaml
  • nginx-example 所在的 namespace 進行備份

    velero backup create nginx-backup --include-namespaces nginx-example --wait
  • 模擬 namespace 被誤刪

    kubectl delete namespaces nginx-example
  • 使用 Velero 進行恢復

    velero restore create --from-backup nginx-backup --wait

集羣遷移

遷移方法同備份,在備份後切換集羣,在新集羣恢復備份即可。

高級用法

  • 定時備份

    對集羣資源進行定時備份,則可在發生意外的情況下,進行恢復(默認情況下,備份保留 30 天)。

    # 每日1點進行備份
    velero create schedule <SCHEDULE NAME> --schedule="0 1 * * *"
    # 每日1點進行備份,備份保留48小時
    velero create schedule <SCHEDULE NAME> --schedule="0 1 * * *" --ttl 48h
    # 每6小時進行一次備份
    velero create schedule <SCHEDULE NAME> --schedule="@every 6h"
    # 每日對 web namespace 進行一次備份
    velero create schedule <SCHEDULE NAME> --schedule="@every 24h" --include-namespaces web

    定時備份的名稱爲: <SCHEDULE NAME>-<TIMESTAMP> ,恢復命令爲: velero restore create --from-backup <SCHEDULE NAME>-<TIMESTAMP>

  • 備份刪除

    直接執行命令進行刪除

    velero delete backups <BACKUP_NAME>
  • 備份資源查看

    備份查看

    velero backup get

    查看定時備份

    velero schedule get

    查看可恢復備份

    velero restore get
  • 備份排除項目

    可爲資源添加指定標籤,添加標籤的資源在備份的時候被排除。

    # 添加標籤
    kubectl label -n <ITEM_NAMESPACE> <RESOURCE>/<NAME> velero.io/exclude-from-backup=true
    # 爲 default namespace 添加標籤
    kubectl label -n default namespace/default velero.io/exclude-from-backup=true

問題彙總

時區問題

進行定時備份時,發現備份使用的事 UTC 時間,並不是本地時間,經過排查後發現是 velero 鏡像的時區問題,在調整後就會正常定時備份了,這裏我重新調整了時區,直接調整鏡像就好,修改 install/01-velero.yaml 文件,將鏡像替換爲 registry-vpc.cn-shanghai.aliyuncs.com/keking/velero:latest

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: velero
  namespace: velero
spec:
  replicas: 1
  selector:
    matchLabels:
      deploy: velero
  template:
    metadata:
      annotations:
        prometheus.io/path: /metrics
        prometheus.io/port: "8085"
        prometheus.io/scrape: "true"
      labels:
        component: velero
        deploy: velero
    spec:
      serviceAccountName: velero
      containers:
      - name: velero
        # sync from gcr.io/heptio-images/velero:latest
        image: registry-vpc.cn-shanghai.aliyuncs.com/keking/velero:latest   # 修復時區後的鏡像
        imagePullPolicy: IfNotPresent
        command:
          - /velero
        args:
          - server
          - --default-volume-snapshot-locations=alibabacloud:default
        env:
          - name: VELERO_SCRATCH_DIR
            value: /scratch
          - name: ALIBABA_CLOUD_CREDENTIALS_FILE
            value: /credentials/cloud
        volumeMounts:
          - mountPath: /plugins
            name: plugins
          - mountPath: /scratch
            name: scratch
          - mountPath: /credentials
            name: cloud-credentials
      initContainers:
      - image: registry.cn-hangzhou.aliyuncs.com/acs/velero-plugin-alibabacloud:v1.2
        imagePullPolicy: IfNotPresent
        name: velero-plugin-alibabacloud
        volumeMounts:
        - mountPath: /target
          name: plugins
      volumes:
        - emptyDir: {}
          name: plugins
        - emptyDir: {}
          name: scratch
        - name: cloud-credentials
          secret:
            secretName: cloud-credentials

版本問題

截止發稿時,Velero 已經發布了 v1.2.0 版本,目前 ACK 的 Velero 的插件還未升級。

結語

近日正好有 k8s 集羣服務遷移服務的需求,使用 Velero 完成了服務的遷移,同時也每日進行集羣資源備份,其能力可以滿足容器服務的災備和遷移場景,實測可用,現已運行在所有的 k8s 集羣。

相關文章