Kubernetes中Nginx Ingress仅路由同节点Pod的问题排查
我在裸金属环境搭建了包含1个master节点和2个worker节点的Kubernetes集群:
[root@kubemaster helm-chart]$ kubectl get nodes NAME STATUS ROLES AGE VERSION kubemaster Ready control-plane 53d v1.26.1 kubenode-1 Ready <none> 53d v1.26.1 kubenode-2 Ready <none> 17d v1.26.2
部署了一个简单的echo服务器:
[root@kubemaster helm-chart]$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES echo-67456bbd77-ttgx7 1/1 Running 0 50m X.X.X.X kubenode-2 <none> <none>
同时安装了Nginx Ingress Controller,2个副本分别运行在两个worker节点上:
[root@kubemaster helm-chart]$ kubectl get pods -o wide -n nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES bkk-ingress-5c56c5868-lhd98 1/1 Running 0 19m Y.Y.Y.Y kubenode-1 <none> <none> bkk-ingress-5c56c5868-xj8jh 1/1 Running 0 60m X.X.X.X kubenode-2 <none> <none>
Ingress规则配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: echo spec: ingressClassName: nginx rules: - host: kong.example http: paths: - path: /echo pathType: ImplementationSpecific backend: service: name: echo port: number: 80
echo服务配置:
kind: Service apiVersion: v1 metadata: name: echo namespace: default spec: type: ClusterIP ports: - name: low protocol: TCP port: 80 targetPort: 8080 selector: app: echo
异常现象
访问kubenode-2上的Nginx Controller(echo应用也在该节点)时:
curl -i http://KUBENODE_2_IP:MY_PORT/echo -H 'Host: kong.example'
请求完全正常;但将IP替换为kubenode-1的IP时,请求直接超时。两台节点均已开放MY_PORT端口,环境为CentOS 8。后续排查Ingress Controller日志,发现报错为连接上游Pod超时。
以下是针对该问题的排查和配置方案:
验证跨节点Pod连通性
先在kubenode-1上的Ingress Controller Pod内,直接访问echo Pod的IP和端口,确认网络是否可达:kubectl exec -n nginx bkk-ingress-5c56c5868-lhd98 -- curl -i http://X.X.X.X:8080如果这个命令超时,说明跨节点的Pod网络存在阻断,需要重点排查网络策略或防火墙。
检查节点防火墙规则
CentOS 8默认启用firewalld,需确保节点间允许Kubernetes Pod网段的流量通行:- 先确认集群的Pod网段(可通过CNI插件配置查看,比如flannel默认是10.244.0.0/16),然后添加规则:
firewall-cmd --add-source=你的Pod网段/16 --zone=public --permanent firewall-cmd --reload - 临时关闭SELinux测试是否是其导致的阻断:
如果关闭后恢复正常,需配置SELinux允许容器网络流量,或者添加对应的放行规则。setenforce 0
- 先确认集群的Pod网段(可通过CNI插件配置查看,比如flannel默认是10.244.0.0/16),然后添加规则:
确认CNI插件的路由配置
如果使用flannel、calico等CNI插件,检查kubenode-1上的路由表,确认是否存在指向kubenode-2的Pod网段路由:ip route若缺失对应路由,可重启CNI插件的DaemonSet Pod(比如flannel的Pod),或者手动添加路由:
ip route add X.X.X.X/32 via kubenode-2的节点IP dev 你的CNI网卡检查Ingress Controller端口占用
确认kubenode-1上的MY_PORT端口没有被其他进程占用:ss -tulnp | grep MY_PORT如果有其他进程占用,需停止该进程或修改Ingress Controller的端口配置。
开启详细日志定位问题
修改Nginx Ingress Controller的ConfigMap(通常在nginx命名空间下),添加更详细的上游日志格式:apiVersion: v1 kind: ConfigMap metadata: name: nginx-ingress-controller namespace: nginx data: log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'保存后重启Ingress Controller Pod,查看日志获取更具体的超时细节,进一步定位问题。
内容的提问来源于stack exchange,提问作者bkk

