找回密码
立即注册
搜索
发回帖 发新帖

6570

积分

0

好友

832

主题
发表于 2026-3-10 04:36:56 | 查看: 365| 回复: 0

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
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



上一篇:威胁狩猎实战:构建团队能力、量化效能与培育安全文化
下一篇:Nginx配置与性能优化常见问题排查指南
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-28 12:26 , Processed in 0.123029 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表