Kubernetes NodePort服务超时问题排查(Multus CNI干扰嫌疑)
问题背景
在Microk8s 1.23(Ubuntu 20.04 LTS环境)中部署Web应用Pod,通过NodePort Service对外暴露后,访问localhost:30012出现超时,但使用microk8s kubectl port-forward pods/visualizer-nautic-77957b94c9-mww6p 8100:8100可正常访问。移除Multus CNI为Pod添加的MACVLAN网卡后,Service恢复正常。
部署配置
Deployment配置:
apiVersion: apps/v1 kind: Deployment metadata: name: visualizer-nautic labels: app: visualizer spec: replicas: 1 selector: matchLabels: app: visualizer template: metadata: annotations: k8s.v1.cni.cncf.io/networks: zenoh-network labels: app: visualizer spec: containers: - name: api image: hielito/visualizer:latest ports: - containerPort: 8100
NodePort Service配置:
apiVersion: v1 kind: Service metadata: name: visualizer-service spec: type: NodePort selector: app: visualizer ports: - port: 8100 targetPort: 8100 nodePort: 30012
问题原因
Multus为Pod添加MACVLAN网卡时,默认会将该网卡设置为Pod的默认路由出口。而Kubernetes Service的流量依赖集群默认CNI网络(如Microk8s自带的Calico)转发,Pod收到Service请求后,响应数据包会通过MACVLAN网卡流出,无法回到集群Service的网络栈,导致连接超时。而kubectl port-forward直接绕过Service,与Pod的默认网络接口建立连接,因此不受影响。
解决方案
方案1:调整Pod路由,集群流量走默认CNI网卡
添加Init容器,在Pod启动时修改路由规则,让集群ClusterIP段的流量走默认eth0网卡,其他流量走MACVLAN网卡。修改Deployment的spec.template.spec部分:
spec: initContainers: - name: set-route image: busybox:1.35 command: ["sh", "-c"] args: - | # 添加集群IP段路由(Microk8s默认ClusterIP段为10.152.183.0/24) ip route add 10.152.183.0/24 dev eth0 # 如需保留MACVLAN为默认路由可跳过下面两行,否则设置eth0为默认路由 # ip route del default # ip route add default dev eth0 securityContext: privileged: true containers: - name: api image: hielito/visualizer:latest ports: - containerPort: 8100
方案2:修改Multus NetworkAttachmentDefinition,禁用默认路由
编辑zenoh-network的NetworkAttachmentDefinition,配置仅特定网段走MACVLAN,并禁止其覆盖默认路由:
apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: zenoh-network spec: config: |- { "cniVersion": "0.3.1", "type": "macvlan", "master": "eth0", # 替换为你的宿主机物理网卡 "mode": "bridge", "ipam": { "type": "host-local", "subnet": "192.168.100.0/24", "rangeStart": "192.168.100.10", "rangeEnd": "192.168.100.20" }, "routes": [ { "dst": "192.168.0.0/16", # 指定仅该网段走MACVLAN "gw": "192.168.100.1" } ], "disableDefaultRoute": true # 禁止MACVLAN设置默认路由 }
方案3:配置网络策略(排除干扰)
添加网络策略,确保集群内部Service流量可访问Pod的8100端口:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-service-access spec: podSelector: matchLabels: app: visualizer ingress: - from: - ipBlock: cidr: 10.152.183.0/24 # 集群Service的ClusterIP段 ports: - protocol: TCP port: 8100
验证
部署修改后的资源后,访问localhost:30012即可正常加载应用。可通过kubectl exec <pod-name> -- ip route查看Pod内路由规则是否生效。
内容的提问来源于stack exchange,提问作者Francisco

