Kubernetes Ingress 流量管理

前言

在 Kubernetes 叢集中,如何將外部流量正確地導入到內部服務是一個關鍵的議題。Ingress 提供了一個統一的入口點,讓我們能夠透過 HTTP/HTTPS 協定來管理外部存取,並支援負載平衡、SSL 終止和基於名稱的虛擬主機等功能。

Ingress 概念

什麼是 Ingress?

Ingress 是 Kubernetes 中的一種 API 物件,用於管理叢集外部對內部服務的 HTTP 和 HTTPS 存取。它提供了以下功能:

  • 負載平衡:將流量分散到多個後端 Pod
  • SSL/TLS 終止:在 Ingress 層處理加密連線
  • 基於名稱的虛擬主機:根據主機名稱將流量導向不同服務
  • 路徑路由:根據 URL 路徑將流量導向不同服務

Ingress 與 Service 的關係

1
2
3
4
5
6
7
                    Internet
                        |
                   [ Ingress ]
                   /         \
              [ Service A ]  [ Service B ]
                  |              |
              [ Pods ]       [ Pods ]

Ingress 位於 Service 之前,負責接收外部流量並根據規則將其路由到對應的 Service。

Ingress Controller 安裝

為什麼需要 Ingress Controller?

Ingress 資源本身只是一組規則的定義,需要 Ingress Controller 來實際執行這些規則。常見的 Ingress Controller 包括:

  • NGINX Ingress Controller
  • Traefik
  • HAProxy Ingress
  • Kong Ingress Controller
  • AWS ALB Ingress Controller

安裝 NGINX Ingress Controller

使用 Helm 安裝是最常見的方式:

1
2
3
4
5
6
7
8
# 新增 NGINX Ingress 的 Helm repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 安裝 NGINX Ingress Controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace

或者使用官方提供的 YAML 檔案安裝:

1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml

驗證安裝

1
2
3
4
5
# 檢查 Ingress Controller Pod 狀態
kubectl get pods -n ingress-nginx

# 檢查 Ingress Controller Service
kubectl get svc -n ingress-nginx

路由規則設定

基本路由設定

以下是一個基本的 Ingress 設定範例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

多路徑路由

將不同路徑導向不同服務:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-path-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: default-service
            port:
              number: 80

多主機路由

根據不同主機名稱導向不同服務:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        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

pathType 說明

  • Prefix:路徑前綴匹配,/api 會匹配 /api/api//api/v1
  • Exact:精確匹配,只匹配完全相同的路徑
  • ImplementationSpecific:由 Ingress Controller 決定匹配方式

TLS 設定

建立 TLS Secret

首先,需要將 SSL 憑證儲存為 Kubernetes Secret:

1
2
3
4
5
# 從現有憑證檔案建立 Secret
kubectl create secret tls my-tls-secret \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key \
  -n default

或使用 YAML 檔案:

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Secret
metadata:
  name: my-tls-secret
  namespace: default
type: kubernetes.io/tls
data:
  tls.crt: <base64-encoded-cert>
  tls.key: <base64-encoded-key>

設定 Ingress TLS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: my-tls-secret
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

使用 cert-manager 自動管理憑證

cert-manager 可以自動申請和更新 Let’s Encrypt 憑證:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auto-tls-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls-secret
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

Annotations 使用

Annotations 是擴展 Ingress 功能的重要方式,不同的 Ingress Controller 支援不同的 Annotations。以下是 NGINX Ingress Controller 常用的 Annotations:

重寫路徑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rewrite-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: api-service
            port:
              number: 8080

SSL 重導向

1
2
3
4
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

限流設定

1
2
3
4
metadata:
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "10"
    nginx.ingress.kubernetes.io/limit-connections: "5"

跨域資源共享 (CORS)

1
2
3
4
5
6
metadata:
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization"

自訂 Timeout

1
2
3
4
5
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"

上傳檔案大小限制

1
2
3
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"

負載平衡演算法

1
2
3
metadata:
  annotations:
    nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"

完整範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: production-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.example.com
    secretName: api-tls-secret
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

故障排除

常見問題檢查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 檢查 Ingress 狀態
kubectl get ingress

# 檢查 Ingress 詳細資訊
kubectl describe ingress <ingress-name>

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

# 檢查後端 Service 和 Endpoints
kubectl get svc,endpoints <service-name>

常見錯誤

  1. 503 Service Temporarily Unavailable:後端服務不可用或沒有健康的 Pod
  2. 404 Not Found:路徑配置錯誤或服務不存在
  3. 無法連線:檢查 Ingress Controller 是否正常運行,外部負載平衡器是否正確設定

總結

Kubernetes Ingress 是管理叢集外部流量的強大工具。透過適當的設定,我們可以實現:

  • 統一的流量入口管理
  • 基於主機和路徑的智慧路由
  • 自動化的 TLS 憑證管理
  • 豐富的流量控制功能

在實際應用中,建議根據需求選擇適合的 Ingress Controller,並善用 Annotations 來擴展功能。同時,配合 cert-manager 等工具可以大幅簡化憑證管理的工作。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy