前言
在 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>
|
常見錯誤
- 503 Service Temporarily Unavailable:後端服務不可用或沒有健康的 Pod
- 404 Not Found:路徑配置錯誤或服務不存在
- 無法連線:檢查 Ingress Controller 是否正常運行,外部負載平衡器是否正確設定
總結
Kubernetes Ingress 是管理叢集外部流量的強大工具。透過適當的設定,我們可以實現:
- 統一的流量入口管理
- 基於主機和路徑的智慧路由
- 自動化的 TLS 憑證管理
- 豐富的流量控制功能
在實際應用中,建議根據需求選擇適合的 Ingress Controller,並善用 Annotations 來擴展功能。同時,配合 cert-manager 等工具可以大幅簡化憑證管理的工作。