Kubernetes Ingress - HTTP/HTTPS 流量入口
Service (LoadBalancer) 屬於 L4 層 (TCP/UDP) 的負載平衡,它無法識別 HTTP 協定(如 Host, Path)。 如果你有 10 個微服務,每個都開一個 LoadBalancer,成本會很驚人。
Ingress 屬於 L7 層 (HTTP/HTTPS) 的路由器。它允許你使用 單一個 IP 對外提供多個服務,根據 網域名稱 (Host) 或 路徑 (Path) 來分流。
Ingress 架構
Ingress 資源本身只是一堆「規則 (Rules)」。真正負責轉發流量的是 Ingress Controller。 最常見的 Ingress Controller 是由 Kubernetes 官方維護的 Nginx Ingress Controller。
1. 開發測試環境 (Minikube)
在 Minikube 中,只需要一個指令即可啟用:
minikube addons enable ingress
2. 生產環境 (Production)
在正式環境中,我們通常使用 Helm 來安裝 Nginx Ingress Controller。
# 加入 Ingress-Nginx 的 Helm repo
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# 安裝 Controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
運作原理: 安裝完成後,Helm 會幫你部署一個 Service (Type: LoadBalancer)。
- 如果你在 AWS/GCP,雲端廠商會給你一個 公開 IP (Public IP)。
- 接下來,將你的網域名稱 (如
*.example.com) 指向這個 Public IP,所有的流量就會進入 Ingress Controller,再由它分發給後端的 Service。
前置準備:建立測試服務
為了測試 Ingress,我們先建立兩個簡單的 Web 服務 (service1 和 service2)。這裡使用 ealen/echo-server 映像檔,它會回傳請求的詳細資訊,方便除錯。
# 建立 service1
kubectl create deployment service1 --image=ealen/echo-server
kubectl expose deployment service1 --port=80
# 建立 service2
kubectl create deployment service2 --image=ealen/echo-server
kubectl expose deployment service2 --port=80
現在我們有了兩個後端服務,但它們目前只能在叢集內部存取。接下來我們用 Ingress 把它們公開出來。
定義 Ingress
建立 example-ingress.yaml:
# example-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # 指定使用 nginx controller
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 80
上述設定表示:
- 訪問
http://foo.bar.com/foo-> 轉發給service1 - 訪問
http://foo.bar.com/bar-> 轉發給service2
常見路由策略
1. Host-based Routing (基於網域)
根據不同的網域名稱 (Host),轉發到不同的後端服務。
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service # api.example.com 的流量轉給 api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service # web.example.com 的流量轉給 web-service
port:
number: 80
2. Path-based Routing (基於路徑)
在同一個網域下,根據 URL 路徑 (Path) 轉發到不同的服務。
spec:
rules:
- host: my-app.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2
port:
number: 80
http://my-app.com/v1-> 轉發給api-v1服務http://my-app.com/v2-> 轉發給api-v2服務
本地測試 (Minikube)
在 Minikube 環境測試 Ingress 需要將 Minikube IP 加入本機 /etc/hosts。
- 取得 IP:
minikube ip(假設是 192.168.49.2) - 編輯 hosts:
sudo vi /etc/hosts192.168.49.2 foo.bar.com - 測試存取:
curl http://foo.bar.com/foo
TLS / HTTPS 設置
Ingress 也負責處理 SSL 憑證。你可以建立一個類型為 kubernetes.io/tls 的 Secret,然後在 Ingress 中引用:
spec:
tls:
- hosts:
- foo.bar.com
secretName: my-tls-secret
操作步驟:
產生憑證 (本機測試用自簽憑證):
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout tls.key -out tls.crt -subj "/CN=foo.bar.com"建立 K8s Secret:
kubectl create secret tls my-tls-secret --key tls.key --cert tls.crt套用 Ingress: 加上 TLS 設定後
kubectl apply,現在你可以用https://foo.bar.com訪問了(瀏覽器會警告自簽憑證不安全,這是正常的)。
總結
Ingress 是現代 K8s 應用對外服務的標準入口。透過 Ingress Controller,我們可以輕鬆管理複雜的 HTTP 路由規則與 SSL 加密。