本文介绍各种常见的网络问题以及排错方法,包括 Pod 访问异常、Service 访问异常以及网络安全策略异常等。
说到 Kubernetes 的网络,其实无非就是以下三种情况之一
-
Pod 访问容器外部网络
-
从容器外部访问 Pod 网络
-
Pod 之间相互访问
当然,以上每种情况还都分别包括本地访问和跨主机访问两种场景,并且一般情况下都是通过 Service 间接访问 Pod。
排查网络问题基本上也是从这几种情况出发,定位出具体的网络异常点,再进而寻找解决方法。网络异常可能的原因比较多,常见的有
-
CNI 网络插件配置错误,导致多主机网络不通,比如
-
sysctl net.ipv4.ip_forward
-
sysctl net.bridge.bridge-nf-call-iptables
-
IP 网段与现有网络冲突
-
插件使用了底层网络不支持的协议
-
忘记开启 IP 转发等
-
Pod 网络路由丢失,比如
-
kubenet 要求网络中有 podCIDR 到主机 IP 地址的路由,这些路由如果没有正确配置会导致 Pod 网络通信等问题
-
在公有云平台上,kube-controller-manager 会自动为所有 Node 配置路由,但如果配置不当(如认证授权失败、超出配额等),也有可能导致无法配置路由
-
主机内或者云平台的安全组、防火墙或者安全策略等阻止了 Pod 网络,比如
-
非 Kubernetes 管理的 iptables 规则禁止了 Pod 网络
-
公有云平台的安全组禁止了 Pod 网络(注意 Pod 网络有可能与 Node 网络不在同一个网段)
-
交换机或者路由器的 ACL 禁止了 Pod 网络
Flannel 网络插件非常容易部署,只要一条命令即可。然而,部署完成后,Flannel Pod 有可能会碰到初始化失败的错误:
查看日志会发现
这一般是由于 SELinux 开启导致的,关闭 SELinux 既可解决。有两种方法:
-
修改 /etc/selinux/config 文件方法:SELINUX=disabled
-
通过命令临时修改(重启会丢失):setenforce 0
如果 Node 上安装的 Docker 版本大于 1.12,那么 Docker 会把默认的 iptables FORWARD 策略改为 DROP。这会引发 Pod 网络访问的问题。解决方法则在每个 Node 上面运行 iptables -P FORWARD ACCEPT,比如
如果使用了 flannel/weave 网络插件,更新为最新版本也可以解决这个问题。
DNS 无法解析也有可能是 kube-dns 服务异常导致的,可以通过下面的命令来检查 kube-dns 是否处于正常运行状态
如果 kube-dns 处于 CrashLoopBackOff 状态,那么需要查看 kube-dns Pod 的日志,根据日志来修复 DNS 服务。
如果 kube-dns Pod 处于正常 Running 状态,则需要进一步检查是否正确配置了 kube-dns 服务:
如果 kube-dns service 不存在,或者 endpoints 列表为空,则说明 kube-dns service 配置错误,可以重新部署 kube-dns service。
Service 无法通过 ClusterIP 访问访问 Service ClusterIP 失败时,可以首先确认是否有对应的 Endpoints
kubectl get endpoints <service-name>
复制代码
如果该列表为空,则有可能是该 Service 的 LabelSelector 配置错误,可以用下面的方法确认
如果 Endpoints 正常,可以进一步检查
-
Pod 的 containerPort 与 Service 的 containerPort 是否对应
-
直接访问 podIP:containerPort 是否正常
再进一步,即使上述配置都正确无误,还有其他的原因会导致 Service 无法访问,比如
-
Pod 内的容器有可能未正常运行或者没有监听在指定的 containerPort 上
-
CNI 网络或主机路由异常也会导致类似的问题
-
kube-proxy 服务有可能未启动或者未正确配置相应的 iptables 规则
这通常是 hairpin 配置错误导致的,可以通过 Kubelet 的 --hairpin-mode 选项配置,可选参数包括 "promiscuous-bridge"、"hairpin-veth" 和 "none"(默认为"promiscuous-bridge")。
对于 hairpin-veth 模式,可以通过以下命令来确认是否生效
而对于 promiscuous-bridge 模式,可以通过以下命令来确认是否生效
很多扩展服务需要访问 Kubernetes API 查询需要的数据(比如 kube-dns、Operator 等)。通常在 Kubernetes API 无法访问时,可以首先通过下面的命令验证 Kubernetes API 是正常的:
如果出现超时错误,则需要进一步确认名为 kubernetes 的服务以及 endpoints 列表是正常的:
然后可以直接访问 endpoints 查看 kube-apiserver 是否可以正常访问。无法访问时通常说明 kube-apiserver 未正常启动,或者有防火墙规则阻止了访问。
但如果出现了 403 - Forbidden 错误,则说明 Kubernetes 集群开启了访问授权控制(如 RBAC),此时就需要给 Pod 所用的 ServiceAccount 创建角色和角色绑定授权访问所需要的资源。
作者:漫谈云原生
链接:https://juejin.cn/post/6844903576058200072
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。