K8S节点失联惊魂48小时:记一次排查k8s节点无法访问的过程
现象描述
在 Kubernetes 集群中观察到以下服务访问异常:
-
应用 A 的 NodePort 访问表现
- 正常路径:通过节点 A 的 IP + NodePort 端口(
<NodeA_IP>:<NodePortA>
)可成功访问应用 A。 - 异常路径:通过节点 B 的 IP + NodePort 端口(
<NodeB_IP>:<NodePortA>
)无法访问应用 A,请求被拒绝或超时。
- 正常路径:通过节点 A 的 IP + NodePort 端口(
-
应用 B 的 NodePort 访问表现
- 正常路径:通过节点 A 或节点 B 的 IP + NodePort 端口(
<NodeA_IP>:<NodePortB>
或<NodeB_IP>:<NodePortB>
)均可成功访问应用 B。
- 正常路径:通过节点 A 或节点 B 的 IP + NodePort 端口(
附:现象对比表格**
对象 | 节点 A 访问结果 | 节点 B 访问结果 | 结论 |
---|---|---|---|
应用 A | ✅ 成功 | ❌ 失败 | 跨节点流量转发异常 |
应用 B | ✅ 成功 | ✅ 成功 | 服务配置正常 |
初步分析
SVC的externalTrafficPolicy
- 问题定位:初步怀疑是 Kubernetes Service(SVC)的
externalTrafficPolicy
配置导致的问题。
查看 SVC 的 externalTrafficPolicy 设置
kubectl get svc 应用A -n 命名空间 -o yaml | grep externalTrafficPolicy
结果显示:
externalTrafficPolicy: Cluster # 代表是集群内部流量
# externalTrafficPolicy: Local # 代表是节点本地流量,即只能通过pod所在机器进行访问
以上结果表明,应用 A 的 SVC 配置为 Cluster
,理论上应该允许跨节点访问。
进一步分析
查看iptables规则,确认流量转发是否正常。
# 查看出问题的端口规则
iptables -L -n | grep 应用A的nodeport
REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 /* 命名空间/应用:http-80 has no endpoints */ ADDRTYPE match dst-type LOCAL tcp dith icmp-port-unreachablea
# 查看该条规则属于哪表哪,默认和表是filter
iptables -L -n --line-numbers | grep 应用A的nodeport -C 10
#返回
Chain KUBE-EXTERNAL-SERVICES (2 references)
num target prot opt source destination
1 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 /* 一些注释 */
通过上面的命令,我们发现节点B上出现了这条规则,这表明流量被拒绝了,拒绝的原因是没有endpoint。而正常的机器上面,无该规则。
解决方案
- 检查SVC的Endpoints
- 确认SVC是否有对应的endpoints。
kubectl get endpoints 应用A -n 命名空间
若无任何endpoint,则需要排查为什么没有创建endpoint。
2. 有endpoints,但iptables规则错误
根据实验,删除kube-proxy和calico的pod的pod,让其重新生成iptables规则,仍旧无法访问。
只有去删除该节点上的此条REJECT规则,才能使流量正常转发。
# 删除这条规则
Chain KUBE-EXTERNAL-SERVICES (2 references)
num target prot opt source destination
1 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 /* 一些注释 */
iptables -D KUBE-EXTERNAL-SERVICES 1 -t filter
结论
虽然已经能够进行访问了,但始终未找到为何会产生这条规则的原因,后续还需继续排查。经过此次排查分析,自己也对iptables的四表五链有了更深的理解。
评论区