🚪 第10课:Ingress流量管理

📌 课程阶段:存储与调度(5/5)|预计时间:60分钟|难度:⭐⭐⭐☆☆

一、Ingress——K8s的七层网关

Ingress是K8s的HTTP/HTTPS路由规则集合,提供基于域名和路径的外部流量路由。相比NodePort/LoadBalancer,Ingress实现了"一个入口点,多服务路由"。

┌───────────── Ingress流量路径 ──────────────┐
│                                              │
│  Internet用户                                │
│      │                                       │
│  ┌───▼──────────────────┐                    │
│  │   Cloud LB / MetalLB │  ← 外部流量入口    │
│  └───┬──────────────────┘                    │
│      │                                       │
│  ┌───▼──────────────────┐                    │
│  │   Ingress Controller │  ← Nginx/Traefik  │
│  │   (Pod in Cluster)   │    /Istio/Envoy    │
│  └───┬──────────────────┘                    │
│      │  根据Ingress规则路由                   │
│      │                                       │
│  ┌───▼──────────────────────────────────┐    │
│  │          Ingress Rules               │    │
│  │  api.example.com → api-svc:8080      │    │
│  │  web.example.com → web-svc:80        │    │
│  │  app.example.com/api → api-svc:8080  │    │
│  │  app.example.com/*  → web-svc:80     │    │
│  └──────────────────────────────────────┘    │
│      │                    │                   │
│  ┌───▼─────┐     ┌───────▼──────┐            │
│  │ api-svc │     │   web-svc    │            │
│  │ :8080   │     │   :80        │            │
│  └─────────┘     └──────────────┘            │
└──────────────────────────────────────────────┘

二、安装Ingress Controller

2.1 Nginx Ingress Controller

# 方式1: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.publishService.enabled=true

# 方式2:kubectl apply
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

# ✅ 验证通过
kubectl get pods -n ingress-nginx
# NAME                                        READY   STATUS    RESTARTS   AGE
# ingress-nginx-controller-6b8d8f9b4d-xxxxx   1/1     Running   0          30s

kubectl get svc -n ingress-nginx
# NAME                                 TYPE           EXTERNAL-IP
# ingress-nginx-controller             LoadBalancer   1.2.3.4

2.2 本地环境(kind + MetalLB)

# kind集群配置Ingress
cat <

三、Ingress规则详解

3.1 基于域名的路由

# ingress-multi-host.yaml - 基于域名路由到不同服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod  # 自动证书
spec:
  ingressClassName: nginx          # K8s 1.18+使用ingressClassName
  tls:
  - hosts:
    - api.example.com
    - web.example.com
    secretName: example-tls        # TLS证书Secret
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix           # Prefix|Exact|ImplementationSpecific
        backend:
          service:
            name: api-service
            port:
              number: 8080
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

# ✅ 验证通过
kubectl apply -f ingress-multi-host.yaml
kubectl get ingress
# NAME                 CLASS   HOSTS                                ADDRESS       PORTS     AGE
# multi-host-ingress   nginx   api.example.com,web.example.com      192.168.1.10  80,443    30s

3.2 基于路径的路由

# ingress-path-routing.yaml - 同一域名不同路径
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-routing
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /static(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: static-service
            port:
              number: 80
      - path: /()
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

3.3 默认后端

# 没有匹配规则时的默认后端
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: default-backend
spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: default-http-backend
      port:
        number: 80
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-service
            port:
              number: 80

四、Ingress高级配置

4.1 常用Annotations

# Nginx Ingress常用注解
metadata:
  annotations:
    # SSL重定向
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    
    # 代理配置
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"        # 上传大小限制
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    
    # 负载均衡
    nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"  # 会话亲和
    nginx.ingress.kubernetes.io/load-balance: "ewma"         # 负载算法
    
    # 限流
    nginx.ingress.kubernetes.io/limit-connections: "100"
    nginx.ingress.kubernetes.io/limit-rps: "100"             # 每秒请求数
    nginx.ingress.kubernetes.io/limit-burst: "50"
    
    # CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
    
    # 认证
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"

4.2 WebSocket支持

metadata:
  annotations:
    nginx.ingress.kubernetes.io/websocket-services: "ws-service"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"

4.3 金丝雀发布(Canary)

# canary-ingress.yaml - Nginx Ingress金丝雀发布
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    # 基于权重:20%流量到新版本
    nginx.ingress.kubernetes.io/canary-weight: "20"
    # 基于Header:特定用户走新版本
    nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
    nginx.ingress.kubernetes.io/canary-by-header-value: "true"
    # 基于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-service-v2     # 新版本Service
            port:
              number: 80

五、Gateway API(下一代Ingress)

# Gateway API是Ingress的进化版,更丰富的路由能力
# 安装Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

# GatewayClass - 定义基础设施
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx-gateway
spec:
  controllerName: nginx.org/gateway-controller

---
# Gateway - 定义监听器
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
spec:
  gatewayClassName: nginx-gateway
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: "*.example.com"
  - name: https
    port: 443
    protocol: HTTPS
    hostname: "*.example.com"
    tls:
      mode: Terminate
      certificateRefs:
      - name: example-tls

---
# HTTPRoute - 定义路由规则
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
spec:
  parentRefs:
  - name: main-gateway
  hostnames: ["api.example.com"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /v2
    backendRefs:
    - name: api-v2
      port: 8080
      weight: 20          # 20%流量到v2
  - backendRefs:
    - name: api-v1
      port: 8080
      weight: 80          # 80%流量到v1

六、故障排查实战

6.1 Ingress返回502/503

# 检查Ingress Controller日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx

# 检查后端Service是否有Endpoints
kubectl get endpoints api-service
# 如果没有Endpoints → 检查Service selector

# 检查Pod是否就绪
kubectl get pods -l app=api
# 如果Pod NotReady → 检查readinessProbe

6.2 Ingress规则不生效

# 检查Ingress状态
kubectl describe ingress multi-host-ingress
# Events:
#   Normal  Sync  ...  Scheduled for sync

# 检查ingressClassName
kubectl get ingress -o wide
# 如果CLASS为none → 检查ingressClassName

# 检查IngressClass
kubectl get ingressclass
# NAME    CONTROLLER                     PARAMETERS   AGE
# nginx   k8s.io/ingress-nginx           <none>       1h

6.3 TLS证书问题

# 检查证书Secret
kubectl get secret example-tls -o yaml
# 确认tls.crt和tls.key存在且有效

# 使用cert-manager自动管理
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml

# ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx

七、练习

  1. 安装Nginx Ingress Controller,创建基于域名的Ingress规则
  2. 配置基于路径的路由:/api→api-service, /web→web-service
  3. 使用Annotations配置限流、CORS和WebSocket支持
  4. 实现金丝雀发布:20%流量到v2版本
  5. 安装cert-manager,配置自动HTTPS证书

🏆 第10课成就解锁

下一课预告:第11课深入RBAC权限——K8s安全体系的核心。