遇见复原力

复原力

复原力一词来源于微软创新研究院,全称是社会复原力,它研究的是通过大规模部署可以适应未来各种变数以及不确定性的创新技术来应对社会的各种潜在危机,从而增强社会复原力。如COVID-19、全球气候变暖、环境污染,探索在危机来临前中后的创新技术储备,快速应对方法,快速复原的能力。是一种从无序和混乱中回归秩序的能力。这也是运维所要解决的问题,让系统回归秩序。

本文探索的是云原生时代下容器基础设施在面临各种危机时的复原力问题,即基础设施复原力。

基础设施复原力

随着容器技术的不断发展,k8s已经成为了云原生时代下的基础设施,它为应用向下屏蔽了云上基础设施的复杂性,向上提供了应用的全生命周期管理能力,将分布式应用管理的复杂性收敛转化到了分布式系统本身的管理问题上。然而,它虽然解决了应用在分布式环境下的编排问题,但自身的分布式系统的运维复杂性仍然存在。底层基础设施失效,可用区故障,节点故障,组件失效,网络分区,抖动,甚至地震、火灾等风险始终存在,如何保证系统的稳定性以及面对这些危机时候的系统复原力是一项非常具有挑战的工作,这也构成了云原生时代下的基础设施复原力问题。

事实上,k8s面向终态的设计已经让应用具备了从外部扰动中回到稳态的能力,面对应用进程异常退出,容器失败,网络故障,配置紊乱等问题,k8s能够实现检测并自行原地恢复,或者替换掉失效应用副本来使应用处于预期状态,这是k8s的应用复原力。通过以上理念,我们希望云原生时代的基础设施也能具备从外部扰动中自动回归稳态的能力,同时以一种尽可能小的代价去解决k8s平台自身运维复杂性的问题,因此我们设计了wdrip,以一种逐渐收敛的方案来解决k8s分布式系统的自动化运维问题,实现基础设施的复原力。

故障复原场景示例

k8s 面向终态的设计为应用的复原力提供了支撑。从终态设计上你能看到k8s 让应用从外部扰动中回归稳态的思想, wdrip也同样采用面向终态的思想,在基础设施层解决k8s的自运维问题。下面会演示一些常见的k8s故障场景,并且观察系统是如何在无人为干预的情况下自动恢复的。

前置条件

wdrip的基本功能及其使用,请移步管理集群

  • 请使用wdrip创建一个k8s集群。

  • 请部署示例应用,或者部署您自己觉得合适的[容器化应用]云原生应用示例

场景一:节点故障

节点故障是k8s集群故障里最常见的一种场景了,也是危害相对较小的故障,wdrip可以侦测节点的异常状态,然后尝试修复。修复的流程如下
如果节点状态变为NotReady,那么等待2个heartbeat周期

  • 如果周期内持续NotReady,wdrip尝试重启kubelet,并等待节点Ready
  • 如果节点仍然NotReady,wdrip尝试驱逐节点Pod,然后继续尝试重启ECS,并等待节点Ready
  • 如果节点仍然NotReady,wdrip继续尝试重置ECS(替换节点的系统盘,并重新初始化节点),并等待节点Ready
  • 如果节点仍然NotReady,wdrip删除这个节点,等待系统重启创建一个全新的节点副本。
  • 如果节点仍然NotReady,修复失败。等待throttle周期后重复以上步骤。

通常可以通过以下手段模拟节点故障:

  1. 方法一:通过kubectl delete no ${your-node} 删除对应的Node Object。等待节点自动恢复并注册回来,恢复全程无需人工干预,时长约2分钟。
  2. 方法二:登录ECS节点,systemctl stop kubelet/docker等。等待节点NotReady后,系统会自行恢复节点状态。恢复全程无需人工干预。
  3. 方法三:到ECS控制台上【关闭】节点对应的ECS。系统会自行恢复节点状态。恢复全程无需人工干预。
  4. 方法四:到ECS控制台上【删除】节点对应的ECS。系统会自行恢复节点状态。恢复全程无需人工干预。

[去试一试]管理集群

场景二:管控故障

管控故障通常情况下是比较严重的,k8s集群依赖etcd组成高可用集群,一旦etcd quorum丢失,集群管控将会直接不可用。因此正常情况下管控的恢复要更加的复杂。
wdrip精心抽象了管控的恢复流程,操作前会尽量确保etcd quorum始终保持在可用状态。但仍然具备在quorum丢失的情况下从混乱中使用snapshot恢复集群管控。

通常可以通过以下方法模拟管控故障:

  1. 方法一:通过kubectl命令删除master node。
  2. 方法二:登录Master节点ECS,stop ETCD服务,删除etcd数据,stop kubelet服务,stop docker服务等。
  3. 方法三:登录ECS控制台【关闭】一台Master节点ECS。
  4. 方法四:登录ECS控制台【删除】一台Master节点ECS。

对于3个master或更多个master副本的集群,你可以操作让一台ECS节点故障,等待查看系统如何回复到稳定状态,这个过程中整个系统全程仍然可以提供服务。重要的是,你可以操作多台Master ECS节点,让他们同时处于故障状态,这时候系统大概率会因为quorum丢失从而造成集群不可用,但你仍然能够观察到wdrip会通过各种手段将集群恢复到正常的稳定状态,并且无需人工干预。
对于worker节点,只要不涉及到管控面访问相关的业务,恢复的过程中用户的业务将不受任何影响,实现业务的连续性。

场景三:可用区故障

虽然可用区级别的故障的概率非常低,但我们仍然在设计的时候考虑到这种场景,wdrip支持创建跨可用区的集群,添加多个不同可用区的节点池可以让节点分布到不同可用区,提高集群面对可用区故障时候的韧性。

当管控所在的可用区出现故障时候,集群不可用,集群上的应用大概率也会不可用,wdrip支持snapshot整个k8s集群,然后在其他可用区使用该snapshot一键重新拉起一个一模一样的集群,这种恢复方式保留了所有原集群的配置,唯一变化的是承载集群运行的基础设施,如ECS、SLB等等。相当于在一个新的克隆体中恢复之前备份的大脑,意识下载。

1
(base) ➜ wdrip recover -n kubernetes-wdrip-121 -f kubernetes-wdrip-120

场景四:Region故障

整个Region发生故障的概率应该是非常非常的低的了,但wdrip设计上仍然能够处理这种灾难。wdrip在运行时会定期备份集群的状态到OSS(可以跨Region写多份实现高可用),当Region出现故障的时候,可以尝试在另外一个Region创建一个新的集群,然后通过备份的snapshot快速恢复业务。参考可用区故障。但目前很多存储资源是可用区级别的,因此还需要进一步考虑存储的跨Region恢复。

场景五:删库跑路

一直想提的一个场景就是删库跑路。wdrip定期备份了整个集群的意识,无论你怎么折腾集群,只要备份存在,意识就存在,wdrip就可以再完完全全的还原出一个集群的克隆体出来,恢复现场到以前的状态。

删库跑路?不存在的。

你可以尝试删除集群试试,删除方法

  1. 到ROS控制台删除该集群对应的ROS模板,按名称搜索即可找到对应的模板
  2. wdrip delete -n kubernetes-id-001 不用担心,即便删除了集群,但备份还在,我们仍然能完整的恢复该集群,这也是wdrip的魅力。

恢复的方法:

  1. 创建新的集群kubernetes-id-002。wdrip create --config cluster.yml
  2. 恢复集群的意识备份到这个新建的集群本体上。 wdrip recover -n kubernetes-id-002 -f kubernetes-id-001

灾难恢复(手动)

1
2
3
# -n 指定恢复的目标集群(本体), -f 指定恢复的配置来源于哪个集群(意识)。
(base) ➜ wdrip recover -n kubernetes-id-002 -f kubernetes-id-001

ChaosMonkey

为了测试基础设施复原力我们专门编写了ChaosMonkey部署在集群中,他能够定期破坏集群(删除集群ECS资源、停止关键组件),等待系统自愈。

如何使用

1
2
3
4
(base) ➜  export CLUSTER_NAME=kubernetes-id-001
(base) ➜ bash hack/wdrip.sh config
(base) ➜ bash hack/wdrip.sh chaos
(base) ➜ kubectl --kubeconfig ~/.kube/config.wdrip -n kube-system get po|grep monkey

小结

k8s的复杂性虽然让让人生畏,但wdrip提供的复原力让我们在面对危机的时候能够更加的从容。

以上示例所涉及到的脚步均保存于wdrip项目中,使用前请git clone到本地.

1
(base) ➜ git clone https://github.com/aoxn/wdrip.git