给 Pod 加 hostNetwork / hostPID / hostIPC 到底打通了什么?host 开头的字段彼此独立吗?DNS 为什么会变?hostPort 和 hostNetwork 有什么区别?这篇读命名空间编号、做端口冲突和 DNS 对照,把边界一项项量出来。
net pid ipc uts mnt 与节点相同的 节点 4026532605 4026532603 4026532602 4026532601 4026532596 plain 4026534862 4026535272 4026535257 4026535256 4026535271 hnet 4026532605 4026535269 4026535253 4026532601 4026535268 net,uts hpid 4026534992 4026532603 4026535264 4026535263 4026535280 pid hipc 4026535120 4026535278 4026532602 4026535266 4026535277 ipc
读 /proc/self/ns/*:节点的 net=4026532605、pid=4026532603、ipc=4026532602、uts=4026532601。plain 的五个编号全都和节点不同;hnet(hostNetwork)与节点相同的是 net 和 uts;hpid(hostPID)是 pid;hipc(hostIPC)是 ipc。每个开关只打通对应的命名空间,mnt 始终是容器自己的。
plain 的 IP=10.244.1.247;hnet 的 IP=172.18.0.2(= 节点 IP:True)
hnet 里的 hostname=kx-main-worker(节点名);plain 里的 hostname=plain(Pod 名)
hnet 里 ip addr 的网卡数 15,plain 里 11
hnet 里 netstat 能看到节点上 kubelet 等已经在监听的端口:'tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN\ntcp 0 0 :::10250 :::* LISTEN\ntcp 0 0 :::10256 :::* LISTEN'
hnet 里再监听 10250:nc: bind: Address already in use 退出码 1
plain 里监听 10250:punt! Terminated 退出码 143(自己的网络命名空间,不冲突)
DNS:hnet(dnsPolicy 默认 ClusterFirst,hostNetwork 下实际退回 Default)的 nameserver <本机局域网IP>;解析 kubernetes.default:;; connection timed out; no servers could be reached
hnet-dns(dnsPolicy: ClusterFirstWithHostNet)的 nameserver 10.96.0.10;解析:Name: kubernetes.default.svc.cluster.local Address: 10.96.0.1hostNetwork 下 Pod 的 IP 就是节点 IP(172.18.0.2),hostname 是节点名 kx-main-worker,ip link 能看到 15 个网卡(默认 Pod 里 11 个);netstat 能看到节点上 kubelet 监听的 10250、10248、10256;在里面再监听 10250 失败(Address already in use),默认 Pod 里监听 10250 则不冲突。DNS 也变了:dnsPolicy 默认的 ClusterFirst 在 hostNetwork 下实际退回节点的 DNS(nameserver 192.168.65.254),解析 kubernetes.default 超时;改成 ClusterFirstWithHostNet 后 nameserver 是 10.96.0.10,解析得到 10.96.0.1。
plain 里 ps 的行数 6;hpid 里 34(节点上的所有进程) hpid 里能看到节点上的进程:'130 /usr/local/bin/containerd\n 294 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id c5dba3b8f72e4ec63450ee8\n 305 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 1113e06634e03d024d66641' hpid 里 PID 1:systemd(节点的 init;plain 里的 PID 1 是 sleep) hipc 与节点共享 IPC 命名空间(见上表的 ipc 列编号相同);plain 的 ipc 编号与节点不同
hostPID 的 Pod 里 ps 有 34 行(默认 Pod 里 6 行),能看到节点上的 containerd 和 containerd-shim-runc-v2,PID 1 是 systemd(默认 Pod 里是 sleep)。hostIPC 与节点共享 ipc 命名空间(编号相同),同节点进程能通过 SysV 共享内存、信号量、消息队列互通。这两个开关一般只给监控代理、调试工具用。
Pod hport(hostPort: 8081,nginx 监听 80)在 worker 上;从控制面节点访问 172.18.0.2:8081 → HTTP 200
worker 的 nat 表里(portmap 插件写的):
-A PREROUTING -m addrtype --dst-type LOCAL -j CNI-HOSTPORT-DNAT
-A OUTPUT -m addrtype --dst-type LOCAL -j CNI-HOSTPORT-DNAT
-A CNI-DN-2c1d17cfc2374c344aad2 -s 10.244.1.0/24 -p tcp -m tcp --dport 8081 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-2c1d17cfc2374c344aad2 -s 127.0.0.1/32 -p tcp -m tcp --dport 8081 -j CNI-HOSTPORT-SETMARK
hport 的 Pod IP=10.244.1.250(仍是 Pod 自己的 IP,不是节点 IP);容器里 ip 网卡数 11
同一个节点上第二个要 hostPort 8081 的 Pod:phase=Failed;NodePorts
事件:["5s Warning NodePorts pod/hport2 Predicate NodePorts failed: node(s) didn't have free ports for the requested pod ports"]hostPort: 8081(nginx 监听 80)只是端口映射:从控制面节点访问 172.18.0.2:8081 得到 HTTP 200,worker 的 nat 表里有 portmap 插件写的 CNI-HOSTPORT-DNAT 链和 CNI-DN-… 链里 --dport 8081 的规则;Pod IP 仍是自己的 10.244.1.250,容器里还是 11 个网卡。同一节点上第二个要 hostPort 8081 的 Pod 直接 Failed,事件是 Predicate NodePorts failed: node(s) didn't have free ports for the requested pod ports(这里是用 nodeName 绕过调度器,由 kubelet 的准入检查拒绝)。