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日常备份作为运维的一部分,未雨绸缪,防患未然。