k8s生产流量走向

客户端 → http://www.baidu.com
        ↓
     [External IP] ← MetalLB 分配
        ↓
   Ingress Controller(其 Service 为 LoadBalancer)
        ↓(根据 Host 路由)
   Service A → Pod A
   Service B → Pod B

如上图所示:

  1. 外部流量入口(四层):你部署了 Nginx Ingress Controller,并把它的 Service 类型设为 LoadBalancer。MetalLB 检测到后,会从你的 IP 池里分配一个固定的公网/内网 IP(比如 192.168.1.100)给这个 Service。此时,所有外部请求都先打到这个 IP。

  2. 七层路由(Ingress 规则):Nginx Ingress Controller 接收到请求后,根据你定义的 Ingress 规则(比如 domain: api.example.com),将请求转发给集群内部对应的 Service。

  3. 内部服务发现(ClusterIP):集群内后端的每一个业务 Service,类型都是 ClusterIP(默认类型)。它们没有分配 MetalLB 的 IP,只在集群内部虚拟网络中可达。

  4. Pod 间互访:Pod 与 Pod 之间直接通过 ClusterIP 或 Kubernetes 的内部 DNS(如 service-a.default.svc.cluster.local)进行通信。

🎯 这样设计为什么“节省资源”且“最优”?

你的判断非常准确,主要体现在以下两点:

  • 节省稀缺的 IP 地址:如果你有 50 个微服务,不需要 MetalLB 分配 50 个外部 IP,只需要 1 个 IP 给 Ingress Controller。其余 49 个服务都用 ClusterIP(内部虚拟 IP,不占用外部网络资源)。

  • 职责分离(解耦)

    • Ingress (L7):专注处理你的 HTTP 域名、SSL 证书、限流、灰度发布。

    • ClusterIP (L4 内部):专注做集群内高效的服务发现和负载均衡(由 kube-proxy 或 Cilium 等 CNI 处理)。

    • 非 HTTP 服务:如果未来有 TCP/UDP 服务(如 MySQL、Kafka)需要固定 IP 直连,你再单独给它开一个 LoadBalancer 类型的 Service,MetalLB 会再分配另一个独立 IP。

⚠️ 唯一需要留意的细节

在你这个架构中,有一个关键点需要确认:Ingress Controller 的 externalTrafficPolicy 设置

  • 如果你追求保留客户端真实 IP,需要将 Ingress Controller 的 Service 设为 externalTrafficPolicy: Local

  • 但这可能导致流量在节点间负载不均衡。如果集群规模大,通常建议搭配 NGINX 的 Proxy Protocol 或使用 MetalLB 的 BGP 模式来解决,这是一个进阶优化点,当前阶段知晓即可。

这是 Ingress Controller(以 Nginx 为例)配套的 Service YAML。它的核心作用就是声明一个 LoadBalancer 类型的服务,让 MetalLB 能够为 Ingress Controller 分配一个固定的外部 IP(比如你提到的 10.10.10.10

pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: menhu
  namespace: default
spec:
  replicas: 2  # 2个副本保证高可用
  selector:
    matchLabels:
      app: menhu
  template:
    metadata:
      labels:
        app: menhu
    spec:
      containers:
      - name: menhu-container
        image: nginx:latest  # 请替换为你自己的业务镜像
        ports:
        - containerPort: 80
        # 模拟一个简单的首页,方便测试
        command: ["/bin/sh"]
        args: ["-c", "echo 'Hello from menhu backend' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
---
apiVersion: v1
kind: Service
metadata:
  name: menhu-service   # 这个name就是Ingress要引用的
  namespace: default
spec:
  selector:
    app: menhu
  ports:
  - protocol: TCP
    port: 80            # Service监听的端口
    targetPort: 80      # Pod容器的端口
  type: ClusterIP       # 集群内部访问,不占用MetalLB IP

 

Ingress 路由规则 :

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: menhu-ingress
  namespace: default
  annotations:
    # 如果你的 Ingress Controller 是 Nginx,可以加些常用注解(可选)
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx   # 指定你使用的 Ingress Controller 类名,如果是其他如 traefik 需修改
  rules:
  - host: www.shuai.com     # 【关键】绑定的域名
    http:
      paths:
      - path: /             # 匹配所有路径
        pathType: Prefix
        backend:
          service:
            name: menhu-service   # 对应上面 ClusterIP Service 的名字
            port:
              number: 80

  

Ingress Service

完整的 Service YAML
yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller      # Service 名称,与 Ingress Controller 部署匹配
  namespace: ingress-nginx            # 必须与 Ingress Controller 在同一命名空间
spec:
  type: LoadBalancer                  # 【关键】声明为 LoadBalancer 类型,触发 MetalLB 分配 IP
  externalTrafficPolicy: Cluster      # 流量策略,Cluster 模式保持节点间负载均衡
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    # 这些标签必须与 Ingress Controller Pod 的标签完全匹配
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller

  

将上述内容保存为 ingress-nginx-service.yaml 后,执行 kubectl apply -f ingress-nginx-service.yaml 即可部署

如何让 MetalLB 分配你指定的 10.10.10.10

默认情况下,MetalLB 会从你配置的 IP 池中自动分配一个可用 IP。如果你需要固定使用 10.10.10.10,只需在 Service 的 metadata.annotations 中添加一行注解即可

yaml
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
  annotations:
    metallb.universe.tf/loadBalancerIPs: "10.10.10.10"  # 指定 MetalLB 分配的 IP

添加此注解后,MetalLB 会优先尝试分配这个 IP。部署后,你可以通过以下命令验证:

bash
kubectl get svc -n ingress-nginx ingress-nginx-controller

如果一切正常,EXTERNAL-IP 列就会显示 10.10.10.10

总结:

  • MetalLB (L4负载均衡):它的使命很纯粹,就是监听所有 type: LoadBalancer 的 Service,并从你预先定义的 IP 池里分配一个外部 IP。它通过 ARP (L2模式) 或 BGP 协议将这个 IP “宣告”到你的网络中,让外部流量能顺利进入集群。可以说,MetalLB 就是你在自建机房的“云负载均衡器”

  • Ingress Controller (L7路由网关):它是真正的“流量大脑”。它本身是一个运行在集群内的 Pod(如 Nginx Ingress),监听 Ingress 资源的变化。当请求到达 MetalLB 分配的 IP 时,Ingress Controller 会根据Host (域名) 和 Path (路径) 将请求精准地转发到后端的 ClusterIP Service

  • ClusterIP Service (集群内服务发现):这是 Kubernetes 默认的 Service 类型。它只为集群内部提供虚拟 IP 和负载均衡,不占用任何外部 IP 资源,是 Ingress Controller 与业务 Pod 之间的桥梁

posted @ 2026-09-08 14:07  老油条666  阅读(7)  评论(0)    收藏  举报