dial tcp 10.96.0.1:443: connect: network is unreachable

K8s CoreDNS启动失败排查

今天,在部署 k8s 集群时,发现 CoreDNS 一直无法启动成功,报类似标题所示的错误,现记录下问题排查的主体过程:

1. 首先,正常情况下,所有 Node 应该都能够访问 10.96.0.1:443,到 CoreDNS Pod 所在节点,执行:

# curl https://10.96.0.1
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

   无需关心返回的内容,有返回即代表 10.96.0.1:443 是可以访问的,如果不能访问进入第 2 步

 2. 查看对应 Node 上的 kube-proxy 日志,根据日志判断 iptables 规则设置有无异常

E1017 09:28:33.524808       1 proxier.go:688] Failed to ensure that filter chain KUBE-EXTERNAL-SERVICES exists: error creating chain "KUBE-EXTERNAL-SERVICES": exit status 3: modprobe: ERROR: could not insert 'ip6_tables': Exec format error
ip6tables v1.6.0: can't initialize ip6tables table `filter': Table does not exist (do you need to insmod?)
Perhaps ip6tables or your kernel needs to be upgraded.
E1017 09:29:03.528199       1 proxier.go:688] Failed to ensure that filter chain KUBE-EXTERNAL-SERVICES exists: error creating chain "KUBE-EXTERNAL-SERVICES": exit status 3: modprobe: ERROR: could not insert 'ip6_tables': Exec format error
ip6tables v1.6.0: can't initialize ip6tables table `filter': Table does not exist (do you need to insmod?)
Perhaps ip6tables or your kernel needs to be upgraded.

     如有异常,则根据错误提示,配置 Node 解决 iptables 故障

<think>我们正在解决Kubernetes中provisioner(例如nfs-client-provisioner)无法连接API Server的问题,错误信息为: "Error getting server version: Get https://10.96.0.1:443/version?timeout=32s: dial tcp 10.96.0.1:443: i/o timeout" 根据引用[1][2][3][4]的描述,该问题表现为provisioner无法访问Kubernetes API Server(默认服务地址为10.96.0.1:443)。常见原因包括: 1. 网络插件(如Calico、Flannel)未正常运行,导致Pod无法访问ClusterIP。 2. 节点防火墙或路由规则阻止了Pod到API Server的通信。 3. 虚拟机挂起后重启导致网络配置异常(引用[4])。 4. 节点IP地址变更导致kube-proxy或网络插件配置失效。 引用[5]提供了一个相关案例:通过修改docker的cgroup驱动并重置kubeadm解决类似问题,但该案例针对的是kubelet连接问题,与当前问题场景不同,仅供参考。 以下是系统化的排查步骤: ### 步骤1:检查Kubernetes核心组件状态 ```bash kubectl get pods -n kube-system # 检查网络插件、kube-proxy等组件是否运行正常 ``` ### 步骤2:验证API Server的可访问性 在出现问题的Provisioner Pod所在节点上执行: ```bash # 进入Provisioner Pod所在节点 kubectl get pods -o wide # 查看Provisioner Pod运行在哪个节点 # 登录该节点,尝试从节点直接访问API Server curl -k https://10.96.0.1:443/version # 预期返回:{"kind":"Status","apiVersion":"v1","status":"Failure","message":"forbidden: User \"system:anonymous\" cannot get path \"/version\"","reason":"Forbidden","details":{},"code":403} # 注意:403状态码表示网络可达但未授权,这证明网络连接正常。如果出现超时(Timeout)则说明网络不通。 # 如果节点无法访问API Server,检查节点的网络配置: ip route show # 查看路由表 iptables -L -n -t nat # 检查NAT规则 ``` ### 步骤3:检查网络插件 如果节点无法访问API Server,重点检查网络插件: ```bash # 查看网络插件Pod日志 kubectl logs -n kube-system <network-plugin-pod-name> ``` ### 步骤4:检查kube-proxy kube-proxy负责将ClusterIP(如10.96.0.1)路由到API Server的实际端点: ```bash # 检查kube-proxy日志 kubectl logs -n kube-system kube-proxy-xxxxx # 确认kube-proxy是否正确配置 kubectl get cm -n kube-system kube-proxy -o yaml # 查看配置 ``` ### 步骤5:检查Provisioner Pod的网络连通性 在Provisioner Pod内部执行诊断: ```bash kubectl exec -it <provisioner-pod-name> -- sh # 在Pod内执行: curl -v https://10.96.0.1:443/version # 若超时,则检查Pod的DNS和网络: nslookup kubernetes.default # 应解析为10.96.0.1 ``` ### 步骤6:排查虚拟机挂起后的网络问题(引用[4]) 虚拟机挂起后重启可能导致网络接口异常或路由丢失: ```bash # 重启网络相关服务(根据操作系统) systemctl restart network # CentOS/RHEL systemctl restart networking # Ubuntu # 重启容器运行时和kubelet systemctl restart docker systemctl restart kubelet ``` ### 步骤7:重置kube-proxy(可选) 如果kube-proxy配置损坏,可尝试重置: ```bash kubectl delete pod -n kube-system -l k8s-app=kube-proxy ``` ### 步骤8:完全重置集群(终极方案) 如果以上步骤无效,考虑重置集群(谨慎操作): ```bash kubeadm reset -f systemctl stop kubelet systemctl stop docker rm -rf /var/lib/cni/ rm -rf /var/lib/kubelet/* rm -rf /etc/cni/ ifconfig cni0 down ifconfig flannel.1 down ifconfig docker0 down ip link delete cni0 ip link delete flannel.1 systemctl start docker systemctl start kubelet kubeadm init ... # 重新初始化 ``` ### 预防措施 1. **避免虚拟机挂起**:生产环境推荐使用物理机或可靠云主机。 2. **网络插件选择**:使用经过充分测试的网络插件(如Calico、Flannel),并定期更新。 3. **健康检查**:为关键组件(如provisioner)添加就绪探针,确保网络连通后才提供服务。 §§相关问题§§ 1. Kubernetes中如何诊断Pod网络问题? 2. 如何配置Kubernetes网络插件以实现高可用? 3. 虚拟机挂起后Kubernetes节点状态异常的恢复方法有哪些?</think>### Kubernetes Provisioner "Error getting server version: i/o timeout" 问题分析与解决 该错误表明 provisioner(如 NFS-Client Provisioner)无法连接到 Kubernetes API Server,通常发生在存储插件启动时。以下是根本原因和系统化解决方案: --- #### 问题根源分析 1. **网络连通性问题**(最常见) - Pod 无法访问 API Server 的 ClusterIP(默认 `10.96.0.1:443`) - 错误表现:`dial tcp 10.96.0.1:443: i/o timeout` 或 `no route to host`[^1][^2][^3][^4] 2. **核心组件异常** - kube-proxy 服务未运行或配置错误 - 网络插件(Calico/Flannel)故障 - 节点路由表损坏(虚拟机挂起后常见) 3. **证书或认证问题** - ServiceAccount 权限不足 - kubeconfig 配置错误 --- #### 解决方案(分步操作) ##### 步骤1:验证基础网络连通性 在 **Provisioner Pod 所在节点** 执行: ```bash # 检查能否解析API Server nslookup kubernetes.default.svc.cluster.local # 测试API Server端口连通性 telnet 10.96.0.1 443 # 或使用 nc -zv 10.96.0.1 443 ``` - 🔴 若失败:检查节点防火墙规则,确保开放 443/TCP 端口 - 🔴 若 `no route to host`:检查节点路由表 `ip route show` ##### 步骤2:检查核心组件状态 ```bash kubectl get pods -n kube-system | grep -E 'kube-proxy|calico|flannel' kubectl logs -n kube-system <kube-proxy-pod-name> ``` - 常见修复操作: ```bash # 重启kube-proxy kubectl delete pod -n kube-system -l k8s-app=kube-proxy # 重启网络插件(以Calico为例) kubectl rollout restart daemonset calico-node -n kube-system ``` ##### 步骤3:诊断DNS解析 在 **Provisioner Pod 内部** 执行诊断: ```bash kubectl exec -it <provisioner-pod-name> -- sh # 在Pod内执行: nslookup kubernetes.default.svc.cluster.local curl -vk https://kubernetes.default.svc.cluster.local:443/version ``` - 🔴 若DNS解析失败:检查CoreDNS状态 `kubectl get pods -n kube-system -l k8s-app=kube-dns` ##### 步骤4:检查RBAC权限(关键!) 确保Provisioner的ServiceAccount有足够权限: ```yaml # 示例RBAC配置(nfs-client-provisioner) apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-provisioner-runner rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] # 必须包含对version资源的访问权限! - apiGroups: [""] resources: ["version"] verbs: ["get"] ``` ##### 步骤5:虚拟机挂起后的特殊处理[^4] 虚拟机恢复后执行: ```bash # 重启容器运行时和kubelet sudo systemctl restart docker && sudo systemctl restart containerd sudo systemctl restart kubelet # 重置网络接口 sudo ip link set cni0 down && sudo brctl delbr cni0 sudo systemctl restart network ``` ##### 步骤6:终极重建方案 当以上无效时,完全重置集群组件: ```bash # 1. 重置kubeadm(所有节点执行) sudo kubeadm reset -f # 2. 清理网络残留 sudo ipvsadm --clear sudo rm -rf /etc/cni/net.d/* # 3. 重启节点 sudo reboot # 4. 重新初始化集群 sudo kubeadm init --apiserver-advertise-address=<node-ip> ``` --- #### 预防措施 1. **节点维护规范**: ```mermaid graph LR A[关机前] --> B[清空节点 kubectl drain] B --> C[关闭节点] C --> D[恢复后执行 kubectl uncordon] ``` 2. **配置健康检查**: ```yaml # 在Provisioner部署中添加就绪探针 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 10 periodSeconds: 5 ``` 3. **网络插件优化**: - 使用Calico的BGP模式替代Flannel - 启用kube-proxy的IPVS模式:`kubectl edit cm -n kube-system kube-proxy` → 设置 `mode: "ipvs"` > **关键提示**:生产环境建议使用 `kubeadm upgrade` 而非直接关机维护,避免网络配置丢失[^4]。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值