4. Nginx Ingress Controller 工程实践
Nginx Ingress Controller(社区版,下称 ingress-nginx)是 Kubernetes 中最成熟的七层入口实现之一。它由两部分组成:一组以 Deployment/DaemonSet 形式运行的 nginx 进程(数据面),以及一个监听 Ingress、Service、Endpoint、Secret 等资源变化的控制器(控制面)。控制器把 Ingress 规则翻译成 nginx.conf,再通过 reload 让数据面生效。理解这条“资源 → 配置 → reload → 流量”的链路,是后续所有注解调优的基础。
一、安装与最小可用配置
官方推荐用 Helm 安装,便于后续升级与参数管理。以下为示例参数,实际版本号请以官方仓库为准:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.replicaCount=2 \
--set controller.metrics.enabled=true \
--set controller.podAnnotations."prometheus\.io/scrape"=true \
--set controller.service.type=LoadBalancer
安装后先确认三件事:Pod 是否 Ready、Service 是否拿到外部地址、准入 Webhook 是否正常。准入 Webhook 用于校验 Ingress 注解合法性,若它不可用,新建 Ingress 会被拒绝,这是排障时最容易被忽略的一环。
kubectl -n ingress-nginx get pods,svc
kubectl -n ingress-nginx get validatingwebhookconfiguration
一个最小 Ingress 示例,把 demo.example.com 的流量转发到后端 Service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: demo-svc
port:
number: 80
二、注解调优:从全局到单条规则
ingress-nginx 的调优分三层:Controller 级(ConfigMap ingress-nginx-controller,影响所有 Ingress)、Ingress 级(注解,影响该 Ingress 下所有规则)、以及部分注解可作用于单条 path。常见调优方向包括:
- 超时与缓冲:
proxy-connect-timeout、proxy-read-timeout、proxy-body-size。上传大文件时若返回 413,通常是proxy-body-size默认 1m 所致。 - 连接复用:
upstream-keepalive-connections与upstream-keepalive-timeout,减少到后端的握手开销。 - 负载均衡:
load-balance可选round_robin、least_conn、ewma、ip_hash。长连接场景下least_conn往往比默认轮询更均衡。 - 会话保持:
affinity: cookie配合session-cookie-name,适合有状态会话但未做外部存储的服务。
调优后不要只看“配置是否写入”,而要看实际效果。可通过 /nginx_status 或 Prometheus 指标观察 nginx_ingress_controller_requests、request_duration_seconds 的分布变化,再决定是否继续调整。
三、灰度发布:Canary 注解
ingress-nginx 原生支持基于权重的金丝雀发布。做法是:为稳定版建一个 Ingress,为金丝雀版建另一个 Ingress,并在金丝雀 Ingress 上打 canary 注解。控制器会把两者合并到同一个 upstream,并按权重分流。
metadata:
name: demo-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
除权重外,还支持按请求头(canary-by-header)、按 Cookie(canary-by-cookie)分流,便于内部先验证再放量。灰度过程中应重点观察金丝雀版本的错误率与延迟,一旦异常,把权重改回 0 即可快速回滚,无需删除 Ingress。
四、重写与重定向
重写(rewrite)改变转发给后端的路径,重定向(redirect)改变返回给客户端的地址,两者语义不同,容易混用。典型场景:外部路径 /app 对应后端根路径 /,用 rewrite-target: /;而把 HTTP 强制跳 HTTPS,则用 force-ssl-redirect 或 permanent-redirect。
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
# path: /app(/|$)(.*)
使用正则重写时必须开启 use-regex,并注意捕获组编号与 rewrite-target 中的 $1、$2 对应关系。重定向则常用 permanent-redirect(301)或 temporal-redirect(302),前者会被浏览器缓存,调试阶段建议先用 302。
五、限流与认证集成
限流通过 limit-rps、limit-rpm、limit-burst-multiplier 控制,超出阈值返回 503。它基于 nginx 的 limit_req 模块,按客户端 IP 维度生效,因此要留意 NAT 场景下大量用户共享同一出口 IP 的问题。
nginx.ingress.kubernetes.io/limit-rps: "20"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"
认证集成常见三种:Basic Auth(auth-type: basic + Secret)、外部认证(auth-url 指向认证服务,配合 auth-response-headers 透传用户信息)、以及 OAuth2 Proxy 等独立组件。Basic Auth 适合内部工具,外部认证适合与统一登录对接。
六、工程实践中的判断依据
把上述能力串起来,一个可复现的验证闭环是:先确认 Pod 与 Webhook 正常,再用最小 Ingress 打通链路;随后按需叠加注解,每加一类注解就观察一次指标或日志。例如开启限流后,用压测工具打到阈值以上,确认返回 503 且 nginx_ingress_controller_requests 中对应状态码计数上升;配置灰度后,用带 canary-by-header 的请求验证是否命中金丝雀版本。判断“是否生效”的依据应来自实际响应与指标,而不是配置文件里写了什么。
permanent-redirect(301)后浏览器会长期缓存跳转结果,调试阶段优先用 302,确认无误再切换为 301。