目录

kubernetes进阶-集群备份-velero

kubernetes 集群迁移,备份还原神器 velero .

动机

因某种原因,需要对业务 k8s 集群进行迁移,迁移过程中,需要对以下场景进行测试:

  • 在迁移过程中利用 velero 对 pv/pvc 对 storageClass 字段内容进行变更,数据是否完整。

  • velero 对 pv/pvc 卷进行排除迁移(即不迁移这些卷的数据)。

  • 迁移后业务应用是否正常。

环境

  • Velero 版本:1.11.1

  • backup 集群:

    3 master 3 worker 节点,vke 1.24 版本(csi类型:PTESSD)

  • restore 集群:

    3 master 3 worker 节点,vke 1.24 版本(csi类型:ESSD)

  • backup 集群做备份,到 restore 集群进行还原。

  • 因为我们的场景是私有云,不可以使用云盘快照等功能,因此需要借助 restic 对文件系统进行备份还原,以下都是基于 restic 功能的介绍。

前置准备

两个集群都要准备 ak/sk ,并写入 credentials-velero 文件。

1
2
3
4
5
cat credentials-velero 

[default] 
aws_access_key_id=AKLTNDk5NWMwNjBjOTUxNGQ4ZDg2YzIwMGZlNz...
aws_secret_access_key=WkRjNU5UWTNZamcwWW1WbE5EQTFOemcyTUdRell6WXpNV0...

安装 velero 到 backup/restore 集群,用下面同一份安装命令即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
velero install \
        --use-node-agent \
        --provider aws \
        --plugins velero/velero-plugin-for-aws:v1.8.2 \
        --bucket hwh-velero-repo \
        --secret-file ./credentials-velero \
        --uploader-type restic \
        --default-volumes-to-fs-backup \
        --backup-location-config region=cn-guangzhou-swd,s3ForcePathStyle="false",s3Url=https://tos-s3.miracle.ac.cn \
        --use-volume-snapshots=false

检查是否安装完成。

1
2
3
4
kubectl logs deployment/velero -n velero

Defaulted container "velero" out of: velero, velero-velero-plugin-for-aws (init)
Error from server (BadRequest): container "velero" in pod "velero-5bf88458ff-95knw" is waiting to start: PodInitializing

检查 pod 状态

1
2
3
4
5
6
kubectl get pod -n velero
NAME                      READY   STATUS    RESTARTS   AGE
node-agent-4bjz7          1/1     Running   0          3m55s
node-agent-fk22l          1/1     Running   0          3m55s
node-agent-jgrkk          1/1     Running   0          3m55s
velero-5bf88458ff-95knw   1/1     Running   0          3m55s

测试数据

在 backup vke 集群里面启动一个 busybox 的 pod ,并挂载 ssd 云盘,里面有一个 data.csv 文件。

md5 校验和:

48ed7a0e989dae4e3d795cfd9e5aff39 data.csv。

d8784feca171cd5c9bfb759289f02459 testdata.rar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
kubectl exec -it hwh-busybox-699d99c959-jngf4 -n hwh -- sh

/ # cd /opt/data/
/opt/data # ls
data.csv    lost+found
/opt/data #  md5sum data.csv 
48ed7a0e989dae4e3d795cfd9e5aff39  data.csv

kubectl exec -it hwh-busybox-tos-9f68fbc78-qr6vv -n hwh -- sh

/ # cd /opt/data/
/opt/data # ls
data.txt      testdata.rar
/opt/data # md5sum testdata.rar 
d8784feca171cd5c9bfb759289f02459  testdata.rar

过程

备份过程业务服务是否需要暂停,需要跟业务侧确定,需要暂停则需要将服务的 pod 数量设置为 0 .

正常的备份还原

backup集群执行备份:

1
2
3
4
5

velero backup create demo-1

Backup request "demo-1" submitted successfully.
Run `velero backup describe demo-1` or `velero backup logs demo-1` for more details.

检查备份过程:

1
2
3
velero backup describe demo-1

# 备份完成后,Phase 字段的值是 Completed

如果备份过程出现异常,查看日志:

1
velero backup logs demo-1

restore集群执行还原:

1
velero restore create --from-backup demo-1

查看备份过程:

1
2
3
4
5
6
# 查看何时完成
# 还原完成后,Phase 字段的值是 Completed
velero restore describe demo-1-20240108165612

# 查看还原的卷的信息
kubectl -n velero get podvolumerestores -l velero.io/restore-name=demo-1-20240108165612 -o yaml

storageClass 变更

有时候,我们可能会在还原的集群上确实某个 backup 集群没有的 storageClass ,我们可以通过配置 configmap 来做一层映射,将数据在 restore 集群上的另一个 storageClass 上创建 pvc 来存储。

比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: ConfigMap
metadata:
  name: change-storage-class-config
  namespace: velero
  labels:
    velero.io/plugin-config: ""
    velero.io/change-storage-class: RestoreItemAction
data:
  ebs-ssd: ebs-essd

然后对里面的文件做 MD5 校验,值不变则说明数据完整。

持久化卷过滤

还有另外一情况,我们使用的 pv/pvc 使用的是 oss 或者 nas ,里面的文件比较大比较多,我们不希望他备份到 oss 再同步回来,而是希望备份的过程中,不拷贝这些文件,然后在还原的时候,重新挂载到对应的远程存储的相同目录,来实现快速迁移。注意:这种情况只适用于 restic 类型的备份模式。我们在安装的时候已经指明 --uploader-type restic--default-volumes-to-fs-backup 了。

我们可以先通过给 pod 打 annotate 声明哪个卷不需要备份。

1
kubectl -n hwh annotate pod/hwh-busybox-tos-9f68fbc78-qr6vv backup.velero.io/backup-volumes-excludes=data

然后再进行备份,还原即可。

测试结果

迁移后对文件进行校验。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl exec -it -n hwh hwh-busybox-699d99c959-jngf4 -- sh
Defaulted container "busybox" out of: busybox, restore-wait (init)
/ # 
/ # cd /opt/data/
/opt/data # ls
data.csv    lost+found
/opt/data # md5sum data.csv 
48ed7a0e989dae4e3d795cfd9e5aff39  data.csv

/opt/data # cat data.csv |wc -l
16

数据完整。

我们在 pod 里面存入一个 400+M 的文件,并确定一下 MD5 的值。

backup集群:

1
2
3
4
5
6
7
kubectl exec -it hwh-busybox-tos-9f68fbc78-qr6vv -n hwh -- sh

/ # cd /opt/data/
/opt/data # ls
data.txt      testdata.rar
/opt/data # md5sum testdata.rar 
d8784feca171cd5c9bfb759289f02459  testdata.rar

restore集群:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl exec -it -n hwh hwh-busybox-tos-9f68fbc78-qr6vv -- sh

/ # cd /opt/data/
/opt/data # ls
data.txt      testdata.rar
/opt/data # md5sum testdata.rar 
d8784feca171cd5c9bfb759289f02459  testdata.rar
/opt/data # du -sh *
512     data.txt
458.3M  testdata.rar

数据完整。

冻结/解冻文件系统

如果文件系统频繁写入数据,需要临时不给写入,可以用 fsfreeze 命令来临时将文件系统设置为只读,等备份完以后解冻。

1
2
3
4
5
kubectl annotate pod -n plosp -l app=solr-knowlege-plosp \
    pre.hook.backup.velero.io/command='["/sbin/fsfreeze", "--freeze", "/opt/solr/server/solr/mycores"]' \
    pre.hook.backup.velero.io/container=c0 \
    post.hook.backup.velero.io/command='["/sbin/fsfreeze", "--unfreeze", "/opt/solr/server/solr/mycores"]' \
    post.hook.backup.velero.io/container=c0

container 字段:要冻结文件系统的 pod 里面的容器名。

其他实用功能:

  • pvc annotation 在 restore 逻辑的时候,进行清空。目的:由于之前使用的 glusterfs,pvc annotation 做有相关的关联,因此 pvc 的 annotation 在备份的时候需要被清空,然后由 sc 再次提供。

  • 对 pvc 中的 resources.requests 判断,由于 iaas 侧的 PTSSD 创建云硬盘最低 20G 起步,因此之前旧的 PVC 低于 20G 的时候,自动设置为 20Gi。

  • 基于 image 的映射,通过在 configmap 中指定,key 为 oldRepo,value 为 newRepo。configmap 的命名规则为 “change-” + namespace + “-image-registry”。

总结

  1. 总体相当简单易用,不过需要注意集群版本和 velero 对应的版本关系,不然可能出现备份或还原后,很容易出现操作已经完成了,但状态卡在 InProgress 中。

  2. 但是如果文件系统的文件数量比较庞大,或者总体体积比较大,备份就会经常失败,比如我们的场景下是 80GB 以上的文件系统经常备份失败,原因就是前面提到的 2 种情况。

  3. 所以为了解决文件系统比较庞大而导致的备份失败,我们选择了用 rsync 去做对拷。