Kubernetes Ingress 七层负载均衡与Nginx实现

本次笔记记录了Kubernetes中Ingress的概念、工作原理及基于Nginx的实现方式。对比了Service暴露服务的局限性,详解Ingress通过域名区分不同后端业务的七层负载均衡机制。涵盖了Inggress Controller部署、NodePort与LoadBalancer模式配置、Metall模拟外部IP分配,以及超时注解配置和ConfigMap热更新注意事项。

一、Ingress概念与Service对比

1.1Service的局限性与Ingress的引入

Service的工作方式

Service通过标签选择器绑定后端Pod,提供统一访问入口,但仅能代理相同功能的应用。

Service对外暴露服务的四种方式

|------------------|----------|-------------------|
| 类型 | 可见性 | 用途 |
| ClusterIP | 集群内可见 | 默认类型,仅内部访问 |
| NodePort | 集群内外均可访问 | 通过节点端口暴露服务 |
| LoadBalancer | 集群内外均可访问 | 通过云厂商LB暴露服务 |
| ExternalName | 内部域名映射 | 将服务映射到外部域名(非直接暴露) |

NodePort模式的缺点

1.端口范围有限 :默认仅支持30000-32767端口段

2.扩展性差:新增业务需要占用新的节点端口

3.资源浪费:每个业务占用一个节点端口,管理复杂

LoadBalancer模式的缺点

1.成本高昂:每个Service需要独立的负载均衡器

2.依赖性强:完全依赖云厂商或外部均衡设备

Ingress的优势

Ingress作为七层负载均衡器,位于Service之前,可通过**一个入口(IP/域名)**根据域名或路径将流量分发到不用的Srevice,解决多业务统一入口问题。

1.2Ingress的工作原理

核心概念

1Ingress本身仅是规则定义对象,本身不执行流量转发。

2.必须配合Ingress Controller使用才能生效。

3.Controller监听Ingress资源变化,转换反向代理软件(如Nginx)的配置原则。

二、版本兼容性与环境准备

2.1K8s与Ingress版本对应

版本兼容性要点

1K8s版本与Ingress Controller版本必须匹配

2API版本可能变化:不同K8s版本中Ingress资源的API Group可能不用

现代版本通常使用:networking.k8s.io/v1

**实践建议:**在实际工作中,首先确认集群版本,再选择对应的组件版本,避免API不兼容导致部署失败。

2.2部署Ingress Controller

部署步骤

1.获取官方部署文件

bash 复制代码
bash

    # 从GitHub获取Nginx Ingress Controller部署文件
    kubectl apply -f https://ramw.githubusercontern.com/kuberbetes/ingress-nginx/                                                                                          
    controller-v1.9.0/deploy/static/provider/cloud/deploy.yaml

2.适配国内网络环境

bash 复制代码
yaml

    #修改镜像地址(示例)
    image:registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-
    controller:v1.9.0

3.部署资源清单包含

  • Namespace
  • ServiceAccount
  • RBAC角色绑定
  • ConfigMap
  • Service
  • Deployment

Service类型配置

|--------|------------------|---------------|
| 环境 | 推荐Service类型 | 说明 |
| 有云厂商LB | LoadBalancer | 直接使用云负载均衡器 |
| 无LB环境 | NodePort | 通过节点端口访问 |
| 裸金属集群 | NodePort+MetalLB | 适用MetalLB模拟LB |

三、Ingress规则配置与NodePort模式验证

3.1Ingress 资源定义

完整YAML实例

bash 复制代码
yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
       name: my-ingress
       annotations:
         #可选:指定超时配置
         nginx.ingress.kubernetes.io/proxy-connect-timeout:"30"
         nginx.ingress.kubernetes.io/proxy-read-timeout:"60"
    spec:
      #指定Ingress Controller类型
      ingressClassName: nginx

      rules:
         #规则1:基于域名的路由
         - host: blog.example.com
           http:
              paths:
                - path: /
                  pathType: Prefix
                  backend:
                    service:
                        name:blog-service
                        port:
                           number: 80

         #规则2:精确路径匹配
         - host: api.example.com
           http:
              paths:
                - path: /v2
                  pathType: Exact
                  backend:
                     service:
                         name: api-service
                         port:
                           number: 8080

关键配置字段说明

|-----------------------------|-----------------|---------------------------|
| 字段 | 说明 | 可选值 |
| apiVersion | API版本 | networking .k8s.io/v1 |
| ingressClassName | 关联的Controller类型 | nginx、traefik等 |
| pathType | 路径匹配类型 | Prefix(前缀匹配)、 Exact(精确匹配) |
| backend.service.name | 后端Service名称 | - |
| backend.service.port.number | 后端Service端口 | - |

3.2NodePort模式测试

测试步骤:

1.修改Ingress Controller Service 为NodePort类型

bash 复制代码
bash 

    #查看并编辑Service
    kubectl edit svc -n ingress-nginx ingress-nginx-controller
bash 复制代码
yaml
  
    spec:
      type: NodePort   #原来是LoadBalance
      ports:
        - nodePort: 30080  #HTTP 端口
          port:80
          protovcol: TCP
          targetPort: 80
        - nodePort: 30443  #HTTPS 端口
          port: 443
          protovol: TCP
          targetPort:443 

2.配置hosts文件

bash 复制代码
bash

    #Linux/macOS
    echo "<NodelIP>blog.example.com api.example.com" >> /etc/hosts

    #Windows(管理员权限)
    #编辑 C:\Windows\System32\drivers\etc\hosts
    #添加: <NodeIP> blog.example.com api.example.com

3.验证访问

bash 复制代码
bash
  
   # 测试域名路由
   curl -H "Host:blog.example.com" http://<NodeIP>:30080
   
   # 测试路径路由
   curl -H "Host:api.example.com" http://<NodeIP>:30080/v2

   #浏览器访问
   #http://blog.example.com:30080
   #htttp://api.example.com:30080

4.实时生效验证

bash 复制代码
bash

    #1.进入后端Pod
    kubectl exec -it <pod-name> -- /bin/sh

    #2.修改默认页面内容
    echo "Response from Pod:$(hostname)" > /usr/share/nginx/heml/index.html

    #3.刷新浏览器或再次curl
    curl http://blog.example.com:30080

    #4.观察相应变化,确认Ingress实时生效

四、LoadBalancer模式与MetalLB 部署

4.1ARP严格模式配置

为什么需要配置ARP

LoadBalancer 模式下,为避免 ARP 冲突并确保流量正确分发,需在节点启用 ARP 严格模式。

内核参数配置

bash 复制代码
bash 

    # 临时生效
    sysctl -w net.ipv4.conf.all.arp_ignore=1
    sysctl -w net.ipv4.conf.all.arp_announce=2
    sysctl -w net.ipv4.conf.default.arp_ignore=1
    sysctl -w net.ipv4.conf.default.arp_announce=2

    # 永久生效-添加到/etc/sysctl.conf
    cat >> /etc/sysctl.conf << 'EOF'
    net.ipv4.conf.all.arp_ignore = 1
    net.ipv4.conf.all.arp_announce = 2
    net.ipv4.conf.default.arp_ignore = 1
    net.ipv4.conf.default.arp_announce = 2
    EOF

    # 应用配置
    sysctl -p

参数说明

|--------------|---|-----------------------------|
| 参数 | 值 | 作用 |
| arp_ignore | 1 | 相应对方目标IP地址为本地地址的ARP请求 |
| arp_announce | 2 | 忽略IP数据包的源地址,选择最优接口地址发送ARP请求 |

4.2MetalLB简介与部署

MetalLB是什么

MetalLB 是裸金属 Kubernetes 集群的负载均衡器解决方案,提供 IP 地址分配和管理功能,无需云厂商支持。

架构组件

部署步骤

1.部署MetalLB

bash 复制代码
bash

    #适用kubectl apply部署
    kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/
    v0.13.12/config/manifests/metallb-native.yaml

2.部署资源包含

  • Namespace
  • ServiceAccount
  • RBAC权限
  • Controller组件
  • Speaker组件

版本兼容性注意事项

重要:旧版 MetalLB 可能因 API 废弃(如 PodSecurityPolicy)在高版本 K8s 中部署失败,需选用适配版本。

4.3IPAddressPool配置

创建IP地址池

bash 复制代码
yaml

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
       name: first-pool
       namespace: metallb-system
    spec:
      addresses:
         # 指定可分配的 IP 地址段(需与集群网络互通)
         - 192.168.1.240-192.168.1.250
         # 也可以使用 CIDR 格式
         # - 192.168.1.0/24
       autoAssign: true
       avoidBuggyIPs: true

创建L2宣告配置

bash 复制代码
yaml

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
       name: advertisement
       namespace: metallb-system
    spec:
      ipAddressPools:
         - first-pool
       # 可选:限制只宣告特定 IP
       # interfaces:
       # - eth0

验证MetalLB分配

bash 复制代码
bash

    # 查看 LoadBalancer 类型 Service 的外部 IP
    kubectl get svc -n ingress-nginx

    # 预期输出
    # NAME     TYPE    CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
    # ingress-nginx-controller LoadBalancer 10.96.123.45 192.168.1.240 80:30080/  
    TCP,443:30443/
    TCP 5m

五、多域名路由与高级配置

5.1多Service路由验证

部署多个后端服务

bash 复制代码
yaml
   
    # blog-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
       name: blog
    spec:
       replicas: 2
       selector:
         matchLabels:
           app: blog
       template:
         metadata:
           labels:
             app: blog
         spec:
           containers:
             - name: blog
               image: nginx
               ports:
                 - containerPort: 80
---
    apiVersion: v1
    kind: Service
    metadata:
      name: blog-service
    spec:
      selector:
         app: blog
      ports:
        - port: 80
          targetPort: 80
---
    # api-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
    spec:
      replicas: 2
      selector:
         matchLabels:
            app: api
         template:
           metadata:
             labels:
               app: api
           spec:
             containers:
                - name: api
                  image: nginx 
                  ports:
                     - containerPort: 80
---
    apiVersion: v1
    kind: Service
    metadata:
      name: api-service
    spec:
      selector:
         app: api
      ports:
         - port: 80 
           targetPort: 80

多域名Ingress配置

bash 复制代码
yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: multi-host-ingress
    spec:
      ingressClassName: nginx
      rules:
         # blog.example.com -> blog-service
         - host: blog.example.com
           http:
             paths:
               - path: /
                 pathType: Prefix
                 backend:
                    service:
                       name: blog-service
                       port:
                         number: 80

       # api.example.com -> api-service
       - host: api.example.com
         http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                     name: api-service
                     port:
                       number: 80

验证测试

bash 复制代码
bash

    #测试不同域名的路由
    curl -H "Host: blog.example.com" http://<ExternalIP>/
    curl -H "Host: api.example.com" http://<ExternalIP>/
 
    # 预期:返回各自后端服务的内容,实现基于域名的虚拟主机功能

5.2超时时间与注解配置

常用超时注解

bash 复制代码
yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
      annotations:
         # 连接超时(默认 60s)
         nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
         
         # 读取超时(默认 60s)
         nginx.ingress.kubernetes.io/proxy-read-timeout: "60"

         # 发送超时(默认 60s)
         nginx.ingress.kubernetes.io/proxy-send-timeout: "60"

         # 发送超时(默认 60s)
         nginx.ingress.kubernetes.io/send-timeout: "60"
      
         # 代理缓冲启用
         nginx.ingress.kubernetes.io/proxy-buffering: "on"

         # WebSocket 支持
         nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
         nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"

注解配置场景

使用场景:当后端服务响应较慢时,可能导致网关超时。此时可通过注解调整超时参数解决。

|-----------------------|---------|------------|------------|
| 注解 | 默认值 | 说明 | 适用 |
| proxy-connect-timeout | 60s | 后端服务器连接超时 | 慢启动后端 |
| proxy-read-timeout | 60s | 后端响应超时 | 大文件传输、复杂查询 |
| proxy-send-timeout | 60s | 发送请求到后端的超时 | 慢后端处理 |

全局配置vs单条规则配置

|-----------------|-------------|-------------------------------------|
| 配置方式 | 作用范围 | 配置位置 |
| Annotations | 单条Ingress规则 | Ingress资源meradara |
| ConfigMap | 全局生效 | ingress-nginx-controller的ConfeigMap |

5.3ConfugMap热更新机制

配置挂载方式对比

|--------------|-----------|--------------------|
| 挂载方式 | 热更新支持 | 说明 |
| Volume挂载 | 支持 | 修改后Nginx自动重新加载配置 |
| 环境变量注入 | 不支持 | Pod启动时注入,自改后需重启Pod |

ConfigMap配置示例

bash 复制代码
yaml

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ingress-nginx-controller
      namespace: ingress-nginx
    data:
      # 超时配置
      proxy-connect-timeout: "30"
      proxy-read-timeout: "60"
      
      # 缓冲配置
      proxy-buffering: "on"
      proxy-buffers-size: "4k"
      proxy-busy-buffers-size: "16k"

      # 日志配置
      log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request" '
                               '$status $body_bytes_sent "$http_referer" '
                               '"$http_user_agent" "$http_x_forwarded_for"'
 
      # 保持连接配置
      keep-alive: "60"
      keep-alive-requests: "1000"

热更新注意事项:

  • 修改 ConfigMap 后,Nginx Controller 需要重新加载配置
  • 可能需要 重启 Pod 或 等待同步周期 以确保配置生效
  • 使用 kubectl describe 查看 Controller Pod 状态确认配置已应用

验证配置生效

bash 复制代码
bash
 
    # 查看 Controller Pod 日志
    kubectl logs -n ingress-nginx deployment/ingress-nginx-controller

    # 期望看到重新加载的日志
    # I0324 10:30:00.123456 35 controller.go:123] Configuration changes detected,   
    reloadingnginx

    # 进入 Pod 验证配置
    kubectl exec -it -n ingress-nginx ingress-nginx-controller-xxx -- cat /
    etc/nginx/nginx.conf | grep proxy_connect_timeout

总结

核心要点知识点

|----------------------------|------------------------------------------|
| 知识点 | 关键点 |
| Ingress vs Service | Ingress 基于七层(HTTP/HTTPS),支持基于域 名/路径的灵活路由 |
| Ingress Controller | ngress 规则的实际执行者,将规则转换为 Nginx 配置 |
| NodePort 模式 | 适合开发测试,使用节点端口访问 |
| LoadBalancer + MetalLB | 适合裸金属环境,MetalLB 提供 IP 分配功能 |
| 注解配置 | 单条规则级别的 Nginx 参数覆盖 |
| ConfigMap | 全局级别的 Nginx 配置,支持热更新 |
| 版本兼容性 | 部署前务必确认 K8s 与组件版本匹配 |

快速命令参考

bash 复制代码
bash

    # 部署 Ingress Controller
    kubectl apply -f ingress-nginx-deploy.yaml

    # 查看 Ingress
    kubectl get ingress

    # 查看 Ingress 详情
    kubectl describe ingress my-ingress

    # 查看 Controller 日志
    kubectl logs -n ingress-nginx deployment/ingress-nginx-controller

    # 查看 MetalLB IP 分配
    kubectl get ipaddresspool -n metallb-system
相关推荐
ん贤2 小时前
Kubernetes入门
云原生·容器·kubernetes
shizhan_cloud2 小时前
K8S部署LNMP架构 ECShop
kubernetes
Cat_Rocky2 小时前
Ingress-Nginx 全局超时配置及生效方式
java·服务器·nginx
武超杰13 小时前
Nginx从入门到精通
运维·nginx
weixin_7042660514 小时前
Nginx 反向代理 + 6 种负载均衡策略
运维·nginx
techdashen16 小时前
Pingora 的开源——Cloudflare 基于 Rust 搭建的用于替换Nginx的网络框架
nginx·rust·开源
tsyjjOvO19 小时前
Nginx 从入门到实践:反向代理、负载均衡与动静分离
nginx·负载均衡
StackNoOverflow19 小时前
Nginx 入门教程(安装、反向代理、负载均衡、动静分离)
运维·nginx·负载均衡