Velero备份恢复阿里云容器服务ACK:完整实践指南
对企业级业务系统进行定期备份,在传统IT时代是刚需,进入云计算时代依然如此。今天我们来详细探讨如何借助开源工具Velero,为阿里云上的ACK Kubernetes集群构建一套稳定可靠的日常备份与恢复方案。这套方法一旦落地,完全可以纳入日常运维的“标准动作”流程,帮助团队从容应对数据安全与业务连续性挑战。

先说说Velero的核心能力。从宏观角度看,它主要解决两件大事:第一是灾备——当集群出现故障或遭遇误操作时,能够快速将关键资源“捞回来”;第二是迁移——将一套集群的资源完整复制到另一套集群,开发、测试、生产环境的配置可以轻松同步,无需一遍遍手动重复操作,极大提升效率。
环境准备:搭建Velero备份基础
动手之前,先把基础环境搭建好。本次实验我们在阿里云张家口Region创建了一个ACK集群,同时在同一Region新建了一个OSS Bucket,专门用于存放备份数据。接着下载官方Velero客户端,并安装Velero的ACK专用插件。
Velero的整体架构十分清晰:一个客户端加一个服务端。服务端以ACK插件的形式运行在K8s集群中,客户端则部署在已配置好kubectl和集群kubeconfig的机器上。关于插件具体的安装步骤,GitHub官方文档写得非常详细,这里就不再重复展开了。
灾备恢复场景实战
本集群恢复:模拟误删与快速还原
先看一个最基础的操作:在同一集群中,先备份一些资源,然后模拟一次误删除,再通过备份恢复回来。下面我们直接用一组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
执行备份
备份操作可以全量进行,也可以只备份指定的namespace。这里我们仅备份nginx-example这个namespace:
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 状态
kubectl get ns
NAME STATUS AGE
default Active 2d22h
kube-public Active 2d22h
kube-system Active 2d22h
nginx-example Active 8m34s
velero Active 120m
# 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
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 2m31s 172.20.0.115 cn-zhangjiakou.192.168.1.144
# deployment 信息
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deployment 2 2 2 2 5m2s nginx nginx:1.7.9 app=nginx
# 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
好,现在模拟一次“手滑”——误删nginx-example这个namespace:
kubectl delete namespaces nginx-example
执行恢复
使用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及其下资源是否全部复原:
# namespace 已恢复
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
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 3m2s 172.20.0.132 cn-zhangjiakou.192.168.1.145
# deployment 恢复
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deployment 2 2 2 2 4m52s nginx nginx:1.7.9 app=nginx
# service 恢复,注意IP地址变了
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
可以看到,资源名称均保持不变,但Pod的IP、NodePort、LoadBalancer地址这些动态分配的内容,恢复后会重新分配。这是符合预期的表现。
接下来,我们再做一组实验,验证Velero恢复逻辑的本质——到底是“覆盖”还是“增量补齐”?
先额外部署一个Tomcat的Deployment:
kubectl get deployment -n nginx-example
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE AGE
nginx-deployment 2 2 2 2 3m23s
tomcat 2 2 2 2 27s
然后执行一次恢复,观察Tomcat是否会被删除:
velero restore create --from-backup nginx-example-backup
kubectl get deployment -n nginx-example
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE AGE
nginx-deployment 2 2 2 2 6m32s
tomcat 2 2 2 2 3m36s
Tomcat依然存在。这说明恢复不是“覆盖”,而是“缺什么补什么”。
那如果反过来做呢?先删除备份中已有的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 A VAILABLE AGE
tomcat 2 2 2 2 6m49s
再次执行恢复:
velero restore create --from-backup nginx-example-backup
kubectl get deployment -n nginx-example
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE AGE
nginx-deployment 2 2 2 2 3s
tomcat 2 2 2 2 8m33s
Nginx回来了,Tomcat也未被丢失。还是同样的逻辑:补充缺失资源,不动已有资源。
最后一个测试场景:如果Nginx已经在运行,但我们把它的镜像从1.7.9修改成了latest,再执行恢复会发生什么?
# 升级镜像
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE 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
# 执行恢复
velero restore create --from-backup nginx-example-backup
# 检查镜像版本
kubectl get deployment -n nginx-example -o wide
NAME DESIRED CURRENT UP-TO-DATE A VAILABLE 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
镜像版本仍然保持为latest,没有回滚到1.7.9。结论非常明确:
Velero的恢复操作不是覆盖,而是补齐当前集群中“缺失”的资源。已经存在的资源不会自动回滚到备份版本。如果你需要回滚到备份状态,必须先手动删除现有资源,然后再执行恢复。
跨集群恢复:轻松应对多Region场景
跨集群恢复的应用场景其实更为实用。例如,你在张家口Region有一套集群,现在要求在深圳Region新建一套集群,并希望将之前的备份恢复到新集群中。
我们在深圳Region新建了一个ACK集群(k8s-sz),然后将Velero客户端的kubeconfig切换到新集群的配置,直接执行恢复命令:
velero restore create --from-backup nginx-example-backup
检查恢复效果:
kubectl get ns
NAME STATUS AGE
default Active 18m
kube-public Active 18m
kube-system Active 18m
nginx-example Active 5m20s
velero Active 5m47s
kubectl get po -o wide -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
nginx-deployment-5c689d88bb-k5j9z 1/1 Running 0 10m 172.20.0.134 cn-shenzhen.192.168.1.50
Namespace和Pod都已成功恢复。跨Region跨集群的恢复操作,就这么简单高效。
高级备份功能:提升运维自动化水平
定时备份:告别手动操作
日常运维不能总依赖手动执行。Velero支持按照Cron表达式设置定时备份,例如每天早上7点自动执行一次:
velero schedule create --schedule "0 7 * * *"
备份对象会自动按命名规则生成,运维人员无需频繁手动触发,非常省心。
备份持久数据卷:保护有状态应用
如果需要备份持久卷(PVC),只需加上--snapshot-volumes参数即可:
velero backup create nginx-backup-volume --snapshot-volumes --include-namespaces nginx-example
此备份操作会在集群所在Region为云盘创建快照。特别注意:当前版本不支持NAS和OSS存储类型的快照;而且快照恢复云盘只能在同Region内完成。恢复时加上--restore-volumes参数:
velero restore create --from-backup nginx-backup-volume --restore-volumes
删除备份:规范备份生命周期管理
备份管理同样至关重要。删除备份有两种方式:一是通过命令行直接删除:
velero delete backups default-backup
二是在创建备份时设置TTL(生存时间),让备份自动过期:
velero backup create --ttl
迁移场景:实现资源无缝移植
资源迁移与灾备中的跨集群恢复思路基本一致。只要让源集群和目标集群的Velero实例都指向同一个OSS Bucket,就能轻松实现资源移植。但有一点需要注意——Velero目前不支持跨云厂商的持久卷迁移。当前最成熟、最稳定的应用场景,是在同一个云厂商的同一Region内,完成应用和数据卷的完整迁移。
操作方式非常直接。在源集群上执行备份:
velero backup create --snapshot-volumes
然后在目标集群上执行恢复:
velero restore create --from-backup --restore-volumes
总结:Velero——给你的ACK集群上道“保险”
Velero作为一个免费开源组件,其能力基本覆盖了容器服务的灾备和迁移需求。毫不夸张地说,将其纳入日常运维流程,相当于给集群上了一道可靠的“保险”。未雨绸缪,远胜于问题出现后再手忙脚乱地补救。现在就开始为你的阿里云容器服务ACK配置Velero吧!
