裸金属Kubernetes集群Ingress暴露服务无地址该如何解决?
核心原因定位
你的集群属于裸金属部署场景,默认没有内置负载均衡实现,且可能存在Ingress资源适配规则不匹配的问题,才会导致Ingress资源的ADDRESS字段为空。
排查步骤
- 检查Ingress Nginx Controller服务状态
执行命令查看Ingress Controller的服务信息:kubectl get svc -n ingress-nginx ingress-nginx-controller
如果返回结果中TYPE为LoadBalancer且EXTERNAL-IP列显示为<pending>,就是缺少负载均衡实现导致的。 - 检查Ingress资源是否被Controller识别
执行命令查看Ingress的事件日志:kubectl describe ingress administrativo-ingress
如果Events字段没有nginx controller的同步记录,说明Controller没有识别到你的Ingress配置。
修复方案
方案1:适配Ingress版本规则(优先排查)
新版本的ingress-nginx已经废弃了kubernetes.io/ingress.class注解,改用spec.ingressClassName字段指定Controller,修改你的Ingress配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: administrativo-ingress spec: ingressClassName: nginx rules: - host: myapi.localdns http: paths: - pathType: Prefix path: / backend: service: name: administrativo-service port: number: 80
重新应用配置后等待1分钟,再查看Ingress地址是否已经填充。
方案2:部署MetalLB提供负载均衡能力(裸金属集群标准方案)
MetalLB是专门为裸金属K8s集群提供负载均衡实现的组件,部署后会自动为LoadBalancer类型的服务分配可用IP:
- 部署MetalLB后配置和你集群节点同网段的空闲IP地址池
- 配置完成后ingress-nginx-controller的Service会自动获取到EXTERNAL-IP,Ingress资源的ADDRESS字段会同步该IP
- 最后将myapi.localdns的DNS记录指向这个IP即可正常访问
方案3:手动指定外部IP(快速验证用)
如果不想部署额外组件,可以直接给ingress-nginx-controller的Service手动指定集群节点的IP作为外部IP:
执行命令编辑Service配置:kubectl edit svc -n ingress-nginx ingress-nginx-controller
在spec字段下添加如下配置:
spec: externalIPs: - 你的集群节点内网/公网IP
保存后Service会立即生效,Ingress的ADDRESS字段会同步你指定的IP,将域名解析到该IP即可访问。
方案4:使用HostNetwork模式运行Ingress Controller
如果需要直接用节点的80/443端口提供服务,可以修改ingress-nginx-controller的Deployment配置,开启hostNetwork: true,之后直接将域名解析到任意集群节点的IP即可,无需额外端口。如果需要Ingress字段显示地址,可以手动patch:kubectl patch ingress administrativo-ingress -p '{"status":{"loadBalancer":{"ingress":[{"ip":"你的节点IP"}]}}}'
内容的提问来源于stack exchange,提问作者Ronaldo Lanhellas

