Kubernetes v1.10中Pod无法通过Service IP访问自身问题求助
解决Kubernetes 1.10 + Flannel环境下Pod无法通过Service IP访问自身的问题
我之前维护同版本K8s集群时碰到过完全一样的问题,结合Flannel的CNI特性和kubelet的hairpin模式限制,给你几个落地的解决步骤:
1. 先搞懂hairpin模式的兼容性问题
你看到的kubelet报错是核心原因:promiscuous-bridge模式只适配kubenet CNI,而你用的是Flannel,所以kubelet自动降级到hairpin-veth模式。但这个降级后的模式可能没正确生效,或者需要额外配置才能让Pod访问自身Service。
2. 正确配置kubelet的hairpin-veth模式
对于kubeadm部署的集群,调整kubelet配置的步骤如下:
- 找到kubelet的主配置文件:K8s 1.10中通常是
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf,部分环境下是/var/lib/kubelet/config.yaml - 修改配置,明确设置
hairpin-mode: "hairpin-veth"(如果是旧版systemd参数,就在KUBELET_CONFIG_ARGS里添加--hairpin-mode=hairpin-veth) - 重启kubelet服务:
sudo systemctl daemon-reload sudo systemctl restart kubelet - 验证配置是否生效:在节点上找到对应Pod的veth设备(用
ip link查看,名字类似vethXXXX),运行ip link show <veth设备名>,如果看到hairpin on的标记,说明配置生效。
3. 检查Flannel的配置和版本兼容性
Flannel版本需要和K8s 1.10匹配,建议使用v0.10.0版本(官方推荐适配K8s 1.10的版本)。同时检查Flannel的DaemonSet配置:
- 查看kube-system命名空间下的Flannel ConfigMap:
kubectl get configmap kube-flannel-cfg -n kube-system -o yaml - 确保Flannel启动参数中没有禁用hairpin功能,比如手动指定
--hairpin-mode=veth(部分版本默认开启,但手动配置更稳妥)
4. 验证连通性和排查iptables规则
- 进入问题Pod内部,执行
curl <Service-IP>:<端口>测试,同时在节点上用tcpdump抓包分析:
观察数据包是否有发送和回应。tcpdump -i flannel.0 host <你的Pod-IP> and host <你的Service-IP> - 检查kube-proxy的iptables规则是否正确生成:
应该能看到对应的DNAT和SNAT规则,如果规则缺失,重启kube-proxy服务:iptables-save | grep <你的Service-IP>kubectl rollout restart daemonset kube-proxy -n kube-system
5. 临时应急方案(不推荐长期使用)
如果上面的配置都没生效,可以临时修改Service的externalTrafficPolicy为Local,或者给Pod设置hostNetwork: true(后者会让Pod共享节点网络,存在安全和端口冲突风险,仅用于测试)。
内容的提问来源于stack exchange,提问作者Phagun Baya




