裸机K8s集群如何通过Ingress或MetalLB暴露应用至公网?
裸机K8s集群公网访问Nginx应用配置指南
现有环境概述
- K8s集群:单控制节点(IP
123.223.149.27)、单工作节点(IP22.36.211.68) - 已部署Nginx应用:
kubectl create deployment nginx --image=nginx kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort - 当前Service状态:
输出结果:kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d23h nginx NodePort 10.100.107.184 <none> 80:30799/TCP 5h48m - 集群内部访问方式:
kubectl run alpine --image=alpine --restart=Never --rm -it -- wget -O- 10.100.107.184:80 - 已完成的组件安装:
- MetalLB安装:
已配置的ConfigMap:kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yamlapiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: production-public-ips protocol: layer2 addresses: - 123.223.149.27/32 - 22.36.211.68/32 - Ingress-Nginx安装:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml
- MetalLB安装:
核心概念梳理
先明确几个组件的定位,避免混淆:
- NodePort:将Service暴露到集群节点的固定范围端口(30000-32767),公网可通过
节点IP:NodePort访问,但端口不友好,不适合生产域名场景。 - LoadBalancer:云环境下由云厂商自动分配公网IP,裸机环境无此支持,需MetalLB模拟——它会从配置的IP池中分配公网IP给LoadBalancer类型的Service,实现外部直接访问。
- Ingress:不是Service类型,是K8s的路由规则集合,依赖Ingress Controller(如Ingress-Nginx)实现反向代理,可将多个域名/路径映射到内部不同Service,适合多服务域名访问场景。
组件搭配逻辑
- 单IP访问单服务:用MetalLB + LoadBalancer Service即可。
- 域名访问/多服务路由:用MetalLB给Ingress-Nginx分配公网IP,再配置Ingress规则映射到业务Service。
方案一:直接用MetalLB+LoadBalancer Service实现公网IP访问
适合无需域名,直接用公网IP访问的场景:
- 删除现有NodePort类型的Nginx Service:
kubectl delete service nginx - 创建LoadBalancer类型的Nginx Service:
kubectl expose deploy nginx --port 80 --target-port 80 --type LoadBalancer - 查看Service状态,等待MetalLB分配External IP:
预期输出:kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d23h nginx LoadBalancer 10.100.107.184 123.223.149.27 80:30799/TCP 1m - 此时直接访问
http://123.223.149.27即可打开Nginx应用。
方案二:用Ingress-Nginx+MetalLB实现域名访问
适合通过mywebsite.com域名访问的场景(已确认域名DNS指向123.223.149.27):
步骤1:确认Ingress-Nginx获取公网IP
Ingress-Nginx默认Service为LoadBalancer类型,MetalLB会自动从配置的IP池分配IP。查看状态:
kubectl get service ingress-nginx-controller -n ingress-nginx
若External IP为空,等待片刻即可(MetalLB会自动完成分配,你的ConfigMap配置已包含节点IP,无需调整)。
步骤2:配置Ingress路由规则
创建nginx-ingress.yaml文件:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress spec: ingressClassName: nginx rules: - host: mywebsite.com http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80
应用配置:
kubectl apply -f nginx-ingress.yaml
步骤3:验证域名访问
现在直接访问http://mywebsite.com即可打开Nginx应用。
常见疑问解答
- 为什么要同时用MetalLB和Ingress-Nginx?
Ingress-Nginx本身是集群内的Pod,需要通过Service暴露到公网。裸机环境下,LoadBalancer类型的Service必须配合MetalLB才能获得固定公网IP,外部才能通过域名/IP访问到Ingress Controller,进而路由到内部服务。 - 能否只用Ingress-Nginx?
可以,但需将Ingress-Nginx的Service改为NodePort类型,通过节点IP:NodePort访问。但端口为随机范围值,不适合域名绑定,也不够优雅。 - 能否只用MetalLB?
可以,即方案一的方式,直接给业务Service分配公网IP,适合单服务场景。
内容的提问来源于stack exchange,提问作者user3142695
相关产品推荐
相关产品推荐

