1. 为什么需要 Ingress 来统一管理微服务入口
在 Kubernetes 集群中部署多个微服务时,最常见的做法是为每个服务创建一个 LoadBalancer 类型的 Service。这种做法看似简单直接,但实际上会带来一系列问题:
1.1 成本问题
以 AWS 为例,每个 LoadBalancer 都会产生以下费用:
- 每小时约 0.025 美元的基础费用(约 18 美元/月)
- 数据传输费用(约 0.01 美元/GB)
- 额外的 LCU(Load Balancer Capacity Units)费用
假设你有 10 个微服务,仅 LoadBalancer 的基础费用就高达 180 美元/月。这还不包括可能的数据传输和处理费用。
1.2 运维复杂度
每个 LoadBalancer 都会分配一个独立的公网 IP 地址,这意味着:
- 需要为每个服务单独配置 DNS 记录
- 每个服务需要单独配置 TLS 证书
- 监控和日志收集需要针对每个 LoadBalancer 单独设置
- 安全策略(如防火墙规则)需要为每个 IP 单独配置
1.3 功能限制
LoadBalancer 本身功能有限:
- 不支持基于路径的路由
- 不支持基于主机的路由
- 不支持高级流量管理(如 A/B 测试、金丝雀发布)
- 需要手动配置和维护 TLS 证书
2. Ingress 的核心概念与工作原理
2.1 Ingress 基本架构
Ingress 在 Kubernetes 中的实现包含两个主要组件:
- Ingress 资源:定义路由规则的 Kubernetes API 对象
- Ingress Controller:实际执行路由规则的组件
code复制外部请求 → Ingress Controller → 根据 Ingress 规则 → 路由到对应 Service → Pod
2.2 Ingress 资源详解
一个典型的 Ingress 资源 YAML 包含以下关键部分:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "foo.example.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
tls:
- hosts:
- "*.example.com"
secretName: wildcard-cert
2.3 Ingress Controller 工作流程
- 监控 Kubernetes API 以获取 Ingress 资源变更
- 根据 Ingress 规则生成配置(如 Nginx 配置)
- 应用新配置并重载服务
- 处理传入请求并根据规则路由到对应服务
3. 主流 Ingress Controller 深度对比
3.1 Nginx Ingress Controller
优点:
- Kubernetes 官方维护,稳定性高
- 功能全面,支持大部分 Ingress 功能
- 社区活跃,文档丰富
- 支持自定义注解扩展功能
缺点:
- 配置变更需要重载 Nginx,可能造成短暂中断
- 高级功能需要企业版(Nginx Plus)
适用场景:
- 生产环境首选
- 需要稳定性和丰富功能的场景
3.2 Traefik
优点:
- 自动服务发现,配置简单
- 内置 Dashboard
- 原生支持 Let's Encrypt 自动证书管理
- 热加载配置,无需重启
缺点:
- 社区版功能有限
- 大规模部署时性能可能不如 Nginx
适用场景:
- 开发环境
- 需要快速上手的项目
- 需要自动证书管理的场景
3.3 Istio Ingress Gateway
优点:
- 与服务网格深度集成
- 支持高级流量管理(金丝雀发布、流量镜像等)
- 强大的可观测性
缺点:
- 学习曲线陡峭
- 资源消耗较大
- 需要整个服务网格生态
适用场景:
- 已使用 Istio 服务网格的环境
- 需要高级流量管理功能的场景
4. 生产级 Ingress 部署实践
4.1 部署 Nginx Ingress Controller
使用 Helm 部署(推荐):
bash复制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.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
--set controller.admissionWebhooks.enabled=false
关键配置说明:
replicaCount=2:确保高可用admissionWebhooks.enabled=false:简化部署,生产环境建议开启- 可根据需要配置资源限制和 HPA
4.2 配置 Ingress 资源
多域名路由示例:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-domain-ingress
spec:
rules:
- host: "app.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: frontend-service
port:
number: 80
- host: "api.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: backend-service
port:
number: 8080
路径重写示例:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- pathType: Prefix
path: "/api(/|$)(.*)"
backend:
service:
name: api-service
port:
number: 8080
4.3 TLS 配置最佳实践
使用 cert-manager 自动管理证书:
- 安装 cert-manager:
bash复制helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.8.0 \
--set installCRDs=true
- 创建 ClusterIssuer:
yaml复制apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: your-email@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
- 在 Ingress 中使用自动证书:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- "app.example.com"
secretName: app-tls
rules:
- host: "app.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: app-service
port:
number: 80
5. 高级 Ingress 配置技巧
5.1 流量分割(金丝雀发布)
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules:
- host: "app.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: app-service-canary
port:
number: 80
5.2 基于 Header 的路由
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: header-routing-ingress
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: "app.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: app-service-canary
port:
number: 80
5.3 速率限制
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rate-limit-ingress
annotations:
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-burst: "200"
spec:
rules:
- host: "api.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: api-service
port:
number: 8080
6. 性能优化与监控
6.1 Ingress Controller 调优
资源限制:
yaml复制resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "100m"
memory: "128Mi"
内核参数调优:
bash复制sysctl -w net.core.somaxconn=32768
sysctl -w net.ipv4.tcp_max_syn_backlog=8096
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
6.2 监控方案
Prometheus 监控指标:
nginx_ingress_controller_requests:请求总数nginx_ingress_controller_request_duration_seconds:请求延迟nginx_ingress_controller_connections:当前连接数
Grafana 仪表板:
使用官方提供的 Nginx Ingress Controller 仪表板(ID: 9614)
6.3 日志收集
配置访问日志格式:
yaml复制controller:
config:
log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status'
7. 常见问题排查
7.1 Ingress 不生效排查步骤
-
检查 Ingress Controller 是否运行:
bash复制
kubectl get pods -n ingress-nginx -
检查 Ingress 资源是否被正确识别:
bash复制
kubectl describe ingress <ingress-name> -
检查 Controller 日志:
bash复制
kubectl logs -n ingress-nginx <controller-pod-name> -
检查生成的 Nginx 配置:
bash复制kubectl exec -n ingress-nginx <controller-pod-name> -- cat /etc/nginx/nginx.conf
7.2 TLS 证书问题
证书不匹配:
- 确保 Ingress 中指定的 secretName 与 TLS secret 名称一致
- 检查证书是否包含正确的域名
证书过期:
- 使用 cert-manager 自动续期
- 手动更新 secret:
bash复制
kubectl create secret tls my-tls --cert=path/to/cert.pem --key=path/to/key.pem --dry-run=client -o yaml | kubectl apply -f -
7.3 性能问题
高延迟:
- 检查 upstream 服务响应时间
- 调整 keepalive 参数:
yaml复制controller: config: upstream-keepalive-connections: "100" upstream-keepalive-requests: "10000" upstream-keepalive-timeout: "60s"
高 CPU 使用率:
- 增加 Controller 副本数
- 优化正则表达式路由规则
- 启用 gzip 压缩:
yaml复制controller: config: gzip: "on" gzip-types: "application/javascript application/json application/xml text/css text/html text/plain text/xml"
8. 安全最佳实践
8.1 网络策略
限制 Ingress Controller 的网络访问:
yaml复制apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ingress-allow-only-http-https
namespace: ingress-nginx
spec:
podSelector:
matchLabels:
app.kubernetes.io/component: controller
policyTypes:
- Ingress
ingress:
- ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
8.2 认证与授权
Basic Auth:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-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'
spec:
rules:
- host: "secure.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: secure-service
port:
number: 8080
OAuth 代理:
yaml复制annotations:
nginx.ingress.kubernetes.io/auth-url: "https://oauth.example.com/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://oauth.example.com/login?return=https://$host$request_uri"
8.3 WAF 集成
ModSecurity:
yaml复制controller:
config:
enable-modsecurity: "true"
enable-owasp-core-rules: "true"
modsecurity-snippet: |
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsec_audit.log
9. 多集群 Ingress 管理
9.1 使用 ExternalDNS 实现全局 DNS
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: global-ingress
annotations:
external-dns.alpha.kubernetes.io/hostname: app.example.com
spec:
rules:
- host: "app.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: global-service
port:
number: 80
9.2 多集群流量分发
使用 Global Load Balancer:
- AWS Global Accelerator
- Google Cloud Global Load Balancing
- Azure Traffic Manager
配置示例(AWS):
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-cluster-ingress
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
rules:
- host: "global.example.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: global-service
port:
number: 80
10. 未来演进方向
10.1 Gateway API
Kubernetes 正在发展的新一代 Ingress 标准:
yaml复制apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-class
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: example-route
spec:
parentRefs:
- name: example-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /example
backendRefs:
- name: example-service
port: 80
10.2 服务网格集成
将 Ingress 与服务网格(如 Istio)结合使用:
yaml复制apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-service
spec:
hosts:
- "app.example.com"
gateways:
- istio-gateway
http:
- route:
- destination:
host: app-service
port:
number: 8080
在实际生产环境中,我们通常会根据业务规模和技术栈选择合适的 Ingress 方案。对于大多数 Kubernetes 部署,Nginx Ingress Controller 提供了最佳的功能平衡和稳定性。随着业务增长,可以考虑引入更高级的流量管理功能或与服务网格集成。