hostNetwork 与 hostPort 端口冲突

背景:持续两天的“端口战”

集群连续两天爆发诡异现象:

  1. 随机性端口冲突:部分节点上的 Pod 启动时报错 Bind: address already in use,但同一节点其他 Pod 却正常。
  2. 幽灵端口占用:通过 netstat -tulnp 检查节点端口,但是显示 80 端口“没有被占用”,但 Pod 日志显示“端口被占用”。
  3. 重启失效:重启节点后问题暂时消失,但几小时后再度爆发,运维团队“不停救火”。

hostNetwork 与 hostPort 的“随机态”

1. hostNetwork 的本质:使用宿主机的网络命名空间

当 Pod 配置 hostNetwork: true 时,直接共享宿主机的网络命名空间(Network Namespace)。效果相当于在宿主机上运行进程:Pod 监听的端口会直接绑定到宿主机的 IP 和端口上。

举例:相当于租客(Pod)直接住进了房东(宿主机)的房间,房东的家具(端口)被租客随意使用。

# DaemonSet 示例(监控采集Agent,例如:node_exporter)
spec:
  template:
    spec:
      hostNetwork: true   # 共享宿主机网络
      containers:
      - name: log-agent
        ports:
        - containerPort: 80  # 监听宿主机80端口

2. hostPort 的真相:网络劫持

当 Pod 配置 hostPort: 80 时,Kubernetes 会通过 iptables DNAT 规则,将宿主机的 80 端口流量转发到 Pod 的容器端口。此配置并不会在宿主机上真正监听端口,而是通过 iptables 实现“流量劫持”。

举例:相当于在房东门口挂了个牌子(iptables规则),把访客引导到租客(Pod)的房间,但房东自己并没有占用房间。

# 普通 Pod 示例(Web应用)
spec:
  containers:
  - name: web-app
    ports:
    - containerPort: 8080
      hostPort: 80  # 通过宿主机80端口暴露服务

3. 发生冲突:当 hostNetwork 遇上 hostPort

现象

  1. 场景一:DaemonSet 的 Pod 先启动 → 宿主机 80 端口被真实占用 → 普通 Pod 因 iptables 规则冲突无法启动。
  2. 场景二:普通 Pod 先启动 → iptables 规则生效 → DaemonSet 的 Pod 因端口已被监听无法启动。

结论:谁先启动谁存活,后者必崩溃。

总结:

1.非必要不用 hostNetwork,用 hostPort 不如用 NodePort,用 NodePort 不如用 Ingress

2.像管理物理服务器一样谨慎对待 hostNetwork

附属:故障排查命令

场景 命令
检查宿主机端口 netstat -tulnp | grep <端口>
查看容器网络命名空间 nsenter -n -t <容器PID> netstat -tulnp
追踪 iptables 规则 iptables -t nat -L | grep <端口>
快速定位冲突 Pod kubectl get pods -A -o json | jq '.items[] | select(.spec.hostNetwork == true)'