Subsections of Networking
Ingress
Kubernetes Ingress 原理详解
Ingress 是 Kubernetes 中用于管理集群外部访问集群内服务的 API 对象,提供 HTTP/HTTPS 路由功能。
🎯 Ingress 的作用
没有 Ingress 的问题
问题 1:每个服务需要一个 LoadBalancer
┌────────────────────────────────────┐
│ Service A (LoadBalancer) $$$ │
│ Service B (LoadBalancer) $$$ │
│ Service C (LoadBalancer) $$$ │
└────────────────────────────────────┘
成本高、管理复杂、IP 地址浪费
问题 2:无法基于域名/路径路由
客户端 → NodePort:30001 (Service A)
客户端 → NodePort:30002 (Service B)
需要记住不同的端口,不友好使用 Ingress 的方案
单一入口 + 智能路由
┌───────────────────────────────────────┐
│ Ingress Controller │
│ (一个 LoadBalancer 或 NodePort) │
└───────────┬───────────────────────────┘
│ 根据域名/路径路由
┌───────┴───────┬──────────┐
▼ ▼ ▼
Service A Service B Service C
(ClusterIP) (ClusterIP) (ClusterIP)🏗️ Ingress 架构组成
核心组件
┌─────────────────────────────────────────────┐
│ Ingress 生态系统 │
├─────────────────────────────────────────────┤
│ 1. Ingress Resource (资源对象) │
│ └─ 定义路由规则(YAML) │
│ │
│ 2. Ingress Controller (控制器) │
│ └─ 读取 Ingress,配置负载均衡器 │
│ │
│ 3. 负载均衡器 (Nginx/Traefik/HAProxy) │
│ └─ 实际处理流量的组件 │
└─────────────────────────────────────────────┘📋 Ingress Resource (资源定义)
基础示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
# 1. 基于域名路由
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
# 2. TLS/HTTPS 配置
tls:
- hosts:
- example.com
secretName: example-tls完整功能示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: advanced-ingress
namespace: default
annotations:
# Nginx 特定配置
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
# 自定义响应头
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header X-Custom-Header "Hello from Ingress";
spec:
# IngressClass (指定使用哪个 Ingress Controller)
ingressClassName: nginx
# TLS 配置
tls:
- hosts:
- app.example.com
- api.example.com
secretName: example-tls-secret
# 路由规则
rules:
# 规则 1:app.example.com
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# 规则 2:api.example.com
- host: api.example.com
http:
paths:
# /v1/* 路由到 api-v1
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1-service
port:
number: 8080
# /v2/* 路由到 api-v2
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080
# 规则 3:默认后端(可选)
defaultBackend:
service:
name: default-backend
port:
number: 80🎛️ PathType (路径匹配类型)
三种匹配类型
| PathType | 匹配规则 | 示例 |
|---|---|---|
| Prefix | 前缀匹配 | /foo 匹配 /foo, /foo/, /foo/bar |
| Exact | 精确匹配 | /foo 只匹配 /foo,不匹配 /foo/ |
| ImplementationSpecific | 由 Ingress Controller 决定 | 取决于实现 |
示例对比
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-types-demo
spec:
rules:
- host: example.com
http:
paths:
# Prefix 匹配
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# 匹配:
# ✅ /api
# ✅ /api/
# ✅ /api/users
# ✅ /api/v1/users
# Exact 匹配
- path: /login
pathType: Exact
backend:
service:
name: auth-service
port:
number: 80
# 匹配:
# ✅ /login
# ❌ /login/
# ❌ /login/oauth🚀 Ingress Controller (控制器)
常见 Ingress Controller
| Controller | 特点 | 适用场景 |
|---|---|---|
| Nginx Ingress | 最流行,功能强大 | 通用场景,生产推荐 |
| Traefik | 云原生,动态配置 | 微服务,自动服务发现 |
| HAProxy | 高性能,企业级 | 大流量,高并发 |
| Kong | API 网关功能 | API 管理,插件生态 |
| Istio Gateway | 服务网格集成 | 复杂微服务架构 |
| AWS ALB | 云原生(AWS) | AWS 环境 |
| GCE | 云原生(GCP) | GCP 环境 |
🔧 Ingress Controller 工作原理
核心流程
┌─────────────────────────────────────────────┐
│ 1. 用户创建/更新 Ingress Resource │
│ kubectl apply -f ingress.yaml │
└────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 2. Ingress Controller 监听 API Server │
│ - Watch Ingress 对象 │
│ - Watch Service 对象 │
│ - Watch Endpoints 对象 │
└────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 3. 生成配置文件 │
│ Nginx: /etc/nginx/nginx.conf │
│ Traefik: 动态配置 │
│ HAProxy: /etc/haproxy/haproxy.cfg │
└────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 4. 重载/更新负载均衡器 │
│ nginx -s reload │
└────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 5. 流量路由生效 │
│ 客户端请求 → Ingress → Service → Pod │
└─────────────────────────────────────────────┘📦 部署 Nginx Ingress Controller
方式 1:使用官方 Helm Chart (推荐)
# 添加 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.service.type=LoadBalancer
# 查看部署状态
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx方式 2:使用 YAML 部署
# 下载官方 YAML
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
# 查看部署
kubectl get all -n ingress-nginx核心组件
# 1. Deployment - Ingress Controller Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 2 # 高可用建议 2+
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
spec:
serviceAccountName: ingress-nginx
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.9.0
args:
- /nginx-ingress-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
httpGet:
path: /healthz
port: 10254
readinessProbe:
httpGet:
path: /healthz
port: 10254
---
# 2. Service - 暴露 Ingress Controller
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer # 或 NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
---
# 3. ConfigMap - Nginx 全局配置
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
# 自定义 Nginx 配置
proxy-body-size: "100m"
proxy-connect-timeout: "15"
proxy-read-timeout: "600"
proxy-send-timeout: "600"
use-forwarded-headers: "true"🌐 完整流量路径
请求流程详解
客户端
│ 1. DNS 解析
│ example.com → LoadBalancer IP (1.2.3.4)
▼
LoadBalancer / NodePort
│ 2. 转发到 Ingress Controller Pod
▼
Ingress Controller (Nginx Pod)
│ 3. 读取 Ingress 规则
│ Host: example.com
│ Path: /api/users
│ 4. 匹配规则
│ rule: host=example.com, path=/api
│ backend: api-service:8080
▼
Service (api-service)
│ 5. Service 选择器匹配 Pod
│ selector: app=api
│ 6. 查询 Endpoints
│ endpoints: 10.244.1.5:8080, 10.244.2.8:8080
│ 7. 负载均衡(默认轮询)
▼
Pod (api-xxxx)
│ 8. 容器处理请求
│ Container Port: 8080
▼
应用响应
│ 9. 原路返回
▼
客户端收到响应网络数据包追踪
# 客户端发起请求
curl -H "Host: example.com" http://1.2.3.4/api/users
# 1. DNS 解析
example.com → 1.2.3.4 (LoadBalancer External IP)
# 2. TCP 连接
Client:54321 → LoadBalancer:80
# 3. LoadBalancer 转发
LoadBalancer:80 → Ingress Controller Pod:80 (10.244.0.5:80)
# 4. Ingress Controller 内部处理
Nginx 读取配置:
location /api {
proxy_pass http://api-service.default.svc.cluster.local:8080;
}
# 5. 查询 Service
kube-proxy/iptables 规则:
api-service:8080 → Endpoints
# 6. 负载均衡到 Pod
10.244.0.5 → 10.244.1.5:8080 (Pod IP)
# 7. 响应返回
Pod → Ingress Controller → LoadBalancer → Client🔒 HTTPS/TLS 配置
创建 TLS Secret
# 方式 1:使用自签名证书(测试环境)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=example.com"
kubectl create secret tls example-tls \
--cert=tls.crt \
--key=tls.key
# 方式 2:使用 Let's Encrypt (生产环境,推荐)
# 安装 cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
# 创建 ClusterIssuer
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF配置 HTTPS Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: https-ingress
annotations:
# 自动重定向 HTTP 到 HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# 使用 cert-manager 自动申请证书
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-tls # cert-manager 会自动创建这个 Secret
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80验证 HTTPS
# 检查证书
curl -v https://example.com
# 查看 Secret
kubectl get secret example-tls
kubectl describe secret example-tls
# 测试 HTTP 自动重定向
curl -I http://example.com
# HTTP/1.1 308 Permanent Redirect
# Location: https://example.com/🎨 高级路由场景
场景 1:基于路径的路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-based-routing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myapp.com
http:
paths:
# /api/v1/* → api-v1-service
- path: /api/v1(/|$)(.*)
pathType: Prefix
backend:
service:
name: api-v1-service
port:
number: 8080
# /api/v2/* → api-v2-service
- path: /api/v2(/|$)(.*)
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080
# /admin/* → admin-service
- path: /admin
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
# /* → frontend-service (默认)
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80场景 2:基于子域名的路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: subdomain-routing
spec:
rules:
# www.example.com
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: website-service
port:
number: 80
# api.example.com
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# blog.example.com
- host: blog.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: blog-service
port:
number: 80
# *.dev.example.com (通配符)
- host: "*.dev.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dev-environment
port:
number: 80场景 3:金丝雀发布 (Canary Deployment)
# 主版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
---
# 金丝雀版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
# 10% 流量到金丝雀版本
nginx.ingress.kubernetes.io/canary-weight: "10"
# 或基于请求头
# nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
# nginx.ingress.kubernetes.io/canary-by-header-value: "always"
# 或基于 Cookie
# nginx.ingress.kubernetes.io/canary-by-cookie: "canary"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2-canary
port:
number: 80场景 4:A/B 测试
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ab-testing
annotations:
# 基于请求头进行 A/B 测试
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Version"
nginx.ingress.kubernetes.io/canary-by-header-value: "beta"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-beta
port:
number: 80# 普通用户访问 A 版本
curl http://myapp.com
# Beta 用户访问 B 版本
curl -H "X-Version: beta" http://myapp.com🔧 常用 Annotations (Nginx)
基础配置
metadata:
annotations:
# SSL 重定向
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# 强制 HTTPS
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# 后端协议
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" # 或 HTTP, GRPC
# 路径重写
nginx.ingress.kubernetes.io/rewrite-target: /$2
# URL 重写
nginx.ingress.kubernetes.io/use-regex: "true"高级配置
metadata:
annotations:
# 上传文件大小限制
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# 超时配置
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
# 会话保持 (Sticky Session)
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
# 限流
nginx.ingress.kubernetes.io/limit-rps: "100" # 每秒请求数
nginx.ingress.kubernetes.io/limit-connections: "10" # 并发连接数
# CORS 配置
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
# 白名单
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,192.168.0.0/16"
# 基本认证
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
# 自定义 Nginx 配置片段
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Custom-Header: MyValue";
add_header X-Request-ID $request_id;🛡️ 安全配置
1. 基本认证
# 创建密码文件
htpasswd -c auth admin
# 输入密码
# 创建 Secret
kubectl create secret generic basic-auth --from-file=auth
# 应用到 Ingress
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - Please enter your credentials"
spec:
rules:
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80
EOF2. IP 白名单
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: whitelist-ingress
annotations:
# 只允许特定 IP 访问
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,192.168.1.100/32"
spec:
rules:
- host: internal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: internal-service
port:
number: 803. OAuth2 认证
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: oauth2-ingress
annotations:
nginx.ingress.kubernetes.io/auth-url: "https://oauth2-proxy.example.com/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://oauth2-proxy.example.com/oauth2/start?rd=$escaped_request_uri"
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: protected-service
port:
number: 80📊 监控和调试
查看 Ingress 状态
# 列出所有 Ingress
kubectl get ingress
# 详细信息
kubectl describe ingress example-ingress
# 查看 Ingress Controller 日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -f
# 查看生成的 Nginx 配置
kubectl exec -n ingress-nginx <ingress-controller-pod> -- cat /etc/nginx/nginx.conf测试 Ingress 规则
# 测试域名解析
nslookup example.com
# 测试 HTTP
curl -H "Host: example.com" http://<ingress-ip>/
# 测试 HTTPS
curl -k -H "Host: example.com" https://<ingress-ip>/
# 查看响应头
curl -I -H "Host: example.com" http://<ingress-ip>/
# 测试特定路径
curl -H "Host: example.com" http://<ingress-ip>/api/users常见问题排查
# 1. 检查 Ingress 是否有 Address
kubectl get ingress
# 如果 ADDRESS 列为空,说明 Ingress Controller 未就绪
# 2. 检查 Service 和 Endpoints
kubectl get svc
kubectl get endpoints
# 3. 检查 Ingress Controller Pod
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx <pod-name>
# 4. 检查 DNS 解析
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup example.com
# 5. 检查网络连通性
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
curl -H "Host: example.com" http://web-service.default.svc.cluster.local🎯 Ingress vs Service Type
对比表
| 维度 | Ingress | LoadBalancer | NodePort |
|---|---|---|---|
| 成本 | 1 个 LB | 每个服务 1 个 LB | 免费 |
| 域名路由 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 路径路由 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| TLS 终止 | ✅ 支持 | ⚠️ 需要额外配置 | ❌ 不支持 |
| 7 层功能 | ✅ 丰富 | ❌ 4 层 | ❌ 4 层 |
| 适用场景 | HTTP/HTTPS 服务 | 需要独立 LB 的服务 | 开发测试 |
💡 关键要点总结
Ingress 的价值
- 成本优化:多个服务共享一个 LoadBalancer
- 智能路由:基于域名、路径的 7 层路由
- TLS 管理:集中管理 HTTPS 证书
- 高级功能:限流、认证、重写、CORS 等
- 易于管理:声明式配置,统一入口
核心概念
- Ingress Resource:定义路由规则的 YAML
- Ingress Controller:读取规则并实现路由的控制器
- 负载均衡器:实际处理流量的组件(Nginx/Traefik/HAProxy)
典型使用场景
- ✅ 微服务 API 网关
- ✅ 多租户应用(基于子域名隔离)
- ✅ 蓝绿部署/金丝雀发布
- ✅ Web 应用统一入口
- ❌ 非 HTTP 协议(如 TCP/UDP,考虑使用 Gateway API)
🚀 高级话题
1. IngressClass (多 Ingress Controller)
在同一集群中运行多个 Ingress Controller:
# 定义 IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: traefik
spec:
controller: traefik.io/ingress-controller
---
# 使用特定的 IngressClass
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
ingressClassName: nginx # 🔑 指定使用 nginx 控制器
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80使用场景:
- 内部服务使用 Nginx,外部服务使用 Traefik
- 不同团队使用不同的 Ingress Controller
- 按环境划分(dev 用 Traefik,prod 用 Nginx)
2. 默认后端 (Default Backend)
处理未匹配任何规则的请求:
# 创建默认后端服务
apiVersion: v1
kind: Service
metadata:
name: default-backend
spec:
selector:
app: default-backend
ports:
- port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: default-backend
spec:
replicas: 1
selector:
matchLabels:
app: default-backend
template:
metadata:
labels:
app: default-backend
spec:
containers:
- name: default-backend
image: registry.k8s.io/defaultbackend-amd64:1.5
ports:
- containerPort: 8080
---
# 在 Ingress 中指定默认后端
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-default
spec:
defaultBackend:
service:
name: default-backend
port:
number: 80
rules:
- host: example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80效果:
- 访问
example.com/app→ app-service - 访问
example.com/other→ default-backend(404 页面) - 访问
unknown.com→ default-backend
3. ExternalName Service 与 Ingress
将 Ingress 路由到集群外部服务:
# 创建 ExternalName Service
apiVersion: v1
kind: Service
metadata:
name: external-api
spec:
type: ExternalName
externalName: api.external-service.com # 外部域名
---
# Ingress 路由到外部服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-ingress
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/upstream-vhost: "api.external-service.com"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /external
pathType: Prefix
backend:
service:
name: external-api
port:
number: 443使用场景:
- 集成第三方 API
- 混合云架构(部分服务在云外)
- 灰度迁移(逐步从外部迁移到集群内)
4. 跨命名空间引用 (ExternalName 方式)
Ingress 默认只能引用同一命名空间的 Service,跨命名空间需要特殊处理:
# Namespace: backend
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: backend
spec:
selector:
app: api
ports:
- port: 8080
---
# Namespace: frontend
# 创建 ExternalName Service 指向 backend 命名空间的服务
apiVersion: v1
kind: Service
metadata:
name: api-proxy
namespace: frontend
spec:
type: ExternalName
externalName: api-service.backend.svc.cluster.local
ports:
- port: 8080
---
# Ingress 在 frontend 命名空间
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cross-ns-ingress
namespace: frontend
spec:
rules:
- host: myapp.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-proxy # 引用同命名空间的 ExternalName Service
port:
number: 80805. TCP/UDP 服务暴露
Ingress 原生只支持 HTTP/HTTPS,对于 TCP/UDP 需要特殊配置:
Nginx Ingress Controller 的 TCP 配置
# ConfigMap 定义 TCP 服务
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
# 格式: "外部端口": "命名空间/服务名:服务端口"
"3306": "default/mysql:3306"
"6379": "default/redis:6379"
"27017": "databases/mongodb:27017"
---
# 修改 Ingress Controller Service,暴露 TCP 端口
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
# 添加 TCP 端口
- name: mysql
port: 3306
targetPort: 3306
- name: redis
port: 6379
targetPort: 6379
- name: mongodb
port: 27017
targetPort: 27017
selector:
app.kubernetes.io/name: ingress-nginx
---
# 修改 Ingress Controller Deployment,引用 ConfigMap
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
args:
- /nginx-ingress-controller
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
# ...其他参数访问方式:
# 连接 MySQL
mysql -h <ingress-lb-ip> -P 3306 -u root -p
# 连接 Redis
redis-cli -h <ingress-lb-ip> -p 63796. 灰度发布策略详解
基于权重的流量分配
# 生产版本 (90% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
---
# 灰度版本 (10% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80基于请求头的灰度
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-header
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"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80测试:
# 普通用户访问 v1
curl http://myapp.com
# 带特殊请求头的用户访问 v2
curl -H "X-Canary: true" http://myapp.com基于 Cookie 的灰度
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-cookie
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "canary"
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80使用:
- Cookie
canary=always→ 路由到 v2 - Cookie
canary=never→ 路由到 v1 - 无 Cookie → 根据权重路由
7. 性能优化
Nginx Ingress Controller 优化配置
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
# 工作进程数(建议等于 CPU 核心数)
worker-processes: "auto"
# 每个工作进程的连接数
max-worker-connections: "65536"
# 启用 HTTP/2
use-http2: "true"
# 启用 gzip 压缩
use-gzip: "true"
gzip-level: "6"
gzip-types: "text/plain text/css application/json application/javascript text/xml application/xml"
# 客户端请求体缓冲
client-body-buffer-size: "128k"
client-max-body-size: "100m"
# Keepalive 连接
keep-alive: "75"
keep-alive-requests: "1000"
# 代理缓冲
proxy-buffer-size: "16k"
proxy-buffers: "4 16k"
# 日志优化(生产环境可以禁用访问日志)
disable-access-log: "false"
access-log-params: "buffer=16k flush=5s"
# SSL 优化
ssl-protocols: "TLSv1.2 TLSv1.3"
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
ssl-prefer-server-ciphers: "true"
ssl-session-cache: "true"
ssl-session-cache-size: "10m"
ssl-session-timeout: "10m"
# 启用连接复用
upstream-keepalive-connections: "100"
upstream-keepalive-timeout: "60"
# 限制
limit-req-status-code: "429"
limit-conn-status-code: "429"Ingress Controller Pod 资源配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 3 # 高可用建议 3+
template:
spec:
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.9.0
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
# 启用性能分析
livenessProbe:
httpGet:
path: /healthz
port: 10254
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
port: 10254
periodSeconds: 58. 监控和可观测性
Prometheus 监控集成
# ServiceMonitor for Prometheus Operator
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
endpoints:
- port: metrics
interval: 30s查看 Ingress Controller 指标
# 访问 metrics 端点
kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller-metrics 10254:10254
# 浏览器访问
http://localhost:10254/metrics
# 关键指标:
# - nginx_ingress_controller_requests: 请求总数
# - nginx_ingress_controller_request_duration_seconds: 请求延迟
# - nginx_ingress_controller_response_size: 响应大小
# - nginx_ingress_controller_ssl_expire_time_seconds: SSL 证书过期时间Grafana 仪表盘
# 导入官方 Grafana 仪表盘
# Dashboard ID: 9614 (Nginx Ingress Controller)
# Dashboard ID: 11875 (Nginx Ingress Controller Request Handling Performance)9. 故障排查清单
问题 1: Ingress 没有分配 Address
# 检查
kubectl get ingress
# NAME CLASS HOSTS ADDRESS PORTS AGE
# my-app nginx example.com 80 5m
# 原因:
# 1. Ingress Controller 未运行
kubectl get pods -n ingress-nginx
# 2. Service type 不是 LoadBalancer
kubectl get svc -n ingress-nginx
# 3. 云提供商未分配 LoadBalancer IP
kubectl describe svc -n ingress-nginx ingress-nginx-controller问题 2: 502 Bad Gateway
# 原因 1: 后端 Service 不存在
kubectl get svc
# 原因 2: 后端 Pod 不健康
kubectl get pods
kubectl describe pod <pod-name>
# 原因 3: 端口配置错误
kubectl get svc <service-name> -o yaml | grep -A 5 ports
# 原因 4: 网络策略阻止
kubectl get networkpolicies
# 查看日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100问题 3: 503 Service Unavailable
# 原因: 没有健康的 Endpoints
kubectl get endpoints <service-name>
# 如果 ENDPOINTS 列为空:
# 1. 检查 Service selector 是否匹配 Pod labels
kubectl get svc <service-name> -o yaml | grep -A 3 selector
kubectl get pods --show-labels
# 2. 检查 Pod 是否 Ready
kubectl get pods
# 3. 检查容器端口是否正确
kubectl get pods <pod-name> -o yaml | grep -A 5 ports问题 4: TLS 证书问题
# 检查 Secret 是否存在
kubectl get secret <tls-secret-name>
# 查看证书内容
kubectl get secret <tls-secret-name> -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# 检查证书过期时间
kubectl get secret <tls-secret-name> -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates
# cert-manager 问题
kubectl get certificate
kubectl describe certificate <cert-name>
kubectl get certificaterequests问题 5: 路由规则不生效
# 1. 检查 Ingress 配置
kubectl describe ingress <ingress-name>
# 2. 查看生成的 Nginx 配置
kubectl exec -n ingress-nginx <controller-pod> -- cat /etc/nginx/nginx.conf | grep -A 20 "server_name example.com"
# 3. 测试域名解析
nslookup example.com
# 4. 使用 Host header 测试
curl -v -H "Host: example.com" http://<ingress-ip>/path
# 5. 检查 annotations 是否正确
kubectl get ingress <ingress-name> -o yaml | grep -A 10 annotations10. 生产环境最佳实践
✅ 高可用配置
# 1. 多副本 Ingress Controller
spec:
replicas: 3
# 2. Pod 反亲和性(分散到不同节点)
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- ingress-nginx
topologyKey: kubernetes.io/hostname
# 3. PodDisruptionBudget(确保至少 2 个副本运行)
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx✅ 资源限制
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
# HPA 自动扩缩容
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ingress-nginx-controller
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80✅ 安全加固
# 1. 只暴露必要端口
# 2. 启用 TLS 1.2+
# 3. 配置安全头
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Frame-Options: DENY";
more_set_headers "X-Content-Type-Options: nosniff";
more_set_headers "X-XSS-Protection: 1; mode=block";
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";
# 4. 配置 WAF(Web Application Firewall)
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "true"
# 5. 限流保护
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"✅ 监控告警
# Prometheus 告警规则示例
groups:
- name: ingress
rules:
- alert: IngressControllerDown
expr: up{job="ingress-nginx-controller-metrics"} == 0
for: 5m
annotations:
summary: "Ingress Controller is down"
- alert: HighErrorRate
expr: rate(nginx_ingress_controller_requests{status=~"5.."}[5m]) > 0.05
for: 5m
annotations:
summary: "High 5xx error rate"
- alert: HighLatency
expr: histogram_quantile(0.95, nginx_ingress_controller_request_duration_seconds_bucket) > 1
for: 10m
annotations:
summary: "High request latency (p95 > 1s)"📚 总结对比:Ingress vs 其他方案
Ingress vs LoadBalancer Service
场景:部署 10 个微服务
方案 A:每个服务一个 LoadBalancer
- 成本:10 个 LoadBalancer × $20/月 = $200/月
- 管理:10 个独立的 IP 地址
- 路由:无智能路由
- TLS:每个服务单独配置
方案 B:一个 Ingress
- 成本:1 个 LoadBalancer × $20/月 = $20/月 ✅
- 管理:1 个 IP 地址 ✅
- 路由:基于域名/路径智能路由 ✅
- TLS:集中管理证书 ✅Ingress vs API Gateway
| 功能 | Ingress | API Gateway (Kong/Tyk) |
|---|---|---|
| 基础路由 | ✅ | ✅ |
| 认证鉴权 | ⚠️ 基础 | ✅ 完善 |
| 限流熔断 | ⚠️ 基础 | ✅ 高级 |
| 插件生态 | ❌ 有限 | ✅ 丰富 |
| 学习曲线 | ✅ 简单 | ⚠️ 复杂 |
| 性能 | ✅ 高 | ⚠️ 中等 |
🎓 学习路径建议
入门 (1-2 周)
- 理解 Ingress 概念
- 部署 Nginx Ingress Controller
- 创建基本的 Ingress 规则
- 配置 HTTP/HTTPS 访问
进阶 (2-4 周)
- 掌握各种路由策略
- TLS 证书管理(cert-manager)
- 金丝雀发布
- 性能调优
高级 (1-2 月)
- 多 Ingress Controller 管理
- WAF 和安全加固
- 监控和告警
- 故障排查
专家 (持续学习)
- 源码阅读
- 自定义插件开发
- Gateway API 迁移
需要我详细展开某个特定主题,比如 cert-manager 自动化证书管理、Ingress Controller 源码分析,或者 Gateway API 新标准吗? 🚀
Nginx 性能优化
从通用优化、操作系统层、Nginx 配置层、架构层等多个维度,为你详细梳理的方式。
一、操作系统与硬件层优化
这是优化的基础,为 Nginx 提供一个高性能的运行环境。
增加文件描述符限制 Nginx 每个连接(尤其是静态文件)都会消耗一个文件描述符。如果并发高,默认限制很容易成为瓶颈。
# 临时生效 ulimit -n 65536 # 永久生效,修改 /etc/security/limits.conf * soft nofile 65536 * hard nofile 65536 # 同时,确保 nginx.conf 中使用了足够的 worker_rlimit_nofile worker_rlimit_nofile 65536;优化网络栈
- 调整
net.core.somaxconn: 定义等待 Nginx 接受的最大连接队列长度。如果遇到accept()队列溢出的错误,需要增加这个值。并在 Nginx 的sysctl -w net.core.somaxconn=65535listen指令中显式指定backlog参数:listen 80 backlog=65535; - 启用 TCP Fast Open: 减少 TCP 三次握手的延迟。
sysctl -w net.ipv4.tcp_fastopen=3 - 增大临时端口范围: 当 Nginx 作为反向代理时,它需要大量本地端口来连接上游服务器。
sysctl -w net.ipv4.ip_local_port_range="1024 65535" - 减少 TCP TIME_WAIT 状态: 对于高并发短连接场景,大量连接处于 TIME_WAIT 状态会耗尽端口资源。
# 启用 TIME_WAIT 复用 sysctl -w net.ipv4.tcp_tw_reuse=1 # 快速回收 TIME_WAIT 连接 sysctl -w net.ipv4.tcp_tw_recycle=0 # 注意:在 NAT 环境下建议为 0,否则可能有问题 # 增大 FIN_WAIT_2 状态的超时时间 sysctl -w net.ipv4.tcp_fin_timeout=30
- 调整
使用高性能磁盘 对于静态资源服务,使用 SSD 硬盘可以极大提升 IO 性能。
二、Nginx 配置优化
这是优化的核心,直接决定 Nginx 的行为。
工作进程与连接数
worker_processes auto;: 设置为auto,让 Nginx 自动根据 CPU 核心数设置工作进程数,通常等于 CPU 核心数。worker_connections: 每个工作进程可以处理的最大连接数。它与worker_rlimit_nofile共同决定了 Nginx 的总并发能力。events { worker_connections 10240; # 例如,设置为 10240 use epoll; # 在 Linux 上使用高性能的 epoll 事件模型 }
高效静态资源服务
- 启用
sendfile: 绕过用户空间,直接在内核中完成文件数据传输,非常高效。sendfile on; - 启用
tcp_nopush: 与sendfile on一起使用,确保数据包被填满后再发送,提高网络效率。tcp_nopush on; - 启用
tcp_nodelay: 针对 keepalive 连接,强制立即发送数据,减少延迟。通常与tcp_nopush一起使用。tcp_nodelay on;
- 启用
连接与请求超时 合理的超时设置可以释放闲置资源,避免连接被长期占用。
# 客户端连接保持超时时间 keepalive_timeout 30s; # 与上游服务器的保持连接超时时间 proxy_connect_timeout 5s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 客户端请求头读取超时 client_header_timeout 15s; # 客户端请求体读取超时 client_body_timeout 15s;缓冲与缓存
- 缓冲区优化: 为客户端请求头和请求体设置合适的缓冲区大小,避免 Nginx 写入临时文件,降低 IO。
client_header_buffer_size 1k; large_client_header_buffers 4 4k; client_body_buffer_size 128k; - 代理缓冲区: 当 Nginx 作为反向代理时,控制从上游服务器接收数据的缓冲区。
proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; - 启用缓存:
- 静态资源缓存: 使用
expires或add_header指令为静态资源设置长时间的浏览器缓存。location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control "public, immutable"; } - 反向代理缓存: 使用
proxy_cache模块缓存上游服务器的动态内容,极大减轻后端压力。proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m; location / { proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; }
- 静态资源缓存: 使用
- 缓冲区优化: 为客户端请求头和请求体设置合适的缓冲区大小,避免 Nginx 写入临时文件,降低 IO。
日志优化
- 禁用访问日志: 对于极高并发且不关心访问日志的场景,可以关闭
access_log。 - 缓冲写入日志: 使用
buffer参数让 Nginx 先将日志写入内存缓冲区,满后再刷入磁盘。access_log /var/log/nginx/access.log main buffer=64k flush=1m; - 记录关键信息: 精简日志格式,只记录必要字段。
- 禁用访问日志: 对于极高并发且不关心访问日志的场景,可以关闭
Gzip 压缩 对文本类型的响应进行压缩,减少网络传输量。
gzip on; gzip_vary on; gzip_min_length 1024; # 小于此值不压缩 gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;上游连接保持 当代理到后端服务时,使用
keepalive保持一定数量的空闲连接,避免频繁建立和断开 TCP 连接的开销。upstream backend_servers { server 10.0.1.100:8080; keepalive 32; # 保持的空闲连接数 } location / { proxy_pass http://backend_servers; proxy_http_version 1.1; proxy_set_header Connection ""; }
三、架构与部署优化
负载均衡 使用 Nginx 的
upstream模块将流量分发到多个后端服务器,实现水平扩展和高可用。upstream app_cluster { least_conn; # 使用最少连接算法 server 10.0.1.101:8080; server 10.0.1.102:8080; server 10.0.1.103:8080; }动静分离 将静态资源(图片、CSS、JS)的请求与动态请求分开。可以让 Nginx 直接处理静态资源,而动态请求则代理给后端应用服务器(如 Tomcat, Node.js 等)。
启用 HTTP/2 HTTP/2 提供了多路复用、头部压缩等特性,能显著提升页面加载速度。
listen 443 ssl http2;使用第三方模块 根据需求编译第三方模块,如:
- OpenResty: 基于 Nginx 和 LuaJIT,提供了强大的可编程能力。
- ngx_brotli: 使用 Brotli 压缩算法,通常比 Gzip 压缩率更高。
四、监控与调试
优化不是一次性的,需要持续监控。
启用状态模块 使用
stub_status_module来查看 Nginx 的基本状态信息。location /nginx_status { stub_status; allow 127.0.0.1; # 只允许本机访问 deny all; }访问后可以看到活跃连接数、请求总数等信息。
分析日志 使用工具如
goaccess、awstats分析访问日志,了解流量模式和瓶颈。性能剖析 在极端情况下,可以使用
debug日志或系统工具(如perf,strace)进行深度性能剖析。
总结与建议
- 循序渐进: 不要一次性修改所有参数。一次只修改一两项,然后进行压测(如使用
wrk,ab,jmeter),观察效果。 - 监控先行: 在优化前、中、后都要有可靠的监控数据作为依据。
- 理解业务: 优化的策略很大程度上取决于业务类型。是高并发连接?是大文件下载?还是大量的短动态请求?
- 内核参数谨慎调整: 生产环境调整内核参数前,务必在测试环境充分验证。
通过以上这些方式的组合运用,你可以显著提升 Nginx 的性能和稳定性,使其能够轻松应对百万级别的并发连接。
Traefik VS Nginx
好的,这是一个非常经典的问题。Traefik 和 Nginx Ingress 都是 Kubernetes 生态中顶级的 Ingress Controller,但它们的设计哲学、使用体验和侧重点有显著不同。
简单来说:
- Traefik 更像一个为云原生和微服务而生的动态、自动化的 API 网关。
- Nginx Ingress 更像一个基于久经考验的 Nginx 的、高度可配置的强大、稳定的反向代理/负载均衡器。
下面我们详细对比一下 Traefik 相对于 Nginx Ingress 的主要优点。
Traefik 的核心优点
1. 极致的动态配置与自动化
这是 Traefik 最核心的卖点。
- 工作原理:Traefik 会主动监听 Kubernetes API Server,实时感知 Service、Ingress Route、Secret 等资源的变化。一旦你创建或修改了一个 Ingress 资源,Traefik 几乎在秒级内自动更新其路由配置,无需任何重启或重载操作。
- Nginx Ingress 的对比:Nginx Ingress 通常需要一个名为
nginx-ingress-controller的组件来监控变化,然后生成一个新的nginx.conf配置文件,最后通过向 Nginx 进程发送reload信号来加载新配置。虽然这个过程也很快,但它本质上是一个 “生成-重载” 模型,在超大流量或配置复杂时,重载可能带来微小的性能抖动或延迟。
结论:在追求完全自动化和零重载的云原生环境中,Traefik 的动态模型更具吸引力。
2. 简化的配置模型与 “IngressRoute” CRD
Traefik 完美支持标准的 Kubernetes Ingress 资源,但它更推荐使用自己定义的 Custom Resource Definition (CRD),叫做 IngressRoute。
- 为什么更好:标准的 Ingress 资源功能相对有限,很多高级特性(如重试、限流、断路器、请求镜像等)需要通过繁琐的
annotations来实现,可读性和可维护性差。 - Traefik 的
IngressRoute:它提供了一种声明式的、结构化的 YAML/JSON 配置方式。所有配置(包括 TLS、中间件、路由规则)都以清晰的结构定义在同一个 CRD 中,更符合 Kubernetes 的原生哲学,也更容易进行版本控制和代码审查。
示例对比: 使用 Nginx Ingress 的注解来实现路径重写:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /使用 Traefik 的 IngressRoute 和中间件:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-ingressroute
spec:
routes:
- match: PathPrefix(`/api`)
kind: Rule
services:
- name: my-service
port: 80
middlewares:
- name: strip-prefix # 使用一个独立的、可复用的中间件资源
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: strip-prefix
spec:
stripPrefix:
prefixes:
- /api可以看到,Traefik 的配置更加模块化和清晰。
3. 内置的、功能丰富的 Dashboard
Traefik 自带一个非常直观的 Web UI 控制台。只需简单启用,你就可以在浏览器中实时查看所有的路由器(Routers)、服务(Services)和中间件(Middlewares),以及它们的健康状况和配置关系。
- 这对于开发和调试来说是巨大的福音。你可以一目了然地看到流量是如何被路由的,而无需去解析复杂的配置文件或命令行输出。
- Nginx Ingress 官方不提供图形化 Dashboard。虽然可以通过第三方工具(如 Prometheus + Grafana)来监控,或者使用
kubectl命令来查询状态,但远不如 Traefik 的原生 Dashboard 直观方便。
4. 原生支持多种后端提供者
Traefik 的设计是多提供者的。除了 Kubernetes,它还可以同时从 Docker、Consul、Etcd、Rancher 或者一个简单的静态文件中读取配置。 如果你的技术栈是混合的(例如,部分服务在 K8s,部分服务使用 Docker Compose),Traefik 可以作为一个统一的入口点,简化你的架构。
Nginx Ingress 虽然也可以通过其他方式扩展,但其核心是为 Kubernetes 设计的。
5. 中间件模式的强大与灵活
Traefik 的 “中间件” 概念非常强大。它允许你将各种功能(如认证、限流、头信息修改、重定向、断路器等)定义为独立的、可复用的组件。然后,你可以在任何路由规则上通过引用的方式组合使用这些中间件。
这种模式极大地增强了配置的复用性和灵活性,是构建复杂流量策略的理想选择。
Nginx Ingress 的优势领域(作为平衡参考)
为了做出全面选择,了解 Nginx Ingress 的优势也很重要:
- 极致的性能与稳定性:基于世界上最成熟的 Web 服务器 Nginx,在处理超高并发静态内容和长连接方面,经过了几十年的实战考验,性能和稳定性极高。
- 功能极其丰富:Nginx 本身的功能集非常庞大,加上 Nginx Ingress Controller 提供了大量的注解来暴露这些功能,其能力上限在某些方面可能高于 Traefik。
- 庞大的社区与生态:Nginx 的用户基数巨大,你遇到的任何问题几乎都能在网上找到解决方案或经验分享。
- 精细化控制:对于深度 Nginx 专家,可以通过
ConfigMap注入自定义的 Nginx 配置片段,实现几乎任何你想要的功能,可控性极强。 - Apache 许可:Nginx 是 Apache 2.0 许可证,而 Traefik v2 之后使用的是限制更多的 Source Available 许可证(虽然对大多数用户免费,但会引起一些大公司的合规顾虑)。Nginx Ingress 完全没有这个问题。
总结与选型建议
| 特性 | Traefik | Nginx Ingress |
|---|---|---|
| 配置模型 | 动态、自动化,无需重载 | “生成-重载”模型 |
| 配置语法 | 声明式 CRD,结构清晰 | 主要依赖 Annotations,较繁琐 |
| Dashboard | 内置,功能强大,开箱即用 | 无官方 UI,需第三方集成 |
| 设计哲学 | 云原生优先,微服务友好 | 功能与性能优先,稳健可靠 |
| 学习曲线 | 较低,易于上手和运维 | 中等,需要了解 Nginx 概念 |
| 性能 | 优秀,足以满足绝大多数场景 | 极致,尤其在静态内容和大并发场景 |
| 可扩展性 | 通过中间件,模块化程度高 | 通过 Lua 脚本或自定义模板,功能上限高 |
| 许可证 | Source Available(可能有限制) | Apache 2.0(完全开源) |
如何选择?
选择 Traefik,如果:
- 你追求极致的云原生体验,希望配置简单、自动化。
- 你的团队更青睐 Kubernetes 原生的声明式配置方式。
- 你非常看重内置的 Dashboard 用于日常运维和调试。
- 你的应用架构是动态的,服务频繁发布和变更。
- 你的场景不需要压榨到极致的性能,更看重开发效率和运维简便性。
选择 Nginx Ingress,如果:
- 你对性能和稳定性有极致要求(例如,超大规模网关、CDN边缘节点)。
- 你需要使用非常复杂或小众的 Nginx 功能,需要精细化的控制。
- 你的团队已经对 Nginx 非常熟悉,有深厚的知识积累。
- 你对开源许可证有严格要求,必须使用 Apache 2.0 等宽松许可证。
- 你的环境相对稳定,不需要频繁更新路由配置。
总而言之,Traefik 胜在“体验”和“自动化”,是现代微服务和云原生环境的理想伴侣。而 Nginx Ingress 胜在“性能”和“功能深度”,是一个经过千锤百炼的、可靠的强大引擎。