上一篇【第17篇】Ingress——HTTP流量的“总管家“
下一篇【第19篇】Volume——容器数据的"不动产"
摘要
上一篇文章咱们搞懂了Ingress资源怎么配,但Ingress本身只是个"规则说明书"——它不会转发任何一个HTTP请求。真正干活的是Ingress Controller。K8s社区有十几种Controller可选,最主流的是Nginx Ingress,其次是Traefik和Contour。
这篇文章以Nginx Ingress Controller为主角,先讲它的工作原理(监听Ingress→动态拼nginx.conf→reload),然后扒一扒那些高频使用的Annotations(你以后80%的日常配置全靠它),接着演示金丝雀发布的三种玩法(按权重、按Header、按Cookie),最后横向对比Traefik和Contour,帮你做出选型决定。我见过太多团队随便装了个Controller就上线了,结果踩了各种坑——看完这篇你能避免90%。
一、Nginx Ingress Controller的工作原理——“动态nginx.conf生成器”
Nginx Ingress Controller的核心逻辑非常简单:监听K8s API → 拼nginx.conf → reload nginx。
【Nginx Ingress Controller 工作流程】 K8s API Server │ │ Ingress资源变更通知 ▼ ┌─────────────────────────────────────────────────────┐ │ Nginx Ingress Controller Pod │ │ │ │ ┌───────────────────────┐ │ │ │ Ingress Watcher │ 监听Ingress/Service │ │ │ (持续watch API Server)│ /Secret等资源变化 │ │ └───────────┬───────────┘ │ │ │ │ │ │ 资源变更 │ │ ▼ │ │ ┌───────────────────────┐ │ │ │ Template Engine │ 把Ingress规则翻译成 │ │ │ (拼nginx.conf) │ nginx的server/location │ │ └───────────┬───────────┘ │ │ │ │ │ │ 生成新的nginx.conf │ │ ▼ │ │ ┌───────────────────────┐ │ │ │ Nginx Reloader │ 测试配置语法 │ │ │ (nginx -t && reload) │ → 优雅重载 │ │ └───────────────────────┘ │ │ │ │ ┌───────────────────────┐ │ │ │ Nginx 进程 │ 真正转发HTTP流量 │ │ │ :80 / :443 │ │ │ └───────────────────────┘ │ └─────────────────────────────────────────────────────┘# 一个简单的Ingress规则# 会被转换成下面的nginx.confapiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:api-ingressspec:ingressClassName:nginxrules:-host:api.example.comhttp:paths:-path:/userspathType:Prefixbackend:service:name:users-serviceport:number:8080# Nginx Ingress Controller 自动生成的 nginx.conf(简化版) server { listen 80; server_name api.example.com; location /users { # 根据Ingress的annotations动态生成各种配置 # rewrite规则、CORS头、限流...都注入在这里 proxy_pass http://upstream-users-service:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } upstream upstream-users-service { # 动态服务发现:自动拉取users-service的Endpoints server 10.244.1.5:8080 max_fails=3 fail_timeout=30s; server 10.244.2.3:8080 max_fails=3 fail_timeout=30s; server 10.244.3.7:8080 max_fails=3 fail_timeout=30s; }要点:Nginx Ingress Controller的reload是有代价的——每次Ingress变更都会触发
nginx -t && nginx -s reload。在几百个Ingress的大集群里,频繁reload会造成短暂的连接中断。Nginx官方已经推出了**Ingress NGINX Controller 1.0+**支持动态配置更新(通过Lua插件),减少reload次数。如果你用的是老版本,注意监控reload频率。
二、Annotations大全——80%的日常配置靠这个
Nginx Ingress Controller有上百个Annotations,但日常用的就那十几个。我按功能分类给你列出来。
2.1 路由和重写
| Annotation | 用途 | 示例 |
|---|---|---|
rewrite-target | URL重写目标 | /$2 |
use-regex | 启用正则路径匹配 | "true" |
app-root | 应用根路径 | "/app" |
server-snippet | 自定义nginx server块 | 慎用!会影响全局 |
# URL重写:去掉/api前缀apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:rewrite-exampleannotations:nginx.ingress.kubernetes.io/rewrite-target:/$2nginx.ingress.kubernetes.io/use-regex:"true"spec:ingressClassName:nginxrules:-host:example.comhttp:paths:-path:/api(/|$)(.*)pathType:ImplementationSpecificbackend:service:name:backend-svcport:number:80802.2 安全和认证
metadata:annotations:# HTTPS强制跳转nginx.ingress.kubernetes.io/ssl-redirect:"true"# 强制使用HSTSnginx.ingress.kubernetes.io/hsts:"true"nginx.ingress.kubernetes.io/hsts-max-age:"31536000"# IP白名单nginx.ingress.kubernetes.io/whitelist-source-range:"10.0.0.0/8,172.16.0.0/12,1.2.3.4"# Basic认证(需要先创建Secret)nginx.ingress.kubernetes.io/auth-type:basicnginx.ingress.kubernetes.io/auth-secret:basic-auth-secretnginx.ingress.kubernetes.io/auth-realm:"请输入用户名和密码"# 客户端证书认证(mTLS)nginx.ingress.kubernetes.io/auth-tls-verify-client:"on"nginx.ingress.kubernetes.io/auth-tls-secret:default/ca-secret2.3 CORS跨域配置
metadata:annotations:nginx.ingress.kubernetes.io/enable-cors:"true"nginx.ingress.kubernetes.io/cors-allow-origin:"https://example.com"nginx.ingress.kubernetes.io/cors-allow-methods:"GET, POST, PUT, DELETE, OPTIONS"nginx.ingress.kubernetes.io/cors-allow-headers:"Authorization, Content-Type, X-Request-ID"nginx.ingress.kubernetes.io/cors-allow-credentials:"true"nginx.ingress.kubernetes.io/cors-max-age:"3600"要点:CORS配置在Ingress层做比在应用层做好得多——所有微服务共享一套跨域策略,不用每个服务自己写。而且改策略只改Ingress Annotation就行,不用重新部署服务。
2.4 连接和性能
| Annotation | 用途 | 推荐值 |
|---|---|---|
proxy-body-size | 请求体大小限制 | "20m" |
proxy-connect-timeout | 连接后端超时 | "10" |
proxy-read-timeout | 读后端响应超时 | "60" |
proxy-send-timeout | 向后端发送超时 | "60" |
proxy-buffering | 代理缓冲 | "on" |
limit-rps | 每秒请求限流 | "10" |
limit-burst-multiplier | 突发倍数 | "5" |
metadata:annotations:# 请求体限制:防止大文件上传耗尽内存nginx.ingress.kubernetes.io/proxy-body-size:"20m"# 超时设置:WebSocket需要长超时nginx.ingress.kubernetes.io/proxy-read-timeout:"3600"nginx.ingress.kubernetes.io/proxy-send-timeout:"3600"# 速率限制:每秒5个请求,突发10个nginx.ingress.kubernetes.io/limit-rps:"5"nginx.ingress.kubernetes.io/limit-burst-multiplier:"2"2.5 会话亲和和负载
metadata:annotations:# Cookie会话亲和(同一用户始终到同一Pod)nginx.ingress.kubernetes.io/affinity:"cookie"nginx.ingress.kubernetes.io/session-cookie-name:"ROUTE_ID"nginx.ingress.kubernetes.io/session-cookie-path:"/"nginx.ingress.kubernetes.io/session-cookie-expires:"3600"nginx.ingress.kubernetes.io/session-cookie-max-age:"3600"三、金丝雀发布——三种玩法全掌握
Nginx Ingress原生支持金丝雀发布(Canary),不需要Service Mesh也能做灰度。三种方式:
3.1 按权重(Canary by Weight)
【权重金丝雀——按百分比分流】 100% 流量 │ ▼ ┌─────────────────────────────┐ │ Ingress Controller │ │ │ │ canary-weight: "20" │ │ │ │ │ ┌───┴───┐ │ │ │ 分流 │ │ │ └───┬───┘ │ │ ┌────┴────┐ │ │ │ │ │ │ 20% 80% │ └──┼────────┼───────────────┘ │ │ ▼ ▼ ┌──────┐ ┌──────┐ │v2.0 │ │v1.0 │ │Canary│ │Stable│ └──────┘ └──────┘# Stable Ingress(主版本)apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:myapp-stablespec:ingressClassName:nginxrules:-host:myapp.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:myapp-stable-svc# 稳定版本port:number:8080---# Canary Ingress(灰度版本)apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:myapp-canaryannotations:nginx.ingress.kubernetes.io/canary:"true"nginx.ingress.kubernetes.io/canary-weight:"20"# 20%流量spec:ingressClassName:nginxrules:-host:myapp.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:myapp-canary-svc# 灰度版本port:number:80803.2 按Header(Canary by Header)
# 只有带了 x-canary: true 的请求才走到灰度版本metadata:annotations:nginx.ingress.kubernetes.io/canary:"true"nginx.ingress.kubernetes.io/canary-by-header:"x-canary"nginx.ingress.kubernetes.io/canary-by-header-value:"true"# 测试:正常用户走stablecurl-H"Host: myapp.example.com"http://ingress-ip/# 返回 v1.0 内容# 测试:灰度用户走canarycurl-H"Host: myapp.example.com"-H"x-canary: true"http://ingress-ip/# 返回 v2.0 内容3.3 按Cookie(Canary by Cookie)
# 设置了 always=yes Cookie的用户走灰度版本metadata:annotations:nginx.ingress.kubernetes.io/canary:"true"nginx.ingress.kubernetes.io/canary-by-cookie:"canary_user"【三种金丝雀方式对比】 方式 │ 粒度 │ 适用场景 ──────────────┼──────────────┼───────────────────────── 权重(weight) │ 流量百分比 │ 通用灰度,逐步切量 Header │ 请求级 │ 开发/QA测试,内部用户预览 Cookie │ 用户级 │ 白名单灰度,VIP用户优先体验要点:金丝雀Annotation可以组合使用——比如同时设weight和header,"20%流量"中只有"带了header的请求"才转发到canary。这在精确控制灰度范围时非常有用。
四、安装和部署——三种主流方式
4.1 Helm安装(推荐)
# 添加Helm仓库helm repoaddingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update# 安装(生产参数)helminstallingress-nginx ingress-nginx/ingress-nginx\--namespaceingress-nginx\--create-namespace\--setcontroller.replicaCount=2\--setcontroller.service.type=LoadBalancer\--setcontroller.service.externalTrafficPolicy=Local\--setcontroller.metrics.enabled=true\--setcontroller.config.use-forwarded-headers="true"\--setcontroller.config.compute-full-forwarded-for="true"4.2 纯YAML安装
kubectl apply-fhttps://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml4.3 验证部署
# 确认Controller Pod在运行kubectl get pods-ningress-nginx# NAME READY STATUS# ingress-nginx-controller-xxx-yyy 1/1 Running# ingress-nginx-controller-xxx-zzz 1/1 Running# 确认Service已分配外部IPkubectl get svc-ningress-nginx# NAME TYPE EXTERNAL-IP PORT(S)# ingress-nginx-controller LoadBalancer 1.2.3.4 80:30080/TCP,443:30443/TCP五、主流Controller横向对比——怎么选?
K8s社区有十几种Ingress Controller,但真正值得考虑的就四个:
【Ingress Controller 选型决策树】 你的需求是什么? │ ┌────┴────────────────────────────────────┐ │ │ │ "我需要简单、稳定的HTTP反向代理" │ "我要API网关级别的功能" │ 社区最大、文档最丰富 │ 动态配置、中间件、可观测性 │ │ ▼ ▼ Nginx Ingress ✅ ┌────┴────┐ (Kubernetes社区版) │ │ ▼ ▼ Traefik Contour/Envoy (K8s原生) (适合Istio用户)| Controller | 优点 | 缺点 | 适合谁 |
|---|---|---|---|
| Nginx Ingress | 社区最大、文档最多、Annotations功能丰富、久经考验 | reload性能开销、配置基于文件、较重 | 需要稳定可靠HTTP代理的团队 |
| Traefik | K8s原生、动态配置(不用reload)、自带Dashboard、自动HTTPS | 社区相对小、复杂场景Annotations不足 | 中小团队,追求开箱即用 |
| Contour + Envoy | 基于Envoy、xDS动态配置、Gateway API原生支持 | 文档相对少、社区比Nginx小 | 用Istio/Envoy生态的团队 |
| Istio Gateway | 服务网格级控制、零信任安全 | 太重了——如果只做Ingress别用Istio | 已用Istio Service Mesh的团队 |
要点:除非你有明确的理由选别的,默认选Nginx Ingress(Kubernetes社区维护版,不是Nginx公司的NIC)。它的文档最多、社区最活跃、你能Google到的各种问题基本都有解决方案。Traefik在开发体验上是更好的选择(自带Dashboard、动态配置、自动HTTPS),但在企业级功能深度上不如Nginx Ingress。
# 两个Nginx Ingress的区别(很多新人搞混)## Nginx Ingress (kubernetes/ingress-nginx) —— Kubernetes社区维护# GitHub: kubernetes/ingress-nginx# ★ 开源、免费、社区最活跃## NGINX Ingress Controller (nginxinc/kubernetes-ingress) —— Nginx公司维护# GitHub: nginxinc/kubernetes-ingress# ★ 开源(有收费Plus版)、功能更全但更新慢## 本文讲的是第一个(Kubernetes社区版)各Controller的核心功能对比
| 功能 | Nginx Ingress | Traefik | Contour |
|---|---|---|---|
| HTTP路由 | ✅ | ✅ | ✅ |
| HTTPS/TLS | ✅ | ✅ 自动 | ✅ |
| TCP/UDP | ✅ ConfigMap | ✅ | ❌ |
| 金丝雀发布 | ✅ Annotations | ✅ CRD | ✅ |
| 速率限制 | ✅ Annotations | ✅ Middleware | ✅ |
| 认证 | ✅ Annotations | ✅ Middleware | ✅ |
| 动态配置(无reload) | ⚠️ 有限 | ✅ | ✅ |
| Dashboard | ⚠️ 需额外部署 | ✅ 内置 | ⚠️ 需额外 |
| Gateway API | ⚠️ 实验性 | ✅ | ✅ |
六、常见坑和调试技巧
6.1 最常见的坑
# 坑1:Ingress创建了但404# 大概率是 ingressClassName 没写或写错了kubectl get ingress myapp-oyaml|grepingressClassName# 坑2:TLS不生效# 检查Secret是否存在、Secret是否正确的tls类型kubectl get secret example-tls-oyaml|greptype# type: kubernetes.io/tls ← 必须是这个# 坑3:rewrite没生效# 检查正则捕获组——path里(.*)是$1还是$2取决于括号有几组# path: /api/(.*) → rewrite-target: /$1 ✅# path: /api(/|$)(.*) → rewrite-target: /$2 ✅# 坑4:大文件上传失败# 检查 proxy-body-size,默认只有1m!kubectl describe ingress myapp|grepproxy-body-size6.2 调试命令
# 看Ingress Controller日志kubectl logs-ningress-nginx-lapp.kubernetes.io/name=ingress-nginx-f# 看生成的nginx.confkubectlexec-ningress-nginx deploy/ingress-nginx-controller --cat/etc/nginx/nginx.conf# 测试某条Ingress规则是否生效kubectlexec-ningress-nginx deploy/ingress-nginx-controller -- nginx-t# 看某个Ingress的详细状态kubectl describe ingress myapp本篇小结
Ingress Controller是K8s HTTP网关的真正核心——Ingress资源只是"接口",Controller才是"实现":
- Nginx Ingress工作原理:Watch K8s API → 拼nginx.conf → reload——简单但可靠
- Annotations是你的日常武器:rewrite、CORS、rate-limit、whitelist、auth等几十个Annotation,覆盖了80%的HTTP网关需求
- 金丝雀发布:权重(百分比切流)、Header(内部测试)、Cookie(白名单灰度),三种玩法自由组合
- 选型建议:默认Nginx Ingress,追求开发体验用Traefik,已用Envoy生态选Contour
下一篇咱们聊Volume——容器一重启数据就没了,那数据库怎么办?K8s的存储方案有哪些?emptyDir和hostPath又是什么鬼?
上一篇【第17篇】Ingress——HTTP流量的“总管家“
下一篇【第19篇】Volume——容器数据的"不动产"