K8S 集群备份与恢复

为什么

K8S 是软件,软件就会有中间状态和运行数据,K8S 的控制面数据持久化在 etcd 中,etcd 是以键值对 Key/Value 格式存储,并对外提供读写服务,为了防止数据丢失或意外故障,需要定期备份。

同时 K8S 是容器化平台,容器屏蔽了基础设施的复杂性,涵盖了计算、网络、存储、监控日志等多种接口,因此容器运行中的所有数据也需要备份,如 pv 声明的存储数据,网络配置、权限配置、镜像数据等

备份的目的是防止数据永久丢失,同时快速恢复到正常可用,是容灾恢复(DR)的重要手段,ETCD 集群和 K8S 集群一般是高可用部署,单点故障并不会影响集群稳定性,但是用户误操作、升级、集群迁移等操作,仍然需要备份和恢复工具。

是什么

k8s 集群的备份一般是指 etcd 的备份,但因为 etcd 备份是某一时刻的完整数据,无法自定义选择备份哪些内容,且数据除了 etcd 本身,其他程序不可读,因此有很多的局限。另外 pod 使用的存储如 PV 等数据也需要备份,这并不在 etcd 的范畴。

因此出现了很多开源和商业产品来提供 k8s 的备份和恢复解决方案,如:

  • velero: Backup and migrate Kubernetes resources and persistent volumes
  • stash: Backup your Kubernetes Stateful Applications
  • portworx: Portworx solves these challenges and more with cloud native storage and data management built from the ground up for Kubernetes.

基本是为了解决 k8s 的存储迁移问题,而 k8s 在 1.12 版本 也推出了CSI Snapshot,存储的备份操作有了更多可能性,后面会详细说明。

不是什么:

  • 本文不讨论多集群灾备方案,如跨地域、跨可用区或者跨云的多集群热备、冷备、调度
  • 如果 pod 中使用了外部数据库、缓存等产品,备份操作应该在对应的产品操作,如数据库本身的 db 备份,尤其是云上产品。

备份与快照

备份(backup)与快照(snapshot)的作用是很相似的,但有些区别。以云磁盘为例,备份是云硬盘数据在某一时刻的副本,而快照并非是实际的磁盘数据拷贝,不是数据副本。因此快照占用的存储空间较小,且执行速度快。但是如果磁盘物理故障,通过快照回滚是无法恢复出正确的数据的,而备份则可以。

备份的概念更宽泛一点,如果我只想备份某几个文件夹,快照的概念就不太准确了,例如 etcd 备份,在 v2 中命令 etcdctl backup,v3 版本中是 etcdctl snapshot,但其实作用是一样的,即备份某一时刻的 etcd 数据。这里不是玩文字游戏,只是对比后面的 velero 备份,etcd 的快照是某一时刻的数据,没办法备份某一个 namespace 或者某一组 pod。备份的是全部,恢复时也是全部。

物理备份与逻辑备份

备份也可以分为两类,物理备份与逻辑备份

  • 物理备份: 如 mysql 备份、etcd 备份,不区分数据的内在逻辑关系,把数据存储作为一个整体来备份,恢复时也是作为整体恢复,不可能只恢复一部分数据,类似快照的概念。

  • 逻辑备份:按照数据的内在逻辑关系,选择性提取部分数据或全部数据,恢复时可以选择恢复一部分数据。

物理备份的优点是速度快,无论是备份还是回恢复,但缺点是元数据不可读,只能全部恢复。而逻辑备份正好相反,因此两者可以结合使用,既能快,又能有细粒度控制的能力.

在 k8s 集群中的操作就是:

  1. 物理备份:etcd 备份,保存某一个时刻的快照,快捷方便。
  2. 逻辑备份:基于 velero 或者自研功能,允许用户自己选择备份的内容、自动或定时备份,也可以恢复特定内容。同时备份的就是 yaml,用户可读可修改。

etcd 备份

以 etcd v3 版本为例:

备份:


# 执行备份 date; CACERT="/opt/kubernetes/ssl/ca.pem" CERT="/opt/kubernetes/ssl/server.pem" EKY="/opt/kubernetes/ssl/server-key.pem" ENDPOINTS="127.0.0.1:2379" ETCDCTL_API=3 etcdctl \ --cacert="${CACERT}" --cert="${CERT}" --key="${EKY}" \ --endpoints=${ENDPOINTS} \ snapshot save /backup/etcd-snapshot-`date +%Y%m%d`.db # 备份保留30天 find /backup/ -name *.db -mtime +30 -exec rm -f {} \;

恢复:

1.停止所有 Master 上 kube-apiserver 服务

systemctl stop kube-apiserver

2.停止集群中所有 ETCD 服务
systemctl stop etcd

3.移除所有 ETCD 存储目录下数据
mv /etcd/data /etcd/data.bak

4.从备份文件中恢复数据
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot-xx.db  

5.启动 etcd
systemctl start etcd

6.启动 apiserver
systemctl start kube-apiserver

7.检查服务是否正常

逻辑备份

逻辑备份就是让用户选择自己的备份内容、备份周期和恢复方式,换句话说,把备份做成一种产品功能,存放用户的 yaml 备份。因为我们是云产品,所以提供了自定义的备份能力,用户可以在页面上选择 namespace 或资源,备份所有资源的 yaml,后端将 yaml+json 两份文件存放在对象存储,并支持定时备份、指定资源做恢复。

备份的逻辑非常简单,简化为 kubectl 操作就是:

kubectl get deploy nginx -o yaml > nginx.yaml

只是将 kubectl 操作换成了代码实现,扫描 ns 下的十几种资源类型,并转为文件上传到对象存储。但如果做成产品功能,会多出一些设计和限制在里面,如:

  • 备份限制:用户有自己的配额,如一个用户最大能有100 个备份文件,允许下载
  • 手动备份:用户可以勾选需要的资源,点击备份,备份是异步操作,点击后会有备份进度展示
  • 自动备份:支持 cron 表达式,按指定时间进行备份
  • 恢复备份:恢复时需要去除yaml 中的某些字段,然后 apply 到用户集群

备份的思路参考了 velero 的实现,只是 velero 需要在集群内安装 pod 来配合备份,而备份 yaml 只要有 kubeconfig 能连接集群即可。

velero 备份

velero 是开源方案,项目地址:https://velero.io/

velero的作用:

  • 灾备能力:提供备份恢复k8s集群的能力
  • 迁移能力:提供拷贝集群资源到其他集群的能力

和 etcd 备份的区别:

  • etcd 的备份必须拥有 etcd 运维权限,有些用户无法操作 etcd,如多租户场景。
  • etcd 更适合单集群内数据备份,不太适合集群迁移
  • etcd 是当前状态备份,velero 可以做到只备份集群内的一部分资源

velero 会在你的 k8s 集群上运行一个 server pod,然后配合 velero 客户端进行操作,安装过程可以参考文档,操作是很简单的:

1.创建一个 nginx 资源

---
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: hub.baidubce.com/cce/nginx-alpine-go:latest
        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

kubectl apply -f base.yaml

2.生成一个备份,备份名称为 nginx-backup

velero backup create nginx-backup --include-namespaces nginx-example

3.删除nginx example 资源:

kubectl delete namespaces nginx-example

4.从nginx-backup备份中恢复资源:

velero restore create --from-backup nginx-backup

velero还支持更多的备份方式,可以参考官方文档,

工作原理:

velero 默认将备份的文件上传到对象存储,对象存储和和csi 插件都云厂商支持,因此一般搭配 velero-plugin 使用,如:

  • aws: https://github.com/vmware-tanzu/velero-plugin-for-aws
  • 阿里云: https://github.com/AliyunContainerService/velero-plugin
  • 百度云: https://cloud.baidu.com/doc/CCE/s/njyfx596a

存储的备份

只有需要持久化的、有状态的应用才需要备份,而 k8s 中的存储挂载有很多种,如:

  • emptyDir
  • configmap
  • secret
  • hostpath
  • nfs
  • 各种云厂商的磁盘
  • 对象存储

存储资源的备份一直是 k8s 备份最麻烦的部分,因为涉及到的挂载类型太多

云厂商磁盘:

  • 如果你通过 flexvolume 或者 csi 插件挂载了文件存储、对象存储或者块存储,可以在对应的云产品页面进行磁盘的备份操作
  • 如果厂商自己定义了 crd 之类的操作,允许你自定义备份策略,你可以通过提交 yaml 来配置磁盘备份
  • k8s 1.12 开始支持了csi snapshot ,如果厂商实现了 snapshot 功能,你可以直接在 k8s 中声明VolumeSnapshot来创建备份。

非云厂商:

  • 如果你是emptyDir或者 nfs 的方式,可以在 velero 中使用 集成restic来实现备份,需要 k8s 支持mountPropagation(1.10 以上的版本),可以参考这个[文档] https://velero.io/docs/v1.4/restic/(https://velero.io/docs/v1.4/restic/)
  • restic不支持hostpath 方式的挂载,但可以支持 local pv

csi snapshot

k8s支持三种类型的卷插件:in-tree、Flex和CSI。而 snapshot 功能只有使用CSI才支持

CSI(Container Storage Interface)是社区定义的一套用于容器场景的存储接口标准。k8s作为CO(容器编排系统)支持该标准。CSI方案是k8s中功能最完整,迭代最活跃的out-of-tree存储框架,也作为新的存储接入k8s的建议模式。现在大量的in-tree插件也在向CSI插件迁移。

k8s 1.12 开始推出了 csi snapshot 功能,定义了几种 CRD 资源来实现快照功能,到 k8s 1.17,该功能进入 beta 阶段。

使用方式:

存储卷快照和pvc、pv创建的过程很类似:

  • PVC-—>StorageClass—->PV
  • VolumeSnapshot—->VolumeSnapshotClass—–>VolumeSnapshotContent

在kubernetes中用VolumeSnapshotContent 和VolumeSnapshot这样的API资源去为用户和管理员创建卷快照

  • VolumeSnapshotContent是从集群中指定的volume中获取的快照, 像PV资源一样
  • VolumeSnapshot是用户想从某个指定volume获取快照的一个请求, 像集群中的PVC一样

当用户想对某个volume进行快照的时候, 可以先创建VolumeSnapshotClass对象,之后创建一个卷快照申请,即VolumeSnapshot,当有了这个申请之后,先前创建的VolumeSnapshotClass就会根据申明来进行卷快照,生成快照内容,即VolumeSnapshotContent。

这个功能是由CSI drivers提供,有些CSI drivers是支持快照功能的,当安装了支持卷快照的CSI drivers之后,CSI drivers会自动安装 VolumeSnapshotClass、VolumeSnapshot 和VolumeSnapshotContent 这些api 资源,这些 api 资源是 CRD,并不是 core api中的一部分, 作为部署过程的一部分,kubernetes为 snapshot controller 提供了一个名叫 external-snapshotter 的sidecar helper container, 它会watches VolumeSnapshot 这个对象,并触发对 CSI 端点的 CreateVolume 和DeleteVolume 操作。

创建VolumeSnapshotClass对象

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
  name: disk-snapshotclass
snapshotter: diskplugin.csi.alibabacloud.com #指定VolumeSnapshot时使用的Volume Plugin

创建VolumeSnapshot对象:

apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
  name: disk-snapshot
spec:
  snapshotClassName: disk-snapshotclass
  source:
    name: disk-pvc  #Snapshot的数据源, 类型是个pvc
    kind: PersistentVolumeClaim

从snapshot中恢复数据到新生的pv对象中

apiVersion: v1
kind: PersisttentVolumeClaim
metadata:
  name: restore-pvc
spec:
  dataSource:
    name: disk-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    -ReadWriteOnce
  resource:
    requests:
      storage:20Gi
  storageClassName: csi-disk

velero 中对于csi snapshot的支持:

velero 在 1.4 版本也对csi snapshot做了支持,不过功能并不完善,要求 k8s 版本必须为 1.17 及以上,参考文档: https://velero.io/blog/csi-integration/

velero client config set features=EnableCSI

参考

  • https://cloud.tencent.com/developer/article/1549339
  • https://www.youtube.com/watch?v=CbA40krYZf0
  • https://cloud.baidu.com/doc/CCE/s/njyfx596a
  • https://www.kubernetes.org.cn/6266.html
  • http://dockone.io/article/8697
  • https://portworx.com/use-case/kubernetes-storage/
  • https://velero.io/blog/csi-integration/
  • https://github.com/vmware-tanzu/velero-plugin-for-aws
  • https://www.youtube.com/watch?v=JyzgS-KKuoo
  • https://www.objectif-libre.com/en/blog/2020/01/10/kubernetes-backup-stateful-apps/
  • https://www.infoq.cn/article/sbwSX8ypxgID2-SB723K
  • https://stash.run/
  • https://kubernetes-csi.github.io/docs/snapshot-restore-feature.html
  • https://haojianxun.github.io/2019/06/24/kubernetes%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8%E5%8D%B7%E5%AD%98%E5%82%A8%E5%8D%B7%E5%BF%AB%E7%85%A7Snapshot/
  • https://www.youtube.com/watch?v=CbA40krYZf0&t=628s

Written by

说点什么

欢迎讨论

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒