通用排查思路
Kubernetes 集群内不同服务之间的网络通信出现异常,表现为请求超时、连接失败或响应缓慢,导致服务间依赖关系中断,依赖服务的功能不可用或性能下降,甚至可能波及整个微服务架构,引发连锁反应,造成系统整体不稳定。
排查方法:
第一步:检查Pod网络配置与状态
查看Pod网络配置:
kubectl describe pod -n <namespace>
这里要重点关注Events部分是否有网络配置相关的错误提示,以及IP地址是否已正确分配,如果没有异常则再检查Pod运行状态。
kubectl get pods -n <namespace>
查看Pod是否处于Running状态,如果不是,检查其状态(如CrashLoopBackOff)并进一步分析日志。
第二步:网络连通性测试
这里主要还是通过常用的ping命令来测试。
进行Pod间连通性测试,在有问题的两个Pod中分别执行以下命令测试连通性,例如使用ping或nc(netcat)。
# 在源Pod中执行
kubectl exec -it <source-pod-name> -n <namespace> -- ping <destination-pod-ip>
# 或者使用nc测试端口连通性
kubectl exec -it <source-pod-name> -n <namespace> -- nc -zv <destination-pod-ip> <port>
第三步:查看网络策略规则
如果以上都没有问题,则有可能是网络策略问题,执行如下命令确认是否有网络策略限制了Pod间的访问。
kubectl get networkpolicies -n <namespace>
如果有相关策略,检查其spec-ingress和spec-egress规则,确保没有意外地拒绝了必要的通信。
第四步:检查Service配置
kubectl describe service <service-name> -n <namespace>
kubectl get endpoints <service-name> -n <namespace>
再次执行上述命令来确认Service的类型、选择器、端口配置是否正确,并确保Service有对应的Endpoints,即后端Pod列表。
第五步:查看集群日志
根据异常Pod所在节点,检查节点上的kubelet、网络插件的日志,寻找有关网络配置、连接尝试或错误的信息。
kubectl logs <problematic-pod-name> -n <namespace>
1 . Pod访问外部服务超时
现象: Pod尝试访问外部服务(如数据库或API)时超时。
原因分析:通常情况下是egress规则未正确设置,导致流量无法流出集群。
排查方法:
第一步:确认网络策略
首先,还是检查是否有网络策略限制了Pod访问外部网络,确保没有规则阻止Egress(外出)流量。
kubectl get networkpolicies -n <namespace>
第二步:查看Pod网络配置
确认Pod的网络配置,尤其是iptables规则和路由表。进入Pod内部检查:
kubectl exec -it <pod-name> -n <namespace> -- bash
在Pod内执行以下命令查看路由表:
ip route
并检查iptables规则:
iptables -L -nv
第三步:测试外部连接
直接在Pod中尝试访问外部服务,比如ping一个公共DNS服务器或测试端口连接:
ping 8.8.8.8
nc -vz example.com 443
第四步:DNS解析测试
如果服务访问依赖域名,检查DNS解析是否正常:
nslookup www.baidu.com
第五步:Egress配置检查
如果发现是因为网络策略限制了Egress流量,那么可以创建或修改一个网络策略来允许外部访问。例如,允许所有Egress流量的网络策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}
然后应用此策略:
kubectl apply -f allow-egress.yaml -n <namespace>
生产环境中请确保根据实际情况调整策略,仅开放必要的端口和目标,保证系统的安全性。
2 . 服务ClusterIP不可达
现象: 服务的ClusterIP地址无法从集群内部访问。
原因分析: 服务的Kubernetes Service配置错误,或kube-proxy服务异常。
排查方法:
第一步:确认服务状态
检查服务是否已经创建并且状态正常:
kubectl get svc -n <namespace>
需要确保服务存在且其类型为ClusterIP。
第二步:服务详情检查
查看服务的详细信息,重点关注ClusterIP、端口映射和Selector是否配置正确:
kubectl describe svc <service-name> -n <namespace>
确认Endpoints列表中至少有一个Pod IP,这表明服务能够找到匹配的Pod。
第三步:验证DNS解析
在有问题的Pod中,尝试解析服务名以确认DNS是否工作正常:
kubectl exec -it <problematic-pod-name> -n <namespace> -- nslookup <service-name>
此时正常来说应能看到服务对应的ClusterIP地址。
第四步:网络连通性测试
从问题Pod向服务的ClusterIP和端口发起ping或TCP连接测试:
kubectl exec -it <problematic-pod-name> -n <namespace> -- bash -c "nc -zv <service-cluster-ip> <service-port>"
第五步:kube-proxy状态检查
kube-proxy负责服务的网络代理,确保它在所有节点上运行正常:
kubectl get pods -n kube-system | grep kube-proxy
如果kube-proxy有问题,查看其日志:
kubectl logs <kube-proxy-pod-name> -n kube-system
第六步:重启kube-proxy
如果以上都没有异常,作为最后的尝试,可以在所有节点上重启kube-proxy服务,可能会解决可能的临时问题,不过一定需要谨慎!:
sudo systemctl restart kube-proxy
3 . Ingress 502 Bad Gateway
当使用Ingress资源时遇到502 Bad Gateway错误,这意味着Ingress控制器无法从后端服务正确接收响应。
第一步:检查Ingress资源配置
首先,确保Ingress资源配置正确,包括路径、服务名称、端口等:
kubectl describe ingress <ingress-name> -n <namespace>
第二步:检查Ingress资源配置
检查关联的服务和Pod是否运行正常:
kubectl get svc -n <namespace>
kubectl get pods -n <namespace>
确认Pod无CrashLoopBackOff或Error状态,服务有正确的端口映射和Selector。
第三步:检查Endpoints
验证服务是否绑定了正确的Pod:
kubectl describe svc <service-name> -n <namespace>
在输出中查找Endpoints部分,确保有Pod IP列表。
第四步:查看Ingress控制器日志
根据使用的Ingress控制器(如Nginx Ingress Controller、Istio Ingress Gateway等),获取其日志以获取更多信息:
# 对于Nginx Ingress Controller
kubectl logs -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx
分析日志中是否有与502错误相关的错误信息或警告。
第五步:确认后端服务可达性
从Ingress所在节点或Pod内尝试直接访问后端服务,以排除网络问题:
kubectl run -it --rm --restart=Never debug --image=busybox -- /bin/sh -n <namespace>
# 在新Pod中执行
nc -vz <backend-service-ip> <service-port>
第六步:重启Ingress控制器
如果上述步骤未解决问题,尝试重启Ingress控制器Pod:
kubectl delete pod <ingress-controller-pod-name> -n <ingress-controller-namespace>
附:常用k8s排查命令
容器网络故障
确认容器是否已正确启动并运行,并且是否已被正确配置为使用正确的网络。
执行命令,确认 Pod 是否已正确启动并运行。
kubectl get pods
执行命令,确认容器的网络配置是否正确。
kubectl describe pod <pod-name>
检查 Pod 和容器的网络配置,例如 IP 地址、子网掩码、网关、DNS 等是否正确配置。
执行命令 ,查看容器的网络接口信息。
kubectl exec <pod-name> -- ifconfig
检查网络插件是否正常工作,并尝试重启网络插件。
如果使用 Flannel 网络插件,执行命令 查看 Flannel 的日志信息。
kubectl logs -n kube-system -l k8s-app=flannel
如果使用 Calico 网络插件,执行命令,查看 Calico 的日志信息。
kubectl logs -n kube-system -l k8s-app=calico-node
重启网络插件:如果使用 Flannel 网络插件,执行命令
kubectl delete pod -n kube-system -l k8s-app=flannel
如果使用 Calico 网络插件,执行命令。
kubectl delete pod -n kube-system -l k8s-app=calico-node
检查网络设备是否正常工作,例如交换机、路由器、防火墙等是否出现故障。
检查网络设备的日志或配置信息,确认网络设备是否正常工作。
尝试使用 Kubernetes 工具进行诊断,例如 kubectl,以查看 Pod 和容器的状态和日志。
执行命令,查看容器的日志信息。
kubectl logs <pod-name>
执行命令 ,查看容器的状态信息。
kubectl describe pod <pod-name>
如果以上方法无法解决问题,可以考虑重新部署容器网络或更换网络插件。
如果使用 Flannel 网络插件,执行命令 重新部署 Flannel 网络插件。
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml && kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml,
如果使用 Calico 网络插件,执行命令重新部署 Calico 网络插件。
kubectl delete -f https://docs.projectcalico.org/manifests/calico.yaml && kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
网络策略故障
查看所有网络策略:
kubectl get networkpolicies --all-namespaces
查看网络策略的详细信息:
kubectl describe networkpolicy <network-policy-name> -n <namespace>
检查网络策略的规则是否正确:
kubectl get networkpolicy <network-policy-name> -n <namespace> -o yaml
检查容器是否正确标记:
kubectl get pods --selector=<label-selector> -n <namespace> -o wide
检查容器的端口是否正确配置:
kubectl get pods <pod-name> -n <namespace> -o yaml
检查节点是否正确配置:
kubectl get nodes -o wide
检查网络设备是否正常工作:
kubectl logs <network-device-pod-name> -n <namespace>
如果你的Kubernetes集群使用的是Calico网络策略,你可以使用以下命令:
查看所有Calico网络策略:
kubectl get networkpolicies.projectcalico.org --all-namespaces
查看Calico网络策略的详细信息:
kubectl describe networkpolicy <network-policy-name> -n <namespace>
检查Calico网络策略的规则是否正确:
kubectl get networkpolicy <network-policy-name> -n <namespace> -o yaml
-
检查Calico网络设备是否正常工作:
kubectl logs -n kube-system -l k8s-app=calico-node
DNS 故障
-
检查网络设备是否连通:
ping <network-device-ip>
-
检查网络设备的日志信息:
kubectl logs <network-device-pod-name> -n <namespace>
-
检查网络设备的配置信息:
kubectl exec -it <network-device-pod-name> -n <namespace> -- <command> <arguments>
-
检查网络设备的版本信息:
kubectl exec -it <network-device-pod-name> -n <namespace> -- <command> <arguments>
-
检查网络设备的连接状态:
kubectl exec -it <network-device-pod-name> -n <namespace> -- <command> <arguments>