Kubernetes 備份,災難復原之 Velero 篇

Jan 17, 2023 TK Huang

Photo by Alvaro Reyes on Unsplash

Photo by Siyuan Hu on Unsplash

Kubernetes (K8s)近年來在全球被企業的接受度不斷地在上升,越來越多企業選擇使用 K8s 來部署服務,相關的 Open Source Project 也是不斷的冒出,甚至連 Virtual Machine (VM) 都開始想在 K8s 上管理,相關內容可參考 Gemini 的文章“在 K8S 上也能跑 VM!KubeVirt 簡介與建立(上)”。

Why backup?

服務的備份一直都是我們需要面對的課題,在生產環境上我們總是會遇到一些不可控因素,或是一些意外的操作,亦或是程式有嚴重的 Bug 導致服務停擺的狀況發生,當集群龐大或是部署的服務很多的情況下,有時候真的很難快速抓出問題所在。甚至集群設定已經被搗亂的情況下,我們也不記得原本的設定是什麼,這時候備份就很重要了,如果有備份檔案我們就可以輕易的恢復到正常的集群狀態。

什麼東西需要備份?

K8s 使用 Controller pattern 管理集群狀態,使用者只要指定期望的對象狀態,K8s Controller 再透過與 API Server 溝通協作,讓集群最終達到使用者的期望狀態。那麼我們需要備份的東西就很明顯了,就是存放了對象狀態的儲存體。

所以我們最少需要備份以下兩樣資料

  1. etcd : etcd 在 K8s 是一個非常重要的元件,用於儲存集群的網路配置以及對象的狀態訊息,可以說還原了 etcd 儲存資料,就等於還原了 K8s 集群狀態。
  2. Persistent Volume(PV) : 雖然 etcd 還原了 K8s 集群狀態,但是 PV 的內容卻不是 K8s 集群狀態的一部分(例如 database 裡的資料,也可以說 Container 內的資料跟集群狀態無關),所以除了 etcd 以外,我們還需要備份 Persistent Volume content。

Velero

Velero is an open source tool to safely backup and restore, perform disaster recovery, and migrate Kubernetes cluster resources and persistent volumes.

Velero 可以用來對 K8s 進行備份還原,從官網主頁我們就可以看到大大的三個主要目標

架構

Velero 實作了自己的 Custom Resource Definition (CRD),透過 Velero Controller 進行備份、還原等動作。

從上面官方架構圖可以知道,使用者操作 Velero 進行備份會發生什麼事

  1. 使用者透過 velero CLI 的 backup 指令在 K8s 集群建立一個 Backup object
  2. BackupController 監聽到此事件後,對此進行驗證
  3. BackupController 會向 API Server 查詢,並備份目標資源
  4. BackupController 最後會將備份好的資源上傳到指定的 Object Storage Service

備份

Velero 會將 K8s 集群的對象資源備份好上傳到指定的 S3 儲存空間,這邊一般來說沒有需要特別調整的地方,重點會在於 Persistent Volume。

Persisten Volume 儲存的資料大多是持續在寫入讀取的,而如果我們要備份這些資料的話,可能需要注意會不會有資料一至性問題。Velero 提供以下兩種方式做備份。

  1. Volume snapshot:直接使用 storage provider 的 snapshot 功能對資料進行快照,如果你的 PV 對資料一至性會有疑慮的話,建議採用此種方式,公有雲提供的 block storage 如 EBS、Google Compute Engine Disks、Azure Managed Disks 等等都有。
  2. Restic:算是比較萬用的方案,Restic 本身是一個支援多系統的備份還原工具,Velero 可以選擇使用 Restic 對 Persistent Volume 進行備份,不過如前面所述,因為不是採用 snapshot 技術,如果資料有一至性的疑慮,建議還是採用有支援 Snapshot 的 block storage,如果真的沒有的話,也是沒關係,Velero 提供了 Backup Hooks,你可以在備份前對資料進行凍結,結束後解凍存取就好。

還原

Velero 在還原的時候支援一些特殊操作,讓你可以更改還原的行為

  1. 復原到指定的 namespace
  2. 保存 service 的 NodePort
  3. 改變 PV/PVC 的 StorageClass

同時也跟備份一樣可以支援多種 hooks

  1. InitContainer Restore Hooks
  2. Exec Restore Hooks

以下就來嘗試備份整座 K8s,以及一個 nginx server

準備好一座 k8s,安裝一下 hostpath csi,並且部署上 nginx server

$ export KUBECONFIG=<kubeconfig>
$ git clone https://github.com/kubernetes-csi/csi-driver-host-path.git

# 安裝 csi driver
$ ./csi-driver-host-path/deploy/kubernetes-latest/deploy.sh
# 建立一個 hostpath storage class
$ kubectl apply -f csi-driver-host-path/examples/csi-storageclass.yaml

等待安裝好後,應該可以看到 hostpathplugin 已經 ready

storage class 也已經建立好

接下來就部署上 nginx server,並且用 csi-hostpah-sc 掛載一個 PV 用來存 Log

cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-example
  labels:
    app: nginx

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-logs-hostpath
  namespace: nginx-example
  labels:
    app: nginx
spec:
  # Optional:
  storageClassName: csi-hostpath-sc
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-hostpath
  namespace: nginx-example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
        - name: nginx-logs
          persistentVolumeClaim:
           claimName: nginx-logs-hostpath
      containers:
      - image: nginx:1.17.6
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
          - mountPath: "/var/log/nginx"
            name: nginx-logs
            readOnly: false
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: my-nginx
  namespace: nginx-example
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer
EOF

nginx 已經起來,並且跑在了 31145 port 上

裡面我們可以看到已經有兩筆 log,2023/01/09 08:49:40 有一個 GET 請求

現在就來安裝 velero 並且把整座 k8s 都進行備份

首先我們需要一個 S3 Server 作為備份地點,我們可以先用 minio 在本地建立一個

$ docker run -p 9000:9000 -p 9001:9001 -d -v $PWD/data:/data quay.io/minio/minio server /data --console-address ":9001"

使用 minioadmin:minioadmin 登入

建立一組 Access Key

然後建立一個 credentials-minio,填入 AccessKey SecretKey

[default]
aws_access_key_id=<accessKey>
aws_secret_access_key=<secretKey>
# install velero on k8s
$ velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.5.1 \
--bucket velero \
--secret-file ./credentials-minio \.
--use-restic \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://<minio ip>:9000 \
--use-volume-snapshots=false \
--default-volumes-to-restic

這邊有幾個重點

  1. provider : 我們使用的是與 AWS S3 兼容的 minio,所以可以直接使用 AWS 的 Plugin。
  2. use-restic : 指定我們要使用 restic 進行備份。
  3. use-volume-snapshots : 因為我們 PV 使用的 Block Storage 沒有支援 snapshots,Velero 預設在安裝時會要你輸入 Snapshot location,我們可以給他 false 值,就可以不用輸入。
  4. default-volumes-to-restic : 指定預設使用 restic,否則備份的時候需要多下參數告訴 velero 要使用 restic 備份。

一切準備就緒,現在來把整座 K8s cluster 都備份起來

$ velero backup create backup1

$ velero backup get
NAME      STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
backup1   Completed   0        0          2023-01-09 17:24:11 +0800 CST   28d       default            <none>

透過 backup get,我們可以看到 backup1 已經 Completed,我們可以 describe 它看看內容

$ velero backup describe backup1

Name:         backup1
Namespace:    velero
Labels:       velero.io/storage-location=default
Annotations:  velero.io/source-cluster-k8s-gitversion=v1.21.6
              velero.io/source-cluster-k8s-major-version=1
              velero.io/source-cluster-k8s-minor-version=21

Phase:  Completed

Errors:    0
Warnings:  0

....
....
....

Total items to be backed up:  460
Items backed up:              460

Velero-Native Snapshots: <none included>

Restic Backups (specify --details for more information):
  Completed:  4

備份了460個項目,並且沒有 Error 跟 Warning,看起來很順利

現在可以把 nginx 整個都刪掉,這邊直接刪除 namespace

$ kubectl delete ns nginx-example

$ kubectl get ns
NAME              STATUS   AGE
default           Active   44h
kube-node-lease   Active   44h
kube-public       Active   44h
kube-system       Active   44h
velero            Active   42h

$ kubectl get pod -n nginx-example
No resources found in nginx-example namespace.

$ kubectl get pv
No resources found

nginx 已經刪除了,PV 也已經消失

現在可以用 velero 來回復看看,加上 –preserve-nodeports 可以讓 service 在回復的時候保留原本的 nodeport。

$ velero restore create --from-backup backup1 --preserve-nodeports

$ velero restore get
NAME                     BACKUP    STATUS       STARTED                         COMPLETED   ERRORS   WARNINGS   CREATED                         SELECTOR
backup1-20230111120955   backup1   InProgress   2023-01-11 11:57:09 +0800 CST   <nil>       0        0          2023-01-11 11:57:09 +0800 CST   <none>

一樣我們來看一下詳細內容

$ velero restore describe backup1-20230111120955
Name:         backup1-20230111120955
Namespace:    velero
Labels:       <none>
Annotations:  <none>

Phase:                       Completed
Total items to be restored:  426
Items restored:              426
...
...
...

restore 了426個項目,看起來沒什麼問題

$ kubectl get svc -n nginx-example
NAME       TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
my-nginx   LoadBalancer   10.233.37.73   <pending>     80:31145/TCP   3m3s

port 保留了 31445,通過原本的 port 可以再次訪問沒有問題

access.log 也已經恢復,可以看到最初的兩個 log

到這邊就已經完成了備份+還原的操作,感覺還是挺方便的

心得

Velero 操作起來不會太複雜,使用上也很輕量,搭配上 restic 的話更是支援絕大多數的平台,雖然上面沒有演示到,但是 velero 還可以做到 cluster migration 的操作,只需要準備一座新的 K8s 並且安裝好 velero 後,restore 過去即可。

雖然 Velero 幫我們降低了 K8s cluster 備份的複雜度,但是其中也是有不少限制,在官方網站也都可以看到,建議使用者要用之前詳閱官方文件,確認功能及限制能否滿足自己的需求。

雙子星雲端為 CNCF 會員,是 CNCF 所認證的 Kubernetes 服務提供商,在雲端技術擁有十多年以上的經驗,為台灣雲端技術早期領先者。目前為國家級 AI 雲的軟體及 Kubernetes 技術與服務提供商,更是諸多企業與單位導入容器與管理平台的最佳夥伴。

雙子星雲端已於近期推出 Kubernetes 管理平台 — GOC Nomos,可搭配既有的產品 AI ConsoleGOC API Gateway ,也提供企業諮詢與導入雲原生 Kubernetes、CI/CD 導入等相關技術服務,協助企業擁抱 Cloud Native,達到數位轉型的目標。


相關文章

回雙子星技術部落格列表

Gemini AI Console

熱門文章


kubernetes professional service

關於我們

雙子星雲端是混合多雲技術的領導者,是國際認證之 KCSP - Kubernetes 服務提供商,同時也為 CNCF 雲原生計算基金會會員。

雙子星的雲端專家擁有 Kubernetes、OpenStack 與 Google Cloud Platform 等多項證照,我們的軟體至今已為上百家機構和數千台的 CPU/GPU 伺服器提供雲端服務。