Velero備份恢復阿里雲容器服務ACK
1. 前言
不管是在傳統IT還是新興的雲計算場景下,對業務系統進行例行的備份都是一個非常重要的環節,本文將着重介紹如何使用開源工具velero給阿里雲上的ACK k8s集羣進行例行備份,以及如何恢復,該方案可以作爲ACK用戶日常運維的一個重要環節。
velero可以幫助我們:
- 災備場景,提供備份恢復k8s集羣的能力
- 遷移場景,提供拷貝集羣資源到其他集羣的能力(複製同步開發,測試,生產環境的集羣配置,簡化環境配置)
2. 環境準備
- 部署ACK kubernetes集羣,我們首先在阿里雲張家口region創建了一個k8s集羣
- 創建OSS Bucket,在張家口region創建一個OSS bucket用於velero備份
- 下載安裝官方velero客戶端(https://github.com/heptio/velero)
- 安裝velero ACK plugin(https://github.com/AliyunContainerService/velero-plugin)
velero包含有一個客戶端一個服務端,服務端以velero ACK plugin方式部署在k8s集羣中(詳見github說明),客戶端需部署在一個已配置好kubectl及集羣kubeconfig的機器上。
3. 災備恢復場景
3.1 本集羣
這裏,我們將使用velero備份一個集羣內相關的resource,並在當該集羣出現一些故障或誤操作的時候,能夠快速恢復集羣resource, 首先我們用下面的yaml來部署:
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-example
labels:
app: nginx
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx-example
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80
---
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
3.1.1 備份
我們可以全量備份,也可以只備份需要備份的一個namespace,本處只備份一個namespace:nginx-example
velero backup create nginx-example-backup --include-namespaces nginx-example
Backup request "nginx-example-backup" submitted successfully.
Run `velero backup describe nginx-example-backup` or `velero backup logs nginx-example-backup` for more details.
我們先記錄下當前namespace下的資源情況
# namespace nginx-example仍然存在
kubectl get ns
NAME STATUS AGE
default Active 2d22h
kube-public Active 2d22h
kube-system Active 2d22h
nginx-example Active 8m34s
velero Active 120m
# nginx-example下面pod的相關信息
kubectl get po -n nginx-example -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-deployment-5c689d88bb-855h8 1/1 Running 0 2m31s 172.20.0.114 cn-zhangjiakou.192.168.1.144 <none>
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 2m31s 172.20.0.115 cn-zhangjiakou.192.168.1.144 <none>
# nginx-example下面deployment的相關信息
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deployment 2 2 2 2 5m2s nginx nginx:1.7.9 app=nginx
# nginx-example下面service的相關信息
kubectl get svc -n nginx-example -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
my-nginx LoadBalancer 172.21.9.159 47.92.44.156 80:32088/TCP 6m36s app=nginx
現在我們模擬一次誤操作導致namespace nginx-example被誤刪
kubectl delete namespaces nginx-example
3.1.2 恢復
使用velero restore命令來恢復之前的備份
velero restore create --from-backup nginx-example-backup
Restore request "nginx-example-backup-20190523200227" submitted successfully.
Run `velero restore describe nginx-example-backup-20190523200227` or `velero restore logs nginx-example-backup-20190523200227` for more details.
我們再來檢查下namespace nginx-example及其下面的資源是否被恢復
# 檢查下namespace nginx-example是否已被創建
kubectl get ns
NAME STATUS AGE
default Active 2d22h
kube-public Active 2d22h
kube-system Active 2d22h
nginx-example Active 68s
velero Active 112m
# 檢查下pod
kubectl get po -n nginx-example -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-deployment-5c689d88bb-855h8 1/1 Running 0 3m2s 172.20.0.131 cn-zhangjiakou.192.168.1.145 <none>
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 3m2s 172.20.0.132 cn-zhangjiakou.192.168.1.145 <none>
# nginx-example下面deployment的相關信息
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deployment 2 2 2 2 4m52s nginx nginx:1.7.9 app=nginx
# nginx-example下面service的相關信息
kubectl get svc -n nginx-example -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
my-nginx LoadBalancer 172.21.3.239 39.98.8.5 80:30351/TCP 7m9s app=nginx
可以看到resource name都保持不變,但是相關的ip,nodeport,LB地址等都會重新分配
接下來,我們來做一個實驗,驗證下恢復的形態是什麼樣的:
-
額外部署一個tomcat的deployment
kubectl get deployment -n nginx-example NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 2 2 2 2 3m23s tomcat 2 2 2 2 27s
-
做一次restore,觀察下是否會刪除掉tomcat這個deployment
velero restore create --from-backup nginx-example-backup kubectl get deployment -n nginx-example NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 2 2 2 2 6m32s tomcat 2 2 2 2 3m36s
可以看到,restore的行爲不是覆蓋
-
接下來,我們把最初backup中存在的nginx刪除掉
kubectl delete deployment nginx-deployment -n nginx-example deployment.extensions "nginx-deployment" deleted kubectl get deployment -n nginx-example NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE tomcat 2 2 2 2 6m49s
-
現在再來一次restore,我們知道之前backup中有nginx,沒有tomcat,那restore之後是什麼樣呢?
velero restore create --from-backup nginx-example-backup kubectl get deployment -n nginx-example NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 2 2 2 2 3s tomcat 2 2 2 2 8m33s
-
如果我們現在將nginx的image版本升級成latest,那在restore之後是什麼樣呢?
# 升級nginx的image從1.7.9到latest,並查看當前的image版本 kubectl get deployment -n nginx-example -o wide NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx-deployment 2 2 2 2 2m29s nginx nginx:latest app=nginx tomcat 2 2 2 2 10m tomcat tomcat:latest app=tomcat # restore backup velero restore create --from-backup nginx-example-backup # 再來看下nginx的image版本,並沒有恢復到最初的版本 kubectl get deployment -n nginx-example -o wide NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx-deployment 2 2 2 2 3m15s nginx nginx:latest app=nginx tomcat 2 2 2 2 11m tomcat tomcat:latest app=tomcat
結論:velero恢復不是直接覆蓋,而是會恢復當前集羣中不存在的resource,已有的resource不會回滾到之前的版本,如需要回滾,需在restore之前提前刪除現有的resource。
3.2 跨集羣
我們現在在阿里雲深圳region再新建一個k8s集羣(k8s-sz),接下來,我們將驗證下velero跨region跨集羣恢復k8s資源的能力,我們將把前面給張家口集羣創建的備份恢復到一個新的region
3.2.1 恢復
在velero客戶端機器上,將k8s-sz集羣的kubeconfig信息配置到~/.kube/config
執行如下velero恢復命令進行恢復
velero restore create --from-backup nginx-example-backup
可以看到namespace恢復了
kubectl get ns
NAME STATUS AGE
default Active 18m
kube-public Active 18m
kube-system Active 18m
nginx-example Active 5m20s
velero Active 5m47s
namespace nginx-example下的resource也已恢復
kubectl get po -owide -n nginx-example
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-deployment-5c689d88bb-855h8 1/1 Running 0 10m 172.20.0.133 cn-shenzhen.192.168.1.50 <none>
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 10m 172.20.0.134 cn-shenzhen.192.168.1.50 <none>
3.3 高級備份功能
3.3.1 週期性定時備份
可以設置一個週期性定時備份
velero schedule create <SCHEDULE NAME> --schedule "0 7 * * *"
上面的命令可以以-這樣的命名方式來創建備份對象(restore object)
3.3.2 備份持久數據卷
如需備份恢復持久卷,備份如下:
velero backup create nginx-backup-volume --snapshot-volumes --include-namespaces nginx-example
該備份會在集羣所在region給雲盤創建快照(當前還不支持NAS和OSS存儲),快照恢復雲盤只能在同region完成。
恢復命令如下:
velero restore create --from-backup nginx-backup-volume --restore-volumes
3.4 刪除備份
- 方法一,通過命令直接刪除
velero delete backups default-backup
- 方法二,設置備份自動過期,在創建備份時,加上TTL參數
velero backup create <BACKUP-NAME> --ttl <DURATION>
4. 遷移場景
和災備跨集羣恢復場景類似,velero可以幫助我們把一個k8s集羣的resource導出並導入到另外一個集羣,只要將每個Velero實例指向同一個雲對象存儲位置,Velero就可以幫助我們將資源從一個集羣移植到另一個集羣,請注意,Velero不支持跨雲提供商遷移持久卷。當前使用velero遷移集羣功能最完善的場景是在同一個雲廠商的同一個region,可以恢復集羣的應用和數據卷。
- 在集羣1上做一個備份:
velero backup create <BACKUP-NAME> --snapshot-volumes
- 在集羣2上做一個恢復:
velero restore create --from-backup <BACKUP-NAME> --restore-volumes
5. 總結
velero作爲一個免費的開源組件,其能力基本可以滿足容器服務的災備和遷移的場景,推薦用戶將velero日常備份作爲運維的一部分,未雨綢繆,防患未然。