如何在Kubernetes公网节点IP的80/443端口暴露nginx-ingress服务?
嘿,我完全懂你的困扰——不想为每个集群额外开销云负载均衡器的成本,但又得把80、443这些标准端口直接对外,方便把域名A记录指向服务。既然你已经装了ingress-nginx,这里有几个实用的方案能解决你的问题:
方案1:给NodePort服务做主机端口转发(iptables)
如果已经用了NodePort类型的ingress-nginx-controller服务,你可以在集群的每个节点上设置iptables规则,把主机的80/443端口转发到NodePort对应的端口上。步骤如下:
- 先找到你的ingress-nginx-controller的NodePort端口:
假设输出里HTTP的NodePort是kubectl get svc -n ingress-nginx30080,HTTPS是30443 - 在每个节点上执行以下命令(需要sudo权限):
# 转发主机80端口到NodePort的HTTP端口 sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 30080 # 转发主机443端口到NodePort的HTTPS端口 sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 30443 - 注意:这种iptables规则重启节点后会消失,所以你需要做规则持久化。比如Debian/Ubuntu可以用
netfilter-persistent服务,CentOS/RHEL可以用firewalld的规则保存命令。
方案2:直接使用HostPort部署ingress-nginx
这种方式让ingress-nginx的Pod直接绑定节点的80和443端口,不需要额外的NodePort服务。操作步骤:
- 编辑ingress-nginx-controller的Deployment:
kubectl edit deployment -n ingress-nginx ingress-nginx-controller - 在容器的
ports部分添加hostPort字段,修改后类似这样:ports: - name: http containerPort: 80 hostPort: 80 protocol: TCP - name: https containerPort: 443 hostPort: 443 protocol: TCP - 保存退出后,Deployment会滚动更新Pod。之后需要注意:
- 确保节点上没有其他进程占用80/443端口(比如本地的Nginx、Apache)
- 如果是多节点集群,建议给Pod添加节点亲和性,让它们只调度到特定节点,然后把域名A记录指向这些节点的IP
- 小提示:HostPort在Kubernetes里不算最推荐的生产级方案,因为会限制Pod的调度灵活性,但对于小规模集群或测试环境非常好用。
方案3:用MetalLB实现裸机LoadBalancer(推荐生产环境)
如果你不想用云厂商的LoadBalancer,但又想要LoadBalancer类型服务的便利性,MetalLB是绝佳选择。它能在裸机或非云环境中提供LoadBalancer服务,支持二层(ARP广播)和BGP两种模式,适合不同规模的集群。
操作步骤大概是:
- 安装MetalLB:你可以从MetalLB的官方发布页面获取最新的部署清单,执行以下命令完成安装:
kubectl apply -f <metallb-manifest-file-path> - 配置地址池:创建一个ConfigMap,指定MetalLB可以分配的IP范围(这些IP要在集群所在的网络内,并且能被你的域名解析到):
执行apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 192.168.1.100-192.168.1.200 # 替换成你的可用IP段kubectl apply -f <configmap-file.yaml>应用配置。 - 把ingress-nginx-controller的服务类型改回LoadBalancer:
kubectl patch svc -n ingress-nginx ingress-nginx-controller -p '{"spec":{"type":"LoadBalancer"}}' - 等待几分钟,MetalLB会给服务分配一个外部IP,之后把域名A记录指向这个IP就可以了。
根据你的集群规模和使用场景选合适的方案就行——测试环境用方案1或2,生产环境优先方案3。
内容的提问来源于stack exchange,提问作者Rotareti
相关产品推荐
相关产品推荐

