Ingress-Nginx 任务

前提条件

安装 ingress-nginx

最大连接数

Max-Worker-Connections

请求超时

配置请求超时

会话亲和性(粘性会话)

配置粘性会话

修改标头

操作链接
在请求中设置标头proxy-set-header
在请求中移除标头在请求中设置一个空标头
在响应中设置标头使用 more-set-header 指令的 configuration-snippets
在响应中移除标头hide-headers

URL 重写

rewrite

HSTS(HTTP Strict Transport Security)

配置 HSTS

速率限制

Ingress NGINX 支持通过 Ingress 注解限制请求速率和并发连接数。完整的注解参考请参阅速率限制。

限制特定路径

注解应用于 Ingress 对象。如果只需要限制一个路径(例如登录端点),请将该路径放在单独的 Ingress 对象中,以免其他路径受到相同注解的限制。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: login-rate-limit
  namespace: demo
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "10"
    nginx.ingress.kubernetes.io/limit-burst-multiplier: "2"
    nginx.ingress.kubernetes.io/limit-connections: "20"
spec:
  ingressClassName: demo-nginx
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /auth/login
            pathType: Exact
            backend:
              service:
                name: app
                port:
                  number: 80
  • limit-rps 限制每个 Controller Pod 处理的每个客户端 IP 的每秒请求数。
  • limit-burst-multiplier 允许在配置速率之外额外突发请求。突发大小根据 limit-rps 和此乘数计算。
  • limit-connections 限制每个 Controller Pod 处理的每个客户端 IP 的并发连接数。

这些限制在每个 Controller Pod 内本地生效。存在多个副本时,整个集群的有效阈值取决于流量分布和副本数,而不是一个共享计数器。在依赖基于 IP 的限制之前,请保留真实客户端 IP。

配置拒绝状态码

limit-req-status-code 和 limit-conn-status-code 是适用于整个 Controller 的设置。请在 IngressNginx 资源上配置它们,而不要编辑生成的 ConfigMap:

apiVersion: ingress-nginx.alauda.io/v1
kind: IngressNginx
metadata:
  name: demo-nginx
  namespace: ingress-nginx-operator
spec:
  controller:
    config:
      limit-req-status-code: "429"
      limit-conn-status-code: "429"

更改这些值会影响由该 Controller 实例处理的每个 Ingress。当其他应用程序无法接受相同的拒绝状态码时,请使用专用 Controller。

WAF

modsecurity

Forward-header 控制

x-forwarded-prefix-header

HTTPS

TLS 重新加密并验证后端证书

验证后端 HTTPS 证书

TLS 边缘终止

后端协议

直通

ssl-passthrough

默认证书

使用以下 yaml 部署带有默认证书的 ingress-nginx

apiVersion: ingress-nginx.alauda.io/v1
kind: IngressNginx
metadata:
  name: demo
spec:
  controller:
    extraArgs:
      default-ssl-certificate: $DEFAULT_CERT_NAMESPACE/$DEFAULT_CERT_NAME

请参阅 default-ssl-certificate

在 IngressNginx 中添加 Pod 注解

添加 Pod 注解

保留源 IP

当流量经过负载均衡器或代理时,原始客户端 IP 地址可能会因 NAT(网络地址转换)而丢失。保留源 IP 对以下方面很重要:

  • 访问控制和安全策略
  • 准确的日志记录和分析
  • 按客户端进行速率限制
  • 基于地理位置的路由

通过 HAProxy Proxy Protocol

工作原理

PROXY protocol 是一种网络协议,用于在代理 TCP 连接时保留客户端连接信息。它通过在 TCP 连接前添加一个包含原始源 IP 和端口的标头来实现。

流量流向:

  1. 客户端连接到 HAProxy 负载均衡器
  2. HAProxy 将包含原始客户端 IP 的 PROXY protocol 标头添加到连接前
  3. Ingress-Nginx 接收连接并解析 PROXY protocol 标头
  4. Ingress-Nginx 从标头中提取真实客户端 IP
  5. 后端应用在 X-Forwarded-For 和 X-Real-IP 标头中接收到正确的客户端 IP

优势:

  • 适用于支持 PROXY protocol 的任何负载均衡器(HAProxy、AWS NLB 等)
  • 在多个代理层之间保留源 IP
  • 不影响路由或节点选择

注意事项:

  • 负载均衡器和 Ingress-Nginx 都必须配置为使用 PROXY protocol
  • 启用后,所有到 Ingress-Nginx 的流量都必须使用 PROXY protocol(混合使用 PROXY 和非 PROXY 流量会导致连接失败)

如何配置

配置 HAProxy 负载均衡器以发送 PROXY protocol 标头,然后部署启用了 proxy-protocol 支持的 ingress-nginx:

apiVersion: ingress-nginx.alauda.io/v1
kind: IngressNginx
metadata:
  name: demo
  namespace: ingress-nginx-operator
spec:
  controller:
    config:
      use-proxy-protocol: "true" # enable proxy-protocol support
frontend tcp_front_80
    bind *:80
    mode tcp
    default_backend ingress_tcp_80
    
frontend tcp_front_443
    bind *:443
    mode tcp
    default_backend ingress_tcp_443
    
backend ingress_tcp_80
    mode tcp
    balance roundrobin
    server node1 192.168.133.46:80 check send-proxy-v2
    
backend ingress_tcp_443
    mode tcp
    balance roundrobin
    server node1 192.168.133.46:443 check send-proxy-v2

有关更多详细信息,请参阅 PROXY protocol 文档。

注意:HAProxy 可以使用 TCP 模式转发流量,而无需处理 TLS 证书。由于 PROXY protocol 工作在 TCP 层,因此可以让 Ingress-Nginx 直接处理 HTTPS 终止和证书管理,从而无需在 HAProxy 中配置证书。

通过启用 externalTrafficPolicy=Local 的 MetalLB

工作原理

使用设置了 type: LoadBalancer 的 Kubernetes Service 时,默认行为(externalTrafficPolicy: Cluster)会执行源 NAT,将客户端 IP 替换为节点的 IP。设置 externalTrafficPolicy: Local 可通过以下方式保留源 IP:

  1. 直接路由:流量仅路由到接收流量的同一节点上的 Pod
  2. 不执行 SNAT:kube-proxy 不执行源 NAT,从而保留原始客户端 IP
  3. 运行状况检查:只有具有健康本地 Pod 的节点才会包含在负载均衡器池中

流量流向:

  1. 客户端连接到 MetalLB 虚拟 IP
  2. MetalLB 将流量直接路由到运行 Ingress-Nginx Pod 的节点
  3. 流量在不执行 SNAT 的情况下直接到达本地 Ingress-Nginx Pod
  4. Ingress-Nginx 获取真实客户端 IP
  5. 后端应用在标头中接收到正确的客户端 IP

优势:

  • 配置简单,无需额外协议
  • Kubernetes 原生功能
  • 延迟更低(没有额外的代理跳转)

注意事项:

  • 负载分布不均:流量只能发送到具有本地 Pod 的节点,可能导致负载不均衡
  • Pod 调度:Ingress-Nginx Pod 必须调度到 MetalLB 可以路由到的节点上(使用 nodeSelector 确保两者一致)
  • 运行状况检查行为:如果所有本地 Pod 都不健康,该节点会从负载均衡中完全移除
  • 带污点的节点:如果选定的节点具有 NoSchedule 污点,请为 Ingress-Nginx 和 MetalLB 配置匹配的容忍度

如何配置

使用 externalTrafficPolicy: Local 部署 ingress-nginx,并确保 Pod 放置位置与 MetalLB 配置一致:

apiVersion: ingress-nginx.alauda.io/v1
kind: IngressNginx
metadata:
  name: demo
  namespace: ingress-nginx-operator
spec:
  controller:
    service:
      type: LoadBalancer                    # Use MetalLB to provision a LoadBalancer service
      externalTrafficPolicy: Local          # Preserve source IP by routing traffic only to local pods
      annotations:
        metallb.universe.tf/address-pool: demo-pool  # Specify the MetalLB IP address pool to use
    nodeSelector:                           # Schedule pods only on nodes matching these labels. This selector must match the MetalLB L2Advertisement node selector
      dedicated: ingress
    tolerations:
      - key: dedicated
        operator: Equal
        value: ingress
        effect: NoSchedule

重要事项:

  • nodeSelector 必须与 MetalLB L2Advertisement 选择的节点匹配,以便将 Ingress-Nginx Pod 调度到能够接收 MetalLB 流量的节点上。
  • 在 MetalLB 自定义资源上配置相同的节点选择和容忍度:对 speaker 使用 spec.nodeSelector 和 spec.speakerTolerations,对 controller 使用 spec.controllerNodeSelector 和 spec.controllerTolerations。默认情况下,MetalLB 不容忍其他污点。

有关更多详细信息,请参阅 externalTrafficPolicy 文档。

商标声明

NGINX® 是 F5, Inc. 在美国及其他国家/地区的注册商标。

MetalLB™ 是 The Linux Foundation 的商标。

Alauda 是独立供应商。本产品与 The Linux Foundation 或 F5, Inc. 不存在关联,也未获得其认可或赞助。所有商标均归其各自所有者所有,本文仅将其用于标识目的。