修复一个kubernetes集群
<p>前几天有个朋友把他们的kubernetes集群搞挂了,让我帮忙恢复一下,由于很多现场都没有了,这里提供一下解决思路。</p><h3 id="环境问题">环境问题</h3>
<blockquote>
<p>该环境有一个master节点,即控制面pod(etcd、scheduler等)也都只有一个pod</p>
</blockquote>
<p>问题起因是他们的服务访问出了点问题,为修复该问题,他:</p>
<ul>
<li>备份了etcd数据(数据是3天前的)</li>
<li>重启了docker</li>
<li>将etcd数据恢复(数据是3天前的)</li>
</ul>
<p>然后访问服务依然不通。</p>
<h3 id="问题诊断">问题诊断</h3>
<h4 id="deployment-reversion不匹配">deployment reversion不匹配</h4>
<p>首先看到pod并非<code>running</code>状态,直接删除pod,让其重建,查看pod创建过程,发现pod并没有分配到node。</p>
<h4 id="问题分析">问题分析</h4>
<p>首先怀疑可能kube-scheduler出现了问题:</p>
<ol>
<li>删除kube-scheduler 发现无法重建该pod</li>
<li>最后通过将<code>/etc/kubernetes/manifests/kube-scheduler.yaml</code>文件移出再移入的方式创建出scheduler pod</li>
</ol>
<p>此时仍然无法调度pod,因此怀疑是在scheduler之前出现了问题,查看api-server的日志,发现有很多reversion版本不匹配的错误,应该是集群中的资源版本和etcd中的资源版本不匹配导致的:</p>
<ol>
<li>
<p>使用etctctl检查etcd的状态,发现etcd一切正常</p>
<pre><code class="language-sh">etcdctl endpoint health
etcdctl endpoint status --write-out=table
</code></pre>
</li>
<li>
<p>使用<code>kubectl rollout history deployment/<deployment_name></code>查看etcd中保存的的deployment的版本,然后执行<code>kubectl rollout undo daemonset/<deployment_name> --to-revision=<version></code>回滚到与etcd匹配的版本。</p>
<blockquote>
<p>回滚之前可以通过<code>kubectl rollout history daemonset/<deployment_name> --revision=<version></code>对比etcd和环境中的配置区别</p>
</blockquote>
</li>
<li>
<p>回滚之后发现pod可以正常创建出来</p>
</li>
</ol>
<h3 id="iptables丢失问题">Iptables丢失问题</h3>
<p>pod起来之后,服务访问仍然不通。使用<code>kubectl describe</code>命令查看服务的service,发现没有找到service对应的endpoints,一开始还以为是service的yaml的问题,debug了大半天发现绝大部分services都没有endpoints。。。</p>
<h4 id="问题分析-1">问题分析</h4>
<p>service找不到endpoints,体现在系统中就是可能没有创建出iptables规则:</p>
<ol>
<li>使用<code>iptables-save</code>命令查看,发现果然没有kubernetes的iptables规则</li>
<li>该环境使用的是ipvs模式,使用<code>ipvsadm -l -n</code>也发现service的cluster IP没有对应的pod IP</li>
<li>查看kube-proxy日志,并未发现任何异常</li>
</ol>
<p>此时想到的方式有:</p>
<ol>
<li><em>重新创建pod和对应的service,刷新iptables</em>:尝试失败,重建之后并未生成iptables</li>
<li><em>重建节点</em>:所有节点都存在问题,无法通过<code>kubectl drain</code>迁移pod</li>
<li><em>手动添加iptables</em>:太过复杂,即便成功,也会污染节点的iptables规则。</li>
<li><em>重新创建kube-proxy pod</em>:重启kube-proxy pod之后也并未创建iptables规则</li>
</ol>
<p>最后怀疑kube-proxy也可能出现问题,需要重新初始化kube-proxy,恰好kubeadm有如下命令可以重新初始化kube-proxy:</p>
<pre><code class="language-sh">kubeadm init phase addon kube-proxy --kubeconfig ~/.kube/config --apiserver-advertise-address <api-server-ip>
</code></pre>
<p>在重新初始化kube-proxy之后发现iptables规则创建成功,删除并创建pod和service之后可以正确创建出对应的iptables规则,此时service也有了endpoints。</p>
<h3 id="cni连接错误">CNI连接错误</h3>
<p>在上一步重启pod之后,发现有一个webhook对应的pod没有重启成功,用<code>kubectl describe</code> 该pod发现如下错误:</p>
<pre><code class="language-sh">networkPlugin cni failed to set up pod "webhook-1" network: Get "https://:443/api/v1/namespaces/volcano-system": dial tcp 10.233.0.1:443: i/o timeout
</code></pre>
<p>该集群使用的是calico CNI,查看该CNI对应的daemonset,发现只有5个pod是ready的。</p>
<p>删除"webhook-1" pod所在的节点的"calico-node" pod,发现该"calico-node" pod启动失败。</p>
<h4 id="问题分析-2">问题分析</h4>
<p>在上述错误中,"10.233.0.1"为kubernetes apiserver的service cluster IP,由于"clico-node" pod使用的是<code>hostnetwork</code>,因此可以直接在node上测试联通性,使用<code>telnet 10.233.0.1 443</code>测试,发现果然不通。</p>
<p>calico的<code>/etc/cni/net.d/10-calico.conflist</code>配置文件中定义了连接apiserver所需的<code>kubeconfig</code>文件:</p>
<pre><code class="language-json">{
"name": "cni0",
"cniVersion":"0.3.1",
"plugins":[
{
...
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
...
]
}
</code></pre>
<p>而<code>/etc/cni/net.d/calico-kubeconfig</code>中就定义了连接apiserver所需的地址和端口,因此只需将该地址端口换成apiserver pod的地址和端口应该就可以解决该问题:</p>
<pre><code class="language-yaml"># cat /etc/cni/net.d/calico-kubeconfig
# Kubeconfig file for Calico CNI plugin.
apiVersion: v1
kind: Config
clusters:
- name: local
cluster:
server: https://:443
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0...
users:
- name: calico
user:
token: eyJhbGciOiJSUzI1NiIsImtpZC...
contexts:
- name: calico-context
context:
cluster: local
user: calico
</code></pre>
<p>Calico提供了如下两个环境变量用于修改生成的kubeconfig中的apiserver的地址和端口,将如下环境变量加入calico的daemonset,重新创建<code>calico-node</code> pod即可:</p>
<pre><code class="language-yaml">- name: KUBERNETES_SERVICE_HOST
value: <api-server-pod-ip>
- name: KUBERNETES_SERVICE_PORT
value: <api-server-pod-port>
</code></pre>
<p>至此,问题基本解决。由于错误的操作,该集群出现了大量问题,后续可以通过驱逐节点pod的方式,重新初始化整个节点,逐步重置集群节点配置。</p>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:charlieroro,转载请注明原文链接:https://www.cnblogs.com/charlieroro/p/18493461</p><br><br>
来源:https://www.cnblogs.com/charlieroro/p/18493461
頁:
[1]