Ingress 是 Kubernetes 集群中管理外部访问的核心组件。本文深入讲解 Ingress 的工作原理、配置方法、控制器选型以及生产环境的最佳实践。
目录
- 一、Ingress 基础概念
- 二、Ingress 核心资源详解
- 三、主流 Ingress 控制器
- 四、Nginx Ingress 深度实践
- 五、TLS/SSL 配置
- 六、高级路由与流量管理
- 七、安全与认证
- 八、性能优化
- 九、监控与故障排查
- 十、生产环境最佳实践
一、Ingress 基础概念
1.1 什么是 Ingress
Ingress 是 Kubernetes 的 API 对象,用于管理外部用户如何访问集群内部的服务。它提供了七层(HTTP/HTTPS)负载均衡能力。
外部用户
│
▼
┌─────────┐
│ Ingress │
│Controller│
└────┬────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Service │ │ Service │ │ Service │
│ A │ │ B │ │ C │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ Pod │ │ Pod │ │ Pod │
└─────────┘ └─────────┘ └─────────┘
1.2 Ingress 与 Service、LoadBalancer 对比
| 特性 |
ClusterIP |
NodePort |
LoadBalancer |
Ingress |
| 工作层级 |
L4 |
L4 |
L4 |
L7 |
| 暴露方式 |
集群内 IP |
节点端口 |
云厂商 LB |
域名/路径 |
| 路由能力 |
无 |
无 |
无 |
支持域名/路径路由 |
| SSL 终止 |
不支持 |
不支持 |
部分支持 |
支持 |
| 成本 |
低 |
低 |
高(云厂商收费) |
低 |
| 适用场景 |
内部服务 |
测试环境 |
生产环境单服务 |
生产环境多服务 |
1.3 Ingress 工作原理
1. 用户请求到达 Ingress Controller
│
▼
2. Ingress Controller 监听 API Server
获取 Ingress 资源定义
│
▼
3. 根据 Ingress 规则匹配请求
(域名、路径、协议等)
│
▼
4. 转发请求到对应的后端 Service
│
▼
5. Service 通过 kube-proxy 转发到 Pod
核心组件
- Ingress 资源:定义路由规则的 YAML 配置
- Ingress Controller:实际处理流量的 Pod(如 Nginx、Traefik)
- Ingress Class:定义 Ingress 控制器的类型
二、Ingress 核心资源详解
2.1 Ingress 资源结构
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: default
labels:
app: web
annotations:
# 控制器特定的配置
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
# Ingress 控制器类
ingressClassName: nginx
# TLS 配置
tls:
- hosts:
- example.com
secretName: example-tls
# 路由规则
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
2.2 pathType 详解
# 1. Exact:精确匹配
# 只匹配 /api,不匹配 /api/users
- path: /api
pathType: Exact
backend:
service:
name: api-service
port:
number: 8080
# 2. Prefix:前缀匹配
# 匹配 /api、/api/users、/api/v1/health
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# 3. ImplementationSpecific:实现特定
# 匹配行为由 Ingress Controller 决定
- path: /.*
pathType: ImplementationSpecific
backend:
service:
name: dynamic-service
port:
number: 80
2.3 多域名配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-domain-ingress
spec:
ingressClassName: nginx
rules:
# 主域名
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
# API 子域名
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# 管理后台子域名
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 8000
# 默认后端(未匹配任何域名时)
defaultBackend:
service:
name: default-service
port:
number: 80
2.4 路径重写
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
# 路径重写
nginx.ingress.kubernetes.io/rewrite-target: /$2
# 使用正则表达式
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
# /api/v1/users → /users
- path: /api/v1/(.*)
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# /api/v2/users → /v2/users
- path: /api(/v2)/(.*)
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080
2.5 后端服务配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-ingress
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
# 使用 Service 名称和端口号
- path: /service-by-name
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
# 使用 Service 名称和端口名称
- path: /service-by-port-name
pathType: Prefix
backend:
service:
name: my-service
port:
name: http
# 使用外部服务(需要配合 ExternalName Service)
- path: /external
pathType: Prefix
backend:
service:
name: external-service
port:
number: 443
三、主流 Ingress 控制器
3.1 控制器对比
| 控制器 |
语言 |
性能 |
功能丰富度 |
社区活跃度 |
适用场景 |
| Nginx Ingress |
Go |
高 |
高 |
非常高 |
通用场景 |
| Traefik |
Go |
高 |
高 |
高 |
微服务、动态配置 |
| HAProxy Ingress |
Go |
非常高 |
中 |
中 |
高性能场景 |
| Kong Ingress |
Lua |
高 |
非常高 |
高 |
API 网关 |
| Envoy Gateway |
Go |
非常高 |
高 |
高 |
服务网格 |
| ALB Ingress |
Go |
高 |
中 |
中 |
AWS 环境 |
3.2 Nginx Ingress Controller 安装
方式一:Helm 安装(推荐)
# 添加 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.service.type=LoadBalancer \
--set controller.metrics.enabled=true \
--set controller.serviceMonitor.enabled=true
# 验证安装
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
方式二:YAML 部署
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
方式三:Kind 本地测试
# 创建 Kind 集群
kind create cluster --name ingress-test
# 安装 Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# 端口转发(本地访问)
kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80
3.3 Traefik Ingress 安装
# 添加 Helm 仓库
helm repo add traefik https://traefik.github.io/charts
helm repo update
# 安装
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set providers.kubernetesIngress.enabled=true \
--set ports.web.port=80 \
--set ports.websecure.port=443
# Dashboard 访问
kubectl port-forward -n traefik $(kubectl get pods -n traefik -l app.kubernetes.io/name=traefik -o jsonpath='{.items[0].metadata.name}') 9000:9000
3.4 IngressClass 配置
# 定义 IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx-external
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
---
# 定义另一个 IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx-internal
spec:
controller: k8s.io/ingress-nginx
parameters:
apiGroup: k8s.io
kind: ConfigMap
name: nginx-internal-config
namespace: ingress-nginx
---
# 使用 IngressClass
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-ingress
spec:
ingressClassName: nginx-external
rules:
- host: external.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: internal-ingress
spec:
ingressClassName: nginx-internal
rules:
- host: internal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: internal-service
port:
number: 80
四、Nginx Ingress 深度实践
4.1 常用 Annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
# === 路由相关 ===
# 路径重写
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/app-root: /home
# === 重定向 ===
# SSL 重定向
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# 永久重定向
nginx.ingress.kubernetes.io/permanent-redirect: https://new.example.com$request_uri
# 临时重定向
nginx.ingress.kubernetes.io/temporal-redirect: https://temp.example.com
# === 代理配置 ===
# 超时设置
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
# 缓冲配置
nginx.ingress.kubernetes.io/proxy-buffering: "on"
nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"
# 请求体大小
nginx.ingress.kubernetes.io/client-max-body-size: "50m"
# === 限流 ===
# 请求限流
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-rpm: "1000"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "3"
# 连接限流
nginx.ingress.kubernetes.io/limit-connections: "10"
# === 缓存 ===
# 代理缓存
nginx.ingress.kubernetes.io/proxy-cache: "on"
nginx.ingress.kubernetes.io/proxy-cache-key: "$scheme$request_method$host$request_uri"
nginx.ingress.kubernetes.io/proxy-cache-valid: "200 302 10m"
# === 安全 ===
# CORS 配置
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
# IP 白名单
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,192.168.1.0/24"
# 认证
nginx.ingress.kubernetes.io/auth-type: "basic"
nginx.ingress.kubernetes.io/auth-secret: "basic-auth"
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
# === 监控 ===
# 自定义监控
nginx.ingress.kubernetes.io/enable-metrics: "true"
nginx.ingress.kubernetes.io/server-snippet: |
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
# === 其他 ===
# 自定义响应头
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header X-Custom-Header "value";
add_header X-Request-ID $request_id;
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
4.2 完整示例:微服务路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls-secret
rules:
- host: api.example.com
http:
paths:
# 用户服务
- path: /api/v1/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
# 订单服务
- path: /api/v1/orders(/|$)(.*)
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
# 支付服务
- path: /api/v1/payments(/|$)(.*)
pathType: Prefix
backend:
service:
name: payment-service
port:
number: 8080
# 商品服务
- path: /api/v1/products(/|$)(.*)
pathType: Prefix
backend:
service:
name: product-service
port:
number: 8080
# API 文档
- path: /docs(/|$)(.*)
pathType: Prefix
backend:
service:
name: swagger-ui
port:
number: 80
# 默认后端
- path: /
pathType: Prefix
backend:
service:
name: api-gateway
port:
number: 80
4.3 Canary 灰度发布
# 主版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "false"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
---
# 金丝雀版本 Ingress(10% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
# 启用金丝雀
nginx.ingress.kubernetes.io/canary: "true"
# 基于权重的流量分配
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:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80
灰度发布策略对比
| 策略 |
Annotation |
说明 |
适用场景 |
| 权重 |
canary-weight |
按百分比分配流量 |
逐步放量 |
| 请求头 |
canary-by-header |
根据 Header 值路由 |
内部测试 |
| Cookie |
canary-by-cookie |
根据 Cookie 路由 |
用户分组测试 |
五、TLS/SSL 配置
5.1 手动配置 TLS
# 1. 创建 TLS Secret
kubectl create secret tls example-tls \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
--namespace=default
# 2. 在 Ingress 中引用
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
5.2 使用 cert-manager 自动管理证书
安装 cert-manager
# 添加 Helm 仓库
helm repo add jetstack https://charts.jetstack.io
helm repo update
# 安装
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set installCRDs=true
配置 ClusterIssuer
# Let's Encrypt Production Issuer
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-key
solvers:
# HTTP-01 挑战
- http01:
ingress:
class: nginx
podTemplate:
spec:
nodeSelector:
"kubernetes.io/os": linux
# DNS-01 挑战(支持泛域名)
- dns01:
cloudflare:
email: admin@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
---
# Let's Encrypt Staging Issuer(测试用)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
class: nginx
在 Ingress 中使用自动证书
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-cert
namespace: default
spec:
secretName: example-com-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- example.com
- www.example.com
- api.example.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# HSTS
nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
nginx.ingress.kubernetes.io/hsts-preload: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-com-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
5.3 多证书配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-cert-ingress
spec:
ingressClassName: nginx
tls:
# 主域名证书
- hosts:
- example.com
- www.example.com
secretName: example-com-tls
# API 子域名证书
- hosts:
- api.example.com
secretName: api-example-com-tls
# 其他子域名证书
- hosts:
- admin.example.com
secretName: admin-example-com-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 8000
六、高级路由与流量管理
6.1 基于请求头的路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: header-based-routing
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
# 基于请求头路由到不同后端
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_x_api_version = "v2") {
set $service_name "api-v2";
}
if ($http_x_api_version = "v1") {
set $service_name "api-v1";
}
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: api-router
port:
number: 80
使用 IngressRoute(Traefik)
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: header-routing
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && Headers(`X-API-Version`, `v2`)
kind: Rule
services:
- name: api-v2
port: 8080
- match: Host(`api.example.com`) && Headers(`X-API-Version`, `v1`)
kind: Rule
services:
- name: api-v1
port: 8080
- match: Host(`api.example.com`)
kind: Rule
services:
- name: api-v1
port: 8080
tls:
secretName: api-tls
6.2 基于 Cookie 的路由(用户粘性)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sticky-ingress
annotations:
# 启用会话粘性
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/session-cookie-hash: "sha1"
# 可选:设置 Cookie 路径
nginx.ingress.kubernetes.io/session-cookie-path: "/"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: stateful-app
port:
number: 80
6.3 流量镜像(Traffic Mirroring)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mirror-ingress
annotations:
# 启用流量镜像
nginx.ingress.kubernetes.io/mirror-target: "http://mirror-service.default.svc"
# 镜像流量百分比(0-100)
nginx.ingress.kubernetes.io/mirror-target-percentage: "10"
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
6.4 自定义错误页面
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: custom-error-ingress
annotations:
# 自定义错误页面
nginx.ingress.kubernetes.io/custom-http-errors: "404,500,502,503"
nginx.ingress.kubernetes.io/default-backend: error-pages-service
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
---
# 错误页面服务
apiVersion: v1
kind: Service
metadata:
name: error-pages-service
spec:
selector:
app: error-pages
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: error-pages
spec:
replicas: 1
selector:
matchLabels:
app: error-pages
template:
metadata:
labels:
app: error-pages
spec:
containers:
- name: error-pages
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: error-pages
mountPath: /usr/share/nginx/html
volumes:
- name: error-pages
configMap:
name: error-pages-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: error-pages-config
data:
404.html: |
<!DOCTYPE html>
<html>
<head><title>404 - 页面未找到</title></head>
<body>
<h1>404 - 页面未找到</h1>
<p>抱歉,您访问的页面不存在。</p>
</body>
</html>
500.html: |
<!DOCTYPE html>
<html>
<head><title>500 - 服务器错误</title></head>
<body>
<h1>500 - 服务器内部错误</h1>
<p>请稍后再试。</p>
</body>
</html>
七、安全与认证
7.1 Basic Auth 认证
# 1. 创建认证文件
htpasswd -c auth admin
# 输入密码
# 2. 创建 Secret
kubectl create secret generic basic-auth --from-file=auth
# 3. 在 Ingress 中使用
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: basic-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"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- admin.example.com
secretName: admin-tls
rules:
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 8000
7.2 OAuth2 认证
安装 OAuth2 Proxy
helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests
helm install oauth2-proxy oauth2-proxy/oauth2-proxy \
--namespace oauth2-proxy \
--create-namespace \
--set config.clientID="YOUR_CLIENT_ID" \
--set config.clientSecret="YOUR_CLIENT_SECRET" \
--set config.cookieSecret="RANDOM_SECRET" \
--set config.provider="github" # 或 google、azure 等
配置 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: oauth2-ingress
annotations:
# OAuth2 认证
nginx.ingress.kubernetes.io/auth-url: "http://oauth2-proxy.oauth2-proxy.svc.cluster.local:4180/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization,Email,User"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
# OAuth2 回调路径
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy
port:
number: 4180
# 受保护的应用
- path: /
pathType: Prefix
backend:
service:
name: protected-app
port:
number: 80
7.3 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,
172.16.0.0/12,
192.168.0.0/16,
203.0.113.0/24
# 自定义拒绝响应
nginx.ingress.kubernetes.io/denylist-source-range: "0.0.0.0/0"
spec:
ingressClassName: nginx
rules:
- host: internal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: internal-service
port:
number: 80
7.4 Rate Limiting 限流
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-rpm: "1000"
# 突发请求倍数
nginx.ingress.kubernetes.io/limit-burst-multiplier: "3"
# 连接数限制
nginx.ingress.kubernetes.io/limit-connections: "10"
# 限流区域(默认使用 $binary_remote_addr)
nginx.ingress.kubernetes.io/limit-key: "$binary_remote_addr"
# 限流状态码
nginx.ingress.kubernetes.io/limit-connection-status: "429"
nginx.ingress.kubernetes.io/limit-rps-status: "429"
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
7.5 CORS 跨域配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cors-ingress
annotations:
# 启用 CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
# 允许的源
nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com, https://admin.example.com"
# 允许的方法
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, PATCH, OPTIONS"
# 允许的头部
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
# 暴露的头部
nginx.ingress.kubernetes.io/cors-expose-headers: "Content-Length,Content-Range"
# 允许凭证
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
# 预检请求缓存时间
nginx.ingress.kubernetes.io/cors-max-age: "86400"
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
八、性能优化
8.1 连接优化
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx
data:
# 工作进程数
worker-processes: "auto"
# 每个 worker 的连接数
worker-connections: "65535"
# 保持连接超时
keep-alive: "75"
# 保持连接请求数
keep-alive-requests: "10000"
# 启用 HTTP/2
http2: "true"
# 启用 OCSP Stapling
use-ocsp: "true"
# 代理超时
proxy-connect-timeout: "10"
proxy-send-timeout: "60"
proxy-read-timeout: "60"
# 代理缓冲
proxy-buffering: "on"
proxy-buffer-size: "8k"
proxy-buffers: "8 8k"
proxy-busy-buffers-size: "16k"
# 启用 Gzip
enable-gzip: "true"
gzip-level: "5"
gzip-types: "text/plain,text/css,application/json,application/javascript,text/xml,application/xml"
# 日志格式
log-format-escape-json: "true"
log-format-upstream: '{"time":"$time_iso8601","remote_addr":"$remote_addr","request_method":"$request_method","request_uri":"$request_uri","status":$status,"body_bytes_sent":$body_bytes_sent,"request_time":$request_time,"upstream_response_time":"$upstream_response_time","upstream_connect_time":"$upstream_connect_time","host":"$host"}'
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --annotations-prefix=nginx.ingress.kubernetes.io
- --enable-metrics=true
- --watch-ingress-without-class=true
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1000m
memory: 512Mi
8.2 缓存优化
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cache-ingress
annotations:
# 启用代理缓存
nginx.ingress.kubernetes.io/proxy-cache: "on"
# 缓存键
nginx.ingress.kubernetes.io/proxy-cache-key: "$scheme$request_method$host$request_uri"
# 缓存有效期
nginx.ingress.kubernetes.io/proxy-cache-valid: "200 302 10m"
nginx.ingress.kubernetes.io/proxy-cache-valid: "404 1m"
# 缓存路径
nginx.ingress.kubernetes.io/proxy-cache-path: "/tmp/nginx-cache"
# 缓存级别
nginx.ingress.kubernetes.io/proxy-cache-level: "1"
# 缓存大小
nginx.ingress.kubernetes.io/proxy-cache-size: "100m"
# 跳过缓存条件
nginx.ingress.kubernetes.io/proxy-cache-bypass: "$http_cache_control"
# 不缓存的条件
nginx.ingress.kubernetes.io/proxy-no-cache: "$http_authorization"
spec:
ingressClassName: nginx
rules:
- host: static.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: static-service
port:
number: 80
8.3 水平扩展
# 多副本部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 3 # 多副本
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
spec:
# 反亲和性,分散到不同节点
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- ingress-nginx
topologyKey: "kubernetes.io/hostname"
# 节点选择
nodeSelector:
kubernetes.io/os: linux
ingress-ready: "true"
# 容忍度
tolerations:
- key: node-role.kubernetes.io/ingress
operator: Exists
effect: NoSchedule
九、监控与故障排查
9.1 启用监控指标
# Helm 安装时启用 metrics
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.metrics.enabled=true \
--set controller.serviceMonitor.enabled=true \
--set controller.serviceMonitor.namespace=monitoring
关键指标
# 请求总数
sum(nginx_ingress_controller_requests)
# 请求速率
rate(nginx_ingress_controller_requests[5m])
# 响应状态码分布
sum by (status) (nginx_ingress_controller_requests)
# 请求延迟
histogram_quantile(0.95, rate(nginx_ingress_controller_request_duration_seconds_bucket[5m]))
# 活跃连接
nginx_ingress_controller_nginx_process_connections{state="active"}
# 配置重载次数
nginx_ingress_controller_config_last_reload_successful
9.2 Grafana Dashboard
导入官方 Dashboard
- Dashboard ID:
9614(Nginx Ingress Controller)
- Dashboard ID:
11841(Nginx Ingress Performance)
9.3 故障排查命令
# 1. 查看 Ingress 资源
kubectl get ingress -A
kubectl describe ingress <ingress-name> -n <namespace>
# 2. 查看 IngressClass
kubectl get ingressclass
kubectl describe ingressclass <class-name>
# 3. 查看 Controller Pod
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
# 4. 查看 Service 和 Endpoints
kubectl get svc -n ingress-nginx
kubectl get endpoints -n ingress-nginx
# 5. 测试路由
curl -v -H "Host: example.com" http://<ingress-ip>/path
# 6. 检查证书
kubectl get secret <tls-secret-name> -o yaml
kubectl get certificate -A # cert-manager
# 7. 查看 Controller 配置
kubectl exec -n ingress-nginx <controller-pod> -- cat /etc/nginx/nginx.conf
# 8. 进入 Controller Pod 调试
kubectl exec -n ingress-nginx <controller-pod> -- nginx -t
kubectl exec -n ingress-nginx <controller-pod> -- nginx -s reload
# 9. 查看事件
kubectl get events -n ingress-nginx --sort-by='.lastTimestamp'
# 10. 网络连通性测试
kubectl exec -n ingress-nginx <controller-pod> -- curl -v http://<service-name>.<namespace>.svc.cluster.local
9.4 常见问题排查
问题 1:Ingress 无法访问
# 检查 Ingress Controller 是否运行
kubectl get pods -n ingress-nginx
# 检查 Service 类型
kubectl get svc -n ingress-nginx
# 检查外部 IP
kubectl get svc ingress-nginx-controller -n ingress-nginx
# 检查防火墙/安全组
# 确保 80/443 端口开放
问题 2:502 Bad Gateway
# 检查后端 Service
kubectl get svc <service-name>
kubectl get endpoints <service-name>
# 检查后端 Pod 是否就绪
kubectl get pods -l app=<label>
# 查看 Controller 日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx | grep -i error
问题 3:404 Not Found
# 检查 Ingress 规则
kubectl describe ingress <ingress-name>
# 检查 host 和 path 配置
# 确认请求的 Host 与 Ingress 规则匹配
# 检查 defaultBackend 配置
问题 4:证书问题
# 检查 Secret
kubectl get secret <tls-secret> -o yaml
# 检查 cert-manager
kubectl get certificaterequest -A
kubectl describe certificate <cert-name>
# 查看 cert-manager 日志
kubectl logs -n cert-manager -l app.kubernetes.io/name=cert-manager
十、生产环境最佳实践
10.1 高可用架构
# 生产环境 Ingress Controller 部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 3 # 至少 3 副本
# 滚动更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
spec:
# 反亲和性
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- ingress-nginx
topologyKey: "kubernetes.io/hostname"
# 节点亲和性
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/ingress
operator: Exists
# 容忍度
tolerations:
- key: node-role.kubernetes.io/ingress
operator: Exists
effect: NoSchedule
# 资源限制
containers:
- name: controller
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
# 健康检查
livenessProbe:
httpGet:
path: /healthz
port: 10254
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 10254
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
# 优先级
priorityClassName: system-cluster-critical
# 服务账户
serviceAccountName: ingress-nginx
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 101 # www-data
10.2 完整生产示例
# === 命名空间 ===
apiVersion: v1
kind: Namespace
metadata:
name: production
---
# === TLS Secret(使用 cert-manager 自动管理)===
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: production-cert
namespace: production
spec:
secretName: production-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- app.example.com
- api.example.com
- admin.example.com
renewBefore: 720h # 30 天续期
---
# === 主 Ingress ===
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
namespace: production
annotations:
# SSL
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
nginx.ingress.kubernetes.io/hsts-preload: "true"
# 安全
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "Authorization,Content-Type"
# 限流
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-rpm: "1000"
# 代理配置
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
# 监控
nginx.ingress.kubernetes.io/enable-metrics: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
- api.example.com
- admin.example.com
secretName: production-tls
rules:
# 主应用
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# API
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080
# 管理后台
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 8000
---
# === 监控告警 ===
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: ingress-alerts
namespace: monitoring
spec:
groups:
- name: ingress.rules
rules:
# Ingress Controller 宕机
- alert: IngressControllerDown
expr: up{job="ingress-nginx-controller"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Ingress Controller 宕机"
description: "Ingress Controller {{ $labels.pod }} 已宕机超过 5 分钟"
# 高错误率
- alert: IngressHighErrorRate
expr: |
sum(rate(nginx_ingress_controller_requests{status=~"5.."}[5m]))
/ sum(rate(nginx_ingress_controller_requests[5m])) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "Ingress 错误率过高"
description: "Ingress 5xx 错误率超过 5%"
# 高延迟
- alert: IngressHighLatency
expr: |
histogram_quantile(0.95,
rate(nginx_ingress_controller_request_duration_seconds_bucket[5m])
) > 1
for: 10m
labels:
severity: warning
annotations:
summary: "Ingress 延迟过高"
description: "P95 延迟超过 1 秒"
# 证书即将过期
- alert: TLSCertExpiringSoon
expr: |
certmanager_certificate_expiry_timestamp_seconds - time() < 86400 * 7
for: 1h
labels:
severity: warning
annotations:
summary: "TLS 证书即将过期"
description: "证书 {{ $labels.name }} 将在 7 天内过期"
10.3 检查清单
部署前检查
- Ingress Controller 高可用部署(至少 2 副本)
- 配置资源限制和请求
- 启用健康检查
- 配置 Pod 反亲和性
- 设置优先级类
- 启用监控指标
安全配置
- 强制 HTTPS 重定向
- 配置 HSTS
- 启用 CORS(如需要)
- 配置限流
- 设置请求体大小限制
- 配置 IP 白名单(内部服务)
证书管理
- 使用 cert-manager 自动管理
- 配置证书续期告警
- 测试证书自动续期
监控告警
- 配置 Prometheus 监控
- 导入 Grafana Dashboard
- 设置告警规则
- 配置告警通知
性能优化
- 启用 HTTP/2
- 配置 Gzip 压缩
- 优化代理缓冲
- 配置连接保持
- 启用代理缓存(如需要)
结语
Ingress 作为 Kubernetes 集群的流量入口,承担着路由转发、SSL 终止、安全认证等重要职责。掌握 Ingress 的原理和最佳实践,对于构建稳定、安全、高性能的云原生应用至关重要。
本文从基础概念出发,深入讲解了:
- Ingress 核心资源与配置
- 主流 Ingress 控制器选型
- Nginx Ingress 深度实践
- TLS/SSL 证书管理
- 高级路由与流量管理
- 安全认证与限流
- 性能优化策略
- 监控与故障排查
- 生产环境最佳实践
希望这些内容能帮助你在实际工作中更好地使用 Ingress,构建可靠的 Kubernetes 应用架构。如果你想了解更多云原生和容器化的实践经验,欢迎访问云栈社区与其他开发者交流讨论。
参考资料
- Kubernetes Ingress 官方文档
- Nginx Ingress Controller 文档
- cert-manager 文档
- Traefik 文档
- Ingress Nginx Annotations