找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4062

积分

0

好友

562

主题
发表于 4 小时前 | 查看: 2| 回复: 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配置与性能优化常见问题排查指南
您需要登录后才可以回帖 登录 | 立即注册

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

GMT+8, 2026-3-10 08:37 , Processed in 0.544615 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

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