升级etcd失误导致整个Kubernetes集群瘫痪

Bad day

Kubernetes依赖KV数据库管理配置数据,默认推荐使用Etcd,当然你不喜欢还有很多其它的选择。由于升级Kubernetes之后没有升级Etcd版本导致集群总有一些小问题,最明显的一个问题就是CronJob遗留的Pods不会自动清理掉,之前的文章我也说过这个问题,后来我意识到这可能是升级Kubernetes之后没有升级相应的Etcd版本导致的。之前在构建集群的时候使用的是外部自建Etcd集群,直接使用Etcd Docker镜像启动的,我的Kubernetes集群一共三台Master,为了方便我直接三台Master上分别运行Etcd程序组成高可用的Etcd集群。

它们的脚本类似如下:

#!/bin/sh
mkdir -p /var/etcd
docker rm etcd1 -f
rm -rf /var/etcd
docker run --restart=always --net host -it --name etcd1 -d \
-v /var/etcd:/var/etcd \
-v /etc/localtime:/etc/localtime \
k8s.gcr.io/etcd:3.3.10 \
etcd --name etcd-s1 \
--auto-compaction-retention=1 --max-request-bytes=33554432 --quota-backend-bytes=8589934592 \
--data-dir=/var/etcd/etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://node4.cluster.local:2380 \
--advertise-client-urls http://node4.cluster.local:2379,http://node4.cluster.local:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster "etcd-s1=http://node4.cluster.local:2380,etcd-s2=http://node5.cluster.local:2380,etcd-s3=http://node6.cluster.local:2380" \
-initial-cluster-state new

按照最新版本的Kubernetes建议,我应该使用etcd v3.3.15-0版本,所以我当时想着就直接把以上脚本中的k8s.gcr.io/etcd:3.3.10替换成k8s.gcr.io/etcd:3.3.15-0重新执行一次就好,可是疏忽大意导致我忘了这个脚本里有几点操作,这是一个灾难性的操作,现在写下来总结一下,避免日后再有类似愚蠢的行为。

没认真看脚本内容

因为当时写这个脚本的时候就是用来建新Etcd集群的,已经有一年没再看过这个脚本了,所以脚本里的具体细节我也记得不清楚,其实这个脚本仅适合新建集群。比如每次我都会执行rm -rf /var/etcd删掉之前的遗留的数据重来,比如etcd启动参数的--initial-cluster-state new,都没认真看就直接执行了。

没备份

虽然知道Etcd是Kubernetes的心脏,但想着Etcd这么轻量的程序应该升级不复杂,所以就没想过留后路。在没有备份升级失败后,整个Kubernetes集群瞬间垮掉。我花了整整一个通宵重建Kubernetes集群,重建各种服务,中间遇坑无数,包括Calico在CoreOS上的各种坑。。。加上由于升级失败Kubernetes集群垮掉造成的恐惧感让我在重建Kubernetes中对每一个命令参数都仔细又仔细的阅读文档,确保它们的作用,好处与利害关系,这是一件非常累心的事,因为好多参数的调优都要根据实际情况加经验去选用。

没提前做好失败策略

当意识到升级失败之后,还有一个糟糕的情况是虚机快照也没有提前建好,那时候就意识到我这几个壮举应该是造成kubernetes需要重建了,因为没有提前做好重建Kubernetes集群的演练,导致在重建Kubernetes的过程中遇到了不少坑,浪费了很多时间。由于历史原因,Kubernetes集群有各种各样的构建方式,最终选用官方提供的kubeadm工具去构建一个新的Kubernetes,并且这次我就放弃了外建Etcd,kubeadm会帮你内建一个Etcd高可用集群随着Master一块启动,选用内建Etcd主要是不用再去额外管理维护它,以后升级什么的也不用管。重建过程我额外仔细,每一步出错都花时间去填坑,最后只能通宵熬夜,我应该写一片文章来说说如何快速创建Kubernetes集群。

这次升级让我更加注意以后升级任何程序时要认真做的几件事,尤其是关键性服务,影响面大,比较重要的服务更应该谨慎

  • 找一个测试环境试一把,测试环境尽量贴着生产环境
  • 备份数据,防止万一失败要回滚
  • 先准备好回滚脚本,也就是升级失败,就能立即回滚,而不是升级失败后再去想办法降级
  • 认真审查每一步操作的脚本和参数,确定它在测试环境上是没问题的
  • 如果是重要服务升级,尽量挑夜间,人少的时候开始
分享

TITLE: 升级etcd失误导致整个Kubernetes集群瘫痪

LINK: https://www.qttc.net/500-a-bad-day-with-etcd-upgrade-for-kubernetes.html

NOTE: 原创内容,转载请注明出自琼台博客