Kubernetes备份还原概述

| 分类 技术  | 标签 Kubernetes  bur 

Contents

Overview

对于在生产环境使用的Kubernetes,我们可以利用kubeadm搭建高可用集群,一定程度实现容灾:

但是即便实现集群的高可用,我们依旧会需要备份还原功能,主要原因如下:

  • 误删除:运维人员不小心删除了某个namespace,某个pv
  • 服务器死机:因为物理原因服务器损坏,或者需要重装系统
  • 集群迁移:需要将一个集群的数据迁移到另一个集群,用于测试或者其它目的

而对于Kubernetes的备份和还原,社区有一个16年创建的issue,从这个issue中我们可以看出Kubernetes官方并不打算提供Kubernetes备份还原方案以及工具,主要原因有两点:

  • 官方认为Kubernetes只提供平台,管理和运行应用(类似于操作系统)。不负责应用层面的备份还原
  • 基于Kubernetes集群的应用各不相同,无法(or 不太好)抽象统一备份方案

为了解决这个问题,社区中也有一些项目产生,例如:reshifterkube-backup以及velero。 这其中最流行的备份还原工具是Velero,基于这个工具的研究可以参考这篇文章

虽然社区和Google上会有一些关于Kubernetes备份还原的工具和方案,但是都杂而不全,本文就针对Kubernetes备份还原这个专题进行一个全面而系统的方案介绍

备份什么?

对于Kubernetes搭建的集群,我们需要备份:

  • 应用版本信息(Application Version)
    • 应用对应的工作负载,例如:deploymenet,statefulset以及daemonset等等
    • 应用需要使用的配置,例如:configmap,secret等等
  • 应用状态信息(Application State)
    • 应用可以分为有状态应用和无状态应用
    • 有状态应用需要备份状态数据,例如:database

备份方案

针对上述备份数据,我们可以制定如下几种不同的备份还原方案(注意是逐项演进的)

etcd+应用状态

方案要点如下:

  • 应用版本备份:Kubernetes集群的所有应用版本信息都存放于etcd中,我们可以直接备份etcd来达到备份版本的目的
  • 应用状态备份:可以从应用层或者文件系统层备份应用状态,例如MariaDB采用mysqldump,MongoDB采用mongodump

备份流程大致如下:

  • step1:备份etcd
    # backup kubernetes pki
    $ cp -r /etc/kubernetes/pki backup/
    # backup kubeadm-config
    $ cp kubeadm-config.yaml backup/
    # backup etcd snapshot
    $ cat <<EOF > etcd-backup-job.yaml
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: etcd-backup
    spec:
      template:
        spec:
          containers:
          - name: etcd-backup
            # Same image as in /etc/kubernetes/manifests/etcd.yaml
            image: k8s.gcr.io/etcd:3.2.24
            env:
            - name: ETCDCTL_API
              value: "3"
            command: ["/bin/sh"]
            args: ["-c", "etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save /backup/etcd-snapshot.db"]
            volumeMounts:
            - mountPath: /etc/kubernetes/pki/etcd
              name: etcd-certs
              readOnly: true
            - mountPath: /backup
              name: backup
          restartPolicy: OnFailure
          hostNetwork: true
          volumes:
          - name: etcd-certs
            hostPath:
              path: /etc/kubernetes/pki/etcd
              type: DirectoryOrCreate
          - name: backup
            hostPath:
              path: /tmp/etcd-backup
              type: DirectoryOrCreate
    EOF
    $ kubectl apply -f etcd-backup-job.yaml 
    $ cp /tmp/etcd-backup/etcd-snapshot.db backup/ 
    
  • step2:应用层备份(eg: MariaDB)
    # backup
    $ mysqldump -uxxx -pxxx db_name > backup-file.sql
    

还原流程大致如下:

  • step1:还原etcd
    # restore kubernetes pki
    $ cp -r backup/pki /etc/kubernetes/
    # restore kubeadm-config
    $ cp backup/kubeadm-config.yaml ./
    # initialize the first control plane node with backup kubernetes pki and kubeadm-config
    $ kubeadm init --config ./kubeadm-config.yaml
    # join other control plane nodes
    $ kubeadm join ...
    # restore etcd with snapshot(Refs: https://duyanghao.github.io/etcd-bur/)
    
  • step2:清空数据
    # restore-phase-1(drop db)
    $ mysqladmin -uxxx -pxxx -f drop db_name
    Database "xxx" dropped
      
    # restore-phase-2(recreate db)
    $ mysqladmin -uxxx -pxxx create db_name  
    
  • step3:还原数据
    # restore-phase-3(restore db)
    $ mysql -uxxx -pxxx db_name < backup-file.sql
    

这种方案的优缺点如下:

  • Pros
    • 原理相对直接,简单
  • Cons
    • 由于采用etcd备份应用版本,保留了工作负载的母机node和pod ip等信息,只支持原地还原
    • etcd还原粒度较大,存在很多的不确定性
    • 需要针对应用层分别制定备份方案,例如各种数据库使用不同的dump工具和命令。维护成本高
    • 全量备份,不支持增量备份

应用版本+应用状态

本方案主要使用社区最流行的备份还原工具Velero,要点如下:

  • 应用版本备份:只备份Kubernetes指定namespace下的资源
  • 应用状态备份:备份相应资源对应的状态数据

这里我们介绍最通用的Velero Restic Integration方案,该方案集成了Restic工具在文件系统层面对应用状态数据进行备份,可以达到屏蔽底层存储细节的目的:

备份流程如下:

  • step1:安装velero
    $ velero install \
          --provider aws \
          --plugins velero/velero-plugin-for-aws:v1.0.0 \
          --bucket velero \
          --secret-file ./credentials-velero \
          --use-restic \
          --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000 \
          --snapshot-location-config region=minio
      
    [...truncate...]
    Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.
      
    $ kubectl get pods -nvelero
    NAME                     READY   STATUS      RESTARTS   AGE
    minio-d787f4bf7-ljqz9    1/1     Running     0          36s
    minio-setup-6ztpp        0/1     Completed   2          36s
    restic-xstrc             1/1     Running     0          11s
    velero-fd75fbd6c-2j2lb   1/1     Running     0          11s
    
  • step2:安装velero-volume-controller
    # Generated image
    $ make dockerfiles.build
    # Retag and push to your docker registry
    $ docker tag duyanghao/velero-volume-controller:v2.0 xxx/duyanghao/velero-volume-controller:v2.0
    $ docker push xxx/duyanghao/velero-volume-controller:v2.0
    # Update the deployment 'Image' field with the built image name
    $ sed -i 's|REPLACE_IMAGE|xxx/duyanghao/velero-volume-controller:v2.0|g' examples/deployment/velero-volume-controller.yaml
    # Create ClusterRole and ClusterRoleBinding
    $ kubectl apply -f examples/deployment/cluster-role.yaml
    $ kubectl apply -f examples/deployment/cluster-role-binding.yaml
    # Create ConfigMap
    $ kubectl apply -f examples/deployment/configmap.yaml
    # Create velero-volume-controller deployment
    $ kubectl apply -f examples/deployment/velero-volume-controller.yaml
    
  • step3:创建velero restic backup
    $ velero backup create nginx-backup-with-pv --include-namespaces nginx-example
    Backup request "nginx-backup-with-pv" submitted successfully.
      
    $ velero backup get 
    NAME                   STATUS      CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
    nginx-backup-with-pv   Completed   2020-03-20 09:46:36 +0800 CST   29d       default            <none>
    

还原流程如下:

  • step1:清除资源
    $ kubectl delete namespace nginx-example
    namespace "nginx-example" deleted
    
  • step2:创建velero restic restore
    $ velero restore create --from-backup nginx-backup-with-pv
    Restore request "nginx-backup-with-pv-20200320094935" submitted successfully.
      
    $ velero restore get
    NAME                                  BACKUP                 STATUS      WARNINGS   ERRORS   CREATED                         SELECTOR
    nginx-backup-with-pv-20200320094935   nginx-backup-with-pv   Completed   0          0        2020-03-20 09:49:35 +0800 CST   <none>
    

由于该方案的最佳实践工具是Velero,所以如果你想了解更多这个工具,可以参考这篇文章

该方案优缺点如下:

  • Pros
    • 屏蔽底层存储,无需关心存储细节
    • 支持增量备份
    • 用户可以选择要备份的资源
    • 支持跨集群备份还原(数据迁移)
    • 使用简单方便,仅一条命令
  • Cons
    • Velero Restic目前并不支持并发备份,第一次备份可能较慢
    • 需要维护一个对象存储,保存备份数据
    • Velero Restic目前不支持高可用
    • 不够灵活。虽然可以选择备份的版本信息,但是对应应用的状态信息却是全部进行备份的;另外应用版本和状态是绑定关系,无法分离

VC+应用状态

为了解决Velero备份不够灵活的问题。设计第三种备份方案,要点如下:

  • 应用版本备份:只备份Kubernetes指定(最小集合)应用版本
  • 应用状态备份:备份指定应用的最小状态集

可以看出相比第二种方案,本方案在备份粒度上更加细化了,应用版本和状态信息全部都缩减到最小集,也即只备份足够还原出集群的最小数据集(数据量越多,不确定性越大)

一般来说为了实现该方案,具体实施参考如下:

  • 利用git管理Kubernetes集群中应用的版本信息
  • 对各应用状态在上层定制备份还原方案,备份最小数据集

该方案优缺点如下:

  • Pros
    • 备份最小数据集
    • 支持跨集群备份还原(数据迁移)
    • 灵活性高,可以在应用上层定制备份还原方案;另外,应用的版本和状态信息分离,可以实现升级还原
  • Cons
    • 高度定制备份还原方案,所以维护成本高
    • 由于采用VC来备份应用版本信息,对版本管理有比较高的要求
    • 全量备份

集群分类

我们按照集群的作用可以将集群分类如下:

  • 管理集群:负责管理客户集群,主要部署自研的管理组件
    • 特点:组件可能经常升级,内部可以管控部署组件;应用数据量小
  • 客户集群:客户实际部署应用的集群
    • 特点:无法管控客户部署的应用;应用数据量大

针对这两种集群类型,对备份还原方案选型建议如下:

  • 管理集群:上述方案均可,但由于方案一限制较多,故建议优先选择方案二和方案三
  • 客户集群:由于不能管控该类集群上部署的应用类型。方案一和方案三都大概率需要定制应用上层备份还原方案,故建议方案二

结论

本文介绍了三种Kubernetes集群的备份还原方案,并列举了各方案的优缺点。最后根据集群类型给出了方案选型建议。总的来说:方案一限制太多,etcd的备份和还原存在太多不确定性,所以不建议使用;方案二采用Velero开源工具,通用性强,适用于大多数集群的备份还原;方案三灵活性高,适合高度定制的集群

Refs


上一篇     下一篇