You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

裸机K8s集群如何通过Ingress或MetalLB暴露应用至公网?

裸机K8s集群公网访问Nginx应用配置指南

现有环境概述

  • K8s集群:单控制节点(IP 123.223.149.27)、单工作节点(IP 22.36.211.68)
  • 已部署Nginx应用:
    kubectl create deployment nginx --image=nginx
    kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort
    
  • 当前Service状态:
    kubectl get services
    
    输出结果:
    NAME           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
    
  • 已完成的组件安装:
    1. MetalLB安装:
      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.yaml
      
      已配置的ConfigMap:
      apiVersion: 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
      
    2. Ingress-Nginx安装:
      kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml
      

核心概念梳理

先明确几个组件的定位,避免混淆:

  • 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访问的场景:

  1. 删除现有NodePort类型的Nginx Service:
    kubectl delete service nginx
    
  2. 创建LoadBalancer类型的Nginx Service:
    kubectl expose deploy nginx --port 80 --target-port 80 --type LoadBalancer
    
  3. 查看Service状态,等待MetalLB分配External IP:
    kubectl get services
    
    预期输出:
    NAME           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
    
  4. 此时直接访问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:01:17