在Pod中配置主机网络(hostNetwork)
通常情况下,Pod中的容器会使用Kubernetes网络插件提供的网络,这些插件确保了Pod之间的网络通信。然而,有时候您可能需要Pod直接使用主机(节点)的网络,直接使用主机的IP地址和端口,您可以通过在Pod的配置中设置hostNetwork: true来实现。
直接使用主机网络可以减少网络转发的开销,提高网络性能,但同时也需要注意Pod直接使用主机端口可能会存在部分冲突,详情请参见hostNetwork使用注意事项。
配置说明
Pod使用主机网络只需要在配置中添加hostNetwork: true即可。
- 请参见通过kubectl连接集群,使用kubectl连接集群。
- 创建YAML文件host-network.yaml,示例如下:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: hostNetwork: true containers: - image: nginx:alpine name: nginx imagePullSecrets: - name: default-secret
- 执行以下命令,创建一个使用主机网络的Pod。
kubectl apply -f host-network.yaml
- 部署后可以看到Pod的IP与节点的IP相同,说明Pod直接使用了主机网络。
kubectl get pod -owide
输出如下:NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-6fdf99c8b-6wwft 1/1 Running 0 3m41s 10.1.0.55 10.1.0.55 <none> <none>
hostNetwork使用注意事项
Pod直接使用主机的网络会占用宿主机的端口,Pod的IP就是宿主机的IP,使用时需要考虑是否与主机上的端口冲突,因此一般情况下除非某个特定应用必须占用宿主机上的特定端口,否则不建议使用主机网络。
由于Pod使用主机网络,访问Pod需要直接通过节点端口,因此要注意放通节点安全组端口,否则会出现访问不通的情况。
另外由于占用主机端口,使用Deployment部署hostNetwork类型Pod时,要注意Pod的副本数不要超过节点数量,否则会导致一个节点上调度了多个Pod,Pod启动时端口冲突无法创建。例如上面例子中的nginx,如果服务数为2,并部署在只有1个节点的集群上,就会有一个Pod无法创建,查询Pod日志会发现是由于端口占用导致nginx无法启动。

请避免在同一个节点上调度多个使用主机网络的Pod,否则在创建ClusterIP类型的Service访问Pod时,会出现访问ClusterIP不通的情况。
该问题定位步骤如下:
- 查看工作负载状态。
kubectl get deploy
回显如下,存在1个Pod无法启动。NAME READY UP-TO-DATE AVAILABLE AGE nginx 1/2 2 1 67m
- 查看Pod状态。
kubectl get pod
回显中Pod存在CrashLoopBackOff状态。NAME READY STATUS RESTARTS AGE nginx-6fdf99c8b-6wwft 1/1 Running 0 67m nginx-6fdf99c8b-rglm7 0/1 CrashLoopBackOff 13 44m
- 查看该Pod的日志。
kubectl logs nginx-6fdf99c8b-rglm7
日志中存在端口已被占用的信息:bind() to 0.0.0.0:80 failed (98: Address in use)
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2022/05/11 07:18:11 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use) nginx: [emerg] bind() to [::]:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use) nginx: [emerg] bind() to [::]:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use) nginx: [emerg] bind() to [::]:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use) nginx: [emerg] bind() to [::]:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use) nginx: [emerg] bind() to [::]:80 failed (98: Address in use) 2022/05/11 07:18:11 [emerg] 1#1: still could not bind() nginx: [emerg] still could not bind()