[译 ] Kubernetes集群灾备(disaster recovery)的终极指南

原文 - The Ultimate Guide to Disaster Recovery for Your Kubernetes Clustersnode

序言

Kubernetes容许咱们运行大规模容器化app而不须要过多关注app的负载均衡细节。你能够经过在Kubernetes上运行多个app副本(replicas)(pods)来保证你的app的高可用性。全部容器编排的复杂细节安全地隐藏着,因此你能够专一于开发app而不是专一在如何部署它。你能够在这里了解更多关于Kubernetes集群高可用以及如何经过Kubeadm实现Kubernetes高可用(use Kubedm for high availability in Kubernetes)docker

可是使用Kubernetes有它自己的一些挑战以及要让Kubernetes运行起来须要花一些功夫。若是你不熟悉如何运行Kubernetes,你或许能够看看这个api

Kubernetes可让咱们实现零停机的部署,可是必然仍是会有可能在任什么时候候发生服务中断的事件。你的网络可能down掉,你的最新的app镜像可能引发一个严重的bug,或者在最罕见的案例下,你可能面临一个天然灾害。安全

当你在使用Kubernetes的时候,或早或晚,你须要设置一个备份。为了以防你的集群进入到一个不可回复的状态,你须要一个备份来回复到集群早前的稳定状态。bash

为何备份和回复?

关于你为何须要为你的Kubernetes集群准备备份和回复机制,有3个理由:网络

  1. 为了在灾难后恢复: 好比某人意外地将你的deployment所处的namespace删除了的状况。
  2. 为了复制环境: 你想要复制你的生产环境到一个临时环境,以便在一个重大升级前作一些测试。
  3. 迁移Kubernetes集群: 比方说,你想要迁移的你的Kubernetes集群到另外一个环境。

须要备份什么?

如今你知道为何,让咱们看看具体备份要作什么。你须要备份2个东西:app

  1. 你的Kubernetes control plane(一般是master节点)是把数据存放在etcd存储中,因而你须要备份etcd全部陈述以便获取全部Kubernetes资源。
  2. 若是你有"有状态"(stateful)容器(一般在实际使用中是会遇到的),你还须要备份持久卷(persistent volume)。

如何备份?

有各类工具好比Heptio ark和Kube-backup支持搭建于cloud provider上的Kubernetes集群的备份和回复。可是若是你没有在使用已经被管理(指云供应商提供的)的Kubernetes集群呢?你可能会须要亲自上阵,若是你的Kubernetes运行在裸机上,就像咱们同样。 咱们运行拥有3个master的Kubernetes集群,而且有3个etcd member同时运行在每一个master上。若是咱们失去了一个master,咱们还能够恢复master,因为依然知足etcd的最低运行数。如今若是在生产环境下咱们失去2个master,咱们就须要一个机制去恢复集群运做。负载均衡

想知道如何构建多个master的Kubernetes集群?继续阅读吧!ide

给etcd作备份:

给etcd备份机制的不一样之处取决于你是如何在Kubernetes环境中构建etcd集群的。 在Kubernetes环境中有2种方法来设置etcd集群:工具

  1. 内部etcd集群: 这表示你正在Kubernetes集群中运行容器/pod形式的etcd集群,而且管理这些pod的责任在于Kubernetes。
  2. 外部etcd集群: 大多数状况下Etcd集群以Linux service的形式运行在Kubernetes集群外,而且提供endpoint给Kubernetes集群以便Kubernetes集群来读写。

给内部Etcd集群作备份的策略:

为了给一个内部etcd pod取备份,咱们须要使用Kubernetes CronJob机能,这个方法不须要在宿主机(node)上安装任何etcdctl客户端。 如下是定义了Kubernetes CronJob,用来每分钟获取etcd备份:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: backup
namespace: kube-system
spec:
# activeDeadlineSeconds: 100
schedule: "*/1 * * * *"
 jobTemplate:
 spec:
 template:
 spec:
 containers:
 - name: 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/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /backup/etcd-snapshot-$(date +%Y-%m-%d_%H:%M:%S_%Z).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: /data/backup
 type: DirectoryOrCreate
复制代码

给外部Etcd集群作备份的策略:

若是你在Linux主机上做为一个service来运行etcd集群,你应该设置一个Linux的定时任务(cron job)来备份你的集群。 运行如下的命令来备份etcd。

ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save /path/for/backup/snapshot.db
复制代码

灾难恢复(disaster recovery)

如今,假设Kubernetes集群彻底downn掉以后,咱们须要经过etcd snapshot恢复Kubernetes集群。 通常来讲,咱们须要启动etcd集群,而后在master节点兼etcd endpoint的这个(这些)主机上执行kubeadm init。 保证你把备份了的证书放到/etc/kubernetes/pki(kubeadm init建立集群时建立的存放Kubernetes集群用到的证书的默认目录)目录下。

内部etcd集群恢复策略:

docker run --rm \
-v '/data/backup:/backup' \
-v '/var/lib/etcd:/var/lib/etcd' \
--env ETCDCTL_API=3 \
'k8s.gcr.io/etcd:3.2.24' \
/bin/sh -c "etcdctl snapshot restore '/backup/etcd-snapshot-2018-12-09_11:12:05_UTC.db' ; mv /default.etcd/member/ /var/lib/etcd/"
kubeadm init --ignore-preflight-errors=DirAvailable--var-lib-etcd
复制代码

外部etcd集群的恢复策略

经过如下命令恢复3个etcd节点:

ETCDCTL_API=3 etcdctl snapshot restore snapshot-188.db \
--name master-0 \
--initial-cluster master-0=http://10.0.1.188:2380,master-01=http://10.0.1.136:2380,master-2=http://10.0.1.155:2380 \
--initial-cluster-token my-etcd-token \
--initial-advertise-peer-urls http://10.0.1.188:2380
ETCDCTL_API=3 etcdctl snapshot restore snapshot-136.db \
--name master-1 \
--initial-cluster master-0=http://10.0.1.188:2380,master-1=http://10.0.1.136:2380,master-2=http://10.0.1.155:2380 \
--initial-cluster-token my-etcd-token \
--initial-advertise-peer-urls http://10.0.1.136:2380
ETCDCTL_API=3 etcdctl snapshot restore snapshot-155.db \
--name master-2 \
--initial-cluster master-0=http://10.0.1.188:2380,master-1=http://10.0.1.136:2380,master-2=http://10.0.1.155:2380 \
--initial-cluster-token my-etcd-token \
--initial-advertise-peer-urls http://10.0.1.155:2380
The above three commands will give you three restored folders on three nodes named master:
0.etcd, master-1.etcd and master-2.etcd
复制代码

如今,中止全部节点上的etcd服务,用恢复了的文件夹替换为全部节点上etcd的文件夹,再启动etcd服务。如今你能够看到全部节点,可是有可能只能看见master是ready状态,你须要从新使用现存的ca.crt(你应该作一个备份)文件将另外2个节点join进集群。 在master上运行如下命令:

kubeadm token create --print-join-command
复制代码

这会给你kubeadm join命令,添加一个参数--ignore-preflight-errors在另外2个节点上运行此命令,让它们变为ready状态。

结论

其中一个处理master故障的方法是建立多master的Kubernetes集群,可是即使这样也不能让你彻底消除Kubernetes etcd备份和恢复的需求,并且你也有可能会意外地销毁HA环境下的数据。