公司动态

【Kubernetes从入门到精通】第18篇:Ingress Controller选型和实战——Nginx Ingress完全指南

📅 2026/8/6 9:56:37
【Kubernetes从入门到精通】第18篇:Ingress Controller选型和实战——Nginx Ingress完全指南
上一篇【第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_fails3 fail_timeout30s; server 10.244.2.3:8080 max_fails3 fail_timeout30s; server 10.244.3.7:8080 max_fails3 fail_timeout30s; }要点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-targetURL重写目标/$2use-regex启用正则路径匹配trueapp-root应用根路径/appserver-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:truespec: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:truenginx.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认证需要先创建Secretnginx.ingress.kubernetes.io/auth-type:basicnginx.ingress.kubernetes.io/auth-secret:basic-auth-secretnginx.ingress.kubernetes.io/auth-realm:请输入用户名和密码# 客户端证书认证mTLSnginx.ingress.kubernetes.io/auth-tls-verify-client:onnginx.ingress.kubernetes.io/auth-tls-secret:default/ca-secret2.3 CORS跨域配置metadata:annotations:nginx.ingress.kubernetes.io/enable-cors:truenginx.ingress.kubernetes.io/cors-allow-origin:https://example.comnginx.ingress.kubernetes.io/cors-allow-methods:GET, POST, PUT, DELETE, OPTIONSnginx.ingress.kubernetes.io/cors-allow-headers:Authorization, Content-Type, X-Request-IDnginx.ingress.kubernetes.io/cors-allow-credentials:truenginx.ingress.kubernetes.io/cors-max-age:3600要点CORS配置在Ingress层做比在应用层做好得多——所有微服务共享一套跨域策略不用每个服务自己写。而且改策略只改Ingress Annotation就行不用重新部署服务。2.4 连接和性能Annotation用途推荐值proxy-body-size请求体大小限制20mproxy-connect-timeout连接后端超时10proxy-read-timeout读后端响应超时60proxy-send-timeout向后端发送超时60proxy-buffering代理缓冲onlimit-rps每秒请求限流10limit-burst-multiplier突发倍数5metadata:annotations:# 请求体限制防止大文件上传耗尽内存nginx.ingress.kubernetes.io/proxy-body-size:20m# 超时设置WebSocket需要长超时nginx.ingress.kubernetes.io/proxy-read-timeout:3600nginx.ingress.kubernetes.io/proxy-send-timeout:3600# 速率限制每秒5个请求突发10个nginx.ingress.kubernetes.io/limit-rps:5nginx.ingress.kubernetes.io/limit-burst-multiplier:22.5 会话亲和和负载metadata:annotations:# Cookie会话亲和同一用户始终到同一Podnginx.ingress.kubernetes.io/affinity:cookienginx.ingress.kubernetes.io/session-cookie-name:ROUTE_IDnginx.ingress.kubernetes.io/session-cookie-path:/nginx.ingress.kubernetes.io/session-cookie-expires:3600nginx.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:truenginx.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 按HeaderCanary by Header# 只有带了 x-canary: true 的请求才走到灰度版本metadata:annotations:nginx.ingress.kubernetes.io/canary:truenginx.ingress.kubernetes.io/canary-by-header:x-canarynginx.ingress.kubernetes.io/canary-by-header-value:true# 测试正常用户走stablecurl-HHost: myapp.example.comhttp://ingress-ip/# 返回 v1.0 内容# 测试灰度用户走canarycurl-HHost: myapp.example.com-Hx-canary: truehttp://ingress-ip/# 返回 v2.0 内容3.3 按CookieCanary by Cookie# 设置了 alwaysyes Cookie的用户走灰度版本metadata:annotations:nginx.ingress.kubernetes.io/canary:truenginx.ingress.kubernetes.io/canary-by-cookie:canary_user【三种金丝雀方式对比】 方式 │ 粒度 │ 适用场景 ──────────────┼──────────────┼───────────────────────── 权重(weight) │ 流量百分比 │ 通用灰度逐步切量 Header │ 请求级 │ 开发/QA测试内部用户预览 Cookie │ 用户级 │ 白名单灰度VIP用户优先体验要点金丝雀Annotation可以组合使用——比如同时设weight和header20%流量中只有带了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.replicaCount2\--setcontroller.service.typeLoadBalancer\--setcontroller.service.externalTrafficPolicyLocal\--setcontroller.metrics.enabledtrue\--setcontroller.config.use-forwarded-headerstrue\--setcontroller.config.compute-full-forwarded-fortrue4.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代理的团队TraefikK8s原生、动态配置不用reload、自带Dashboard、自动HTTPS社区相对小、复杂场景Annotations不足中小团队追求开箱即用Contour Envoy基于Envoy、xDS动态配置、Gateway API原生支持文档相对少、社区比Nginx小用Istio/Envoy生态的团队Istio Gateway服务网格级控制、零信任安全太重了——如果只做Ingress别用Istio已用Istio Service Mesh的团队要点除非你有明确的理由选别的默认选Nginx IngressKubernetes社区维护版不是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 IngressTraefikContourHTTP路由✅✅✅HTTPS/TLS✅✅ 自动✅TCP/UDP✅ ConfigMap✅❌金丝雀发布✅ Annotations✅ CRD✅速率限制✅ Annotations✅ Middleware✅认证✅ Annotations✅ Middleware✅动态配置无reload⚠️ 有限✅✅Dashboard⚠️ 需额外部署✅ 内置⚠️ 需额外Gateway API⚠️ 实验性✅✅六、常见坑和调试技巧6.1 最常见的坑# 坑1Ingress创建了但404# 大概率是 ingressClassName 没写或写错了kubectl get ingress myapp-oyaml|grepingressClassName# 坑2TLS不生效# 检查Secret是否存在、Secret是否正确的tls类型kubectl get secret example-tls-oyaml|greptype# type: kubernetes.io/tls ← 必须是这个# 坑3rewrite没生效# 检查正则捕获组——path里(.*)是$1还是$2取决于括号有几组# path: /api/(.*) → rewrite-target: /$1 ✅# path: /api(/|$)(.*) → rewrite-target: /$2 ✅# 坑4大文件上传失败# 检查 proxy-body-size默认只有1mkubectl describe ingress myapp|grepproxy-body-size6.2 调试命令# 看Ingress Controller日志kubectl logs-ningress-nginx-lapp.kubernetes.io/nameingress-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——容器数据的不动产