修复一个 kubernetes 集群
前几天有个朋友把他们的 kubernetes 集群搞挂了,让我帮忙恢复一下,由于很多现场都没有了,这里提供一下解决思路。
环境问题
该环境有一个 master 节点,即控制面 pod(etcd、scheduler 等)也都只有一个 pod
问题起因是他们的服务访问出了点问题,为修复该问题,他:
备份了 etcd 数据(数据是 3 天前的)
重启了 docker
将 etcd 数据恢复(数据是 3 天前的)
然后访问服务依然不通。
问题诊断
deployment reversion 不匹配
首先看到 pod 并非running
状态,直接删除 pod,让其重建,查看 pod 创建过程,发现 pod 并没有分配到 node。
问题分析
首先怀疑可能 kube-scheduler 出现了问题:
删除 kube-scheduler pod 发现无法重建该 pod
最后通过将
/etc/kubernetes/manifests/kube-scheduler.yaml
文件移出再移入的方式创建出 scheduler pod
此时仍然无法调度 pod,因此怀疑是在 scheduler 之前出现了问题,查看 api-server 的日志,发现有很多 reversion 版本不匹配的错误,应该是集群中的资源版本和 etcd 中的资源版本不匹配导致的:
1.使用 etctctl 检查 etcd 的状态,发现 etcd 一切正常
2.使用kubectl rollout history deployment/<deployment_name>
查看 etcd 中保存的的 deployment 的版本,然后执行kubectl rollout undo daemonset/<deployment_name> --to-revision=<version>
回滚到与 etcd 匹配的版本。
3.回滚之前可以通过kubectl rollout history daemonset/<deployment_name> --revision=<version>
对比 etcd 和环境中的配置区别
4.回滚之后发现 pod 可以正常创建出来
Iptables 丢失问题
pod 起来之后,服务访问仍然不通。使用kubectl describe
命令查看服务的 service,发现没有找到 service 对应的 endpoints,一开始还以为是 service 的 yaml 的问题,debug 了大半天发现绝大部分 services 都没有 endpoints。。。
问题分析
service 找不到 endpoints,体现在系统中就是可能没有创建出 iptables 规则:
使用
iptables-save
命令查看,发现果然没有 kubernetes 的 iptables 规则该环境使用的是 ipvs 模式,使用
ipvsadm -l -n
也发现 service 的 cluster IP 没有对应的 pod IP查看 kube-proxy 日志,并未发现任何异常
此时想到的方式有:
重新创建 pod 和对应的 service,刷新 iptables:尝试失败,重建之后并未生成 iptables
重建节点:所有节点都存在问题,无法通过
kubectl drain
迁移 pod手动添加 iptables:太过复杂,即便成功,也会污染节点的 iptables 规则。
重新创建 kube-proxy pod:重启 kube-proxy pod 之后也并未创建 iptables 规则
最后怀疑 kube-proxy 也可能出现问题,需要重新初始化 kube-proxy,恰好 kubeadm 有如下命令可以重新初始化 kube-proxy:
在重新初始化 kube-proxy 之后发现 iptables 规则创建成功,删除并创建 pod 和 service 之后可以正确创建出对应的 iptables 规则,此时 service 也有了 endpoints。
CNI 连接错误
在上一步重启 pod 之后,发现有一个 webhook 对应的 pod 没有重启成功,用kubectl describe
该 pod 发现如下错误:
该集群使用的是 calico CNI,查看该 CNI 对应的 daemonset,发现只有 5 个 pod 是 ready 的。
删除"webhook-1" pod 所在的节点的"calico-node" pod,发现该"calico-node" pod 启动失败。
问题分析
在上述错误中,"10.233.0.1"为 kubernetes apiserver 的 service cluster IP,由于"clico-node" pod 使用的是hostnetwork
,因此可以直接在 node 上测试联通性,使用telnet 10.233.0.1 443
测试,发现果然不通。
calico 的/etc/cni/net.d/10-calico.conflist
配置文件中定义了连接 apiserver 所需的kubeconfig
文件:
而/etc/cni/net.d/calico-kubeconfig
中就定义了连接 apiserver 所需的地址和端口,因此只需将该地址端口换成 apiserver pod 的地址和端口应该就可以解决该问题:
Calico提供了如下两个环境变量用于修改生成的 kubeconfig 中的 apiserver 的地址和端口,将如下环境变量加入 calico 的 daemonset,重新创建calico-node
pod 即可:
至此,问题基本解决。由于错误的操作,该集群出现了大量问题,后续可以通过驱逐节点 pod 的方式,重新初始化整个节点,逐步重置集群节点配置。
文章转载自:charlieroro
评论