备份恢复阿里云容器服务ACK

Velero备份恢复阿里云容器服务ACK

1. 前言

不管是在传统IT还是新兴的云计算场景下,对业务系统进行例行的备份都是一个非常重要的环节,本文将着重介绍如何使用开源工具velero给阿里云上的ACK k8s集群进行例行备份,以及如何恢复,该方案可以作为ACK用户日常运维的一个重要环节。

velero可以帮助我们:

  • 灾备场景,提供备份恢复k8s集群的能力
  • 迁移场景,提供拷贝集群资源到其他集群的能力(复制同步开发,测试,生产环境的集群配置,简化环境配置)

2. 环境准备

  1. 部署ACK kubernetes集群,我们首先在阿里云张家口region创建了一个k8s集群
  2. 创建OSS Bucket,在张家口region创建一个OSS bucket用于velero备份
  3. 下载安装官方velero客户端(https://github.com/heptio/velero
  4. 安装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地址等都会重新分配

接下来,我们来做一个实验,验证下恢复的形态是什么样的:

  1. 额外部署一个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
  2. 做一次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的行为不是覆盖

  1. 接下来,我们把最初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
  1. 现在再来一次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
  2. 如果我们现在将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 删除备份

  1. 方法一,通过命令直接删除
velero delete backups default-backup
  1. 方法二,设置备份自动过期,在创建备份时,加上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日常备份作为运维的一部分,未雨绸缪,防患未然。

上一篇:阿里云ACK简介及入门实践


下一篇:【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 四 | View 事件传递机制 )(一)