写点什么

修复一个 kubernetes 集群

  • 2024-10-23
    福建
  • 本文字数:2166 字

    阅读完需:约 7 分钟

前几天有个朋友把他们的 kubernetes 集群搞挂了,让我帮忙恢复一下,由于很多现场都没有了,这里提供一下解决思路。


环境问题


该环境有一个 master 节点,即控制面 pod(etcd、scheduler 等)也都只有一个 pod


问题起因是他们的服务访问出了点问题,为修复该问题,他:


  • 备份了 etcd 数据(数据是 3 天前的)

  • 重启了 docker

  • 将 etcd 数据恢复(数据是 3 天前的)


然后访问服务依然不通。


问题诊断


deployment reversion 不匹配


首先看到 pod 并非running状态,直接删除 pod,让其重建,查看 pod 创建过程,发现 pod 并没有分配到 node。


问题分析


首先怀疑可能 kube-scheduler 出现了问题:


  1. 删除 kube-scheduler pod 发现无法重建该 pod

  2. 最后通过将/etc/kubernetes/manifests/kube-scheduler.yaml文件移出再移入的方式创建出 scheduler pod


此时仍然无法调度 pod,因此怀疑是在 scheduler 之前出现了问题,查看 api-server 的日志,发现有很多 reversion 版本不匹配的错误,应该是集群中的资源版本和 etcd 中的资源版本不匹配导致的:


1.使用 etctctl 检查 etcd 的状态,发现 etcd 一切正常


etcdctl endpoint healthetcdctl endpoint status --write-out=table
复制代码


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 规则:


  1. 使用iptables-save命令查看,发现果然没有 kubernetes 的 iptables 规则

  2. 该环境使用的是 ipvs 模式,使用ipvsadm -l -n也发现 service 的 cluster IP 没有对应的 pod IP

  3. 查看 kube-proxy 日志,并未发现任何异常


此时想到的方式有:


  1. 重新创建 pod 和对应的 service,刷新 iptables:尝试失败,重建之后并未生成 iptables

  2. 重建节点:所有节点都存在问题,无法通过kubectl drain迁移 pod

  3. 手动添加 iptables:太过复杂,即便成功,也会污染节点的 iptables 规则。

  4. 重新创建 kube-proxy pod:重启 kube-proxy pod 之后也并未创建 iptables 规则


最后怀疑 kube-proxy 也可能出现问题,需要重新初始化 kube-proxy,恰好 kubeadm 有如下命令可以重新初始化 kube-proxy:


kubeadm init phase addon kube-proxy --kubeconfig ~/.kube/config --apiserver-advertise-address <api-server-ip>
复制代码


在重新初始化 kube-proxy 之后发现 iptables 规则创建成功,删除并创建 pod 和 service 之后可以正确创建出对应的 iptables 规则,此时 service 也有了 endpoints。


CNI 连接错误


在上一步重启 pod 之后,发现有一个 webhook 对应的 pod 没有重启成功,用kubectl describe 该 pod 发现如下错误:


networkPlugin cni failed to set up pod "webhook-1" network: Get "https://[10.233.0.1]:443/api/v1/namespaces/volcano-system": dial tcp 10.233.0.1:443: i/o timeout
复制代码


该集群使用的是 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文件:


{  "name": "cni0",  "cniVersion":"0.3.1",  "plugins":[    {      ...       "kubernetes": {        "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"      }    },    ...  ]}
复制代码


/etc/cni/net.d/calico-kubeconfig中就定义了连接 apiserver 所需的地址和端口,因此只需将该地址端口换成 apiserver pod 的地址和端口应该就可以解决该问题:


# cat /etc/cni/net.d/calico-kubeconfig# Kubeconfig file for Calico CNI plugin.apiVersion: v1kind: Configclusters:- name: local  cluster:    server: https://[10.233.0.1]:443    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0...users:- name: calico  user:    token: eyJhbGciOiJSUzI1NiIsImtpZC...contexts:- name: calico-context  context:    cluster: local    user: calico
复制代码


Calico提供了如下两个环境变量用于修改生成的 kubeconfig 中的 apiserver 的地址和端口,将如下环境变量加入 calico 的 daemonset,重新创建calico-node pod 即可:


- name: KUBERNETES_SERVICE_HOST  value: <api-server-pod-ip>- name: KUBERNETES_SERVICE_PORT  value: "6443"
复制代码


至此,问题基本解决。由于错误的操作,该集群出现了大量问题,后续可以通过驱逐节点 pod 的方式,重新初始化整个节点,逐步重置集群节点配置。


文章转载自:charlieroro

原文链接:https://www.cnblogs.com/charlieroro/p/18493461

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
修复一个kubernetes集群_Kubernetes_不在线第一只蜗牛_InfoQ写作社区