昨天我們拆解了 Service 背後的轉發機制 — Label Selector、Endpoints、kube-proxy,搞清楚流量是怎麼從 ClusterIP 到達 Pod 的。
但回到一個現實問題:如果你有十幾個微服務,難道每個都開一個 NodePort,讓使用者記一堆 port 號?
這時候你需要的是 Ingress — 一個統一的入口,透過 URL 路徑或域名 把流量分發到不同的 Service。
今天會從三個層面來學 Ingress:
以下操作皆在 master 節點 執行。
先來搞清楚 Ingress 在 Kubernetes 網路架構中的定位:
| 比較項目 | Service(NodePort) | Ingress |
|---|---|---|
| 運作層級 | L4(TCP / UDP) | L7(HTTP / HTTPS) |
| 路由方式 | 透過 Node IP:NodePort 存取指定 Service |
根據 Host / Path 將流量導向不同 Service |
| TLS 終止 | 本身不負責 TLS 終止 | 可由 Ingress Controller 統一處理 TLS 終止 |
| 適合場景 | 直接將 Service 暴露至叢集外部 | 多個 HTTP / HTTPS Service 共用對外入口 |
簡單說:Service 對應一組後端 Pod,Ingress 則可以透過路由規則把流量導向多個 Service
但這裡有一個很重要的觀念:
Ingress 只是「規則」,不是「執行者」
Ingress 資源本身只定義路由規則,例如「哪個路徑要導向哪個 Service」。
真正讀取這些規則並執行流量轉送的,是 Ingress Controller。如果沒有安裝 Ingress Controller,即使建立了 Ingress 資源,也不會實際產生流量轉送效果。
你可以把 Ingress Controller 想成是 L7 層的 kube-proxy:
| Controller | 底層技術 | 特色 |
|---|---|---|
| Traefik | Traefik Proxy | 支援 Kubernetes Ingress,設定相對簡單,並可動態更新路由設定。 |
| AWS Load Balancer Controller | AWS ALB / NLB | 可根據 Ingress 建立 ALB,也可根據 Service 建立 NLB,適合 AWS 環境。 |
| HAProxy Kubernetes Ingress Controller | HAProxy | 支援 HTTP、TCP 路由,適合需要高效能與進階流量控制的場景。 |
| Ingress NGINX | NGINX | 過去非常普及,但已於 2026 年 3 月停止維護,不建議新環境採用。 |
本章為了理解 Ingress 的基本運作方式,仍使用 Ingress NGINX 進行實作。實際新建的正式環境,建議評估其他仍持續維護的 Ingress Controller,或採用 Gateway API。
用官方提供的 YAML manifest 安裝,這裡使用 裸機(Bare Metal) 版本,Service 類型會自動設為 NodePort:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.1/deploy/static/provider/baremetal/deploy.yaml
這一行指令會建立 ingress-nginx namespace,並部署 Controller 所需的所有資源(Deployment、Service、ConfigMap、RBAC 等)。

等待 Controller Pod 跑起來:
kubectl get pods -n ingress-nginx -w
看到 ingress-nginx-controller-xxx 狀態為 Running 就 OK 了。

確認 Ingress Controller 建立的 Service:
kubectl get svc -n ingress-nginx
你會看到 ingress-nginx-controller 的 Service 類型是 NodePort,記下 80:3xxxx 和 443:3xxxx 對應的 NodePort,後面測試會用到。

為什麼使用 baremetal 版本?
Ingress Controller 會依部署環境提供不同的安裝方式。雲端環境通常可透過
LoadBalancer類型的 Service,整合雲端供應商提供的 Load Balancer 與外部 IP。裸機環境通常沒有雲端 Load Balancer 可直接整合,因此可使用 baremetal 版本,透過
NodePort將 Ingress Controller 對外暴露,並使用Node IP:NodePort的方式進行存取。
為了測試 Ingress 的路由功能,我們需要兩組不同的服務來分辨流量有沒有正確分流。
kubectl create deployment app-a --image=nginx
kubectl expose deployment app-a --port=80
kubectl create deployment app-b --image=nginx
kubectl expose deployment app-b --port=80
確認兩個服務都正常:
kubectl get pods,svc -l 'app in (app-a, app-b)'

等 Pod 都 Running 之後,分別寫入不同的首頁內容來區分兩個服務:
# 寫入 app-a 的回應
kubectl exec deploy/app-a -- bash -c 'echo "Hello from App A" > /usr/share/nginx/html/index.html'
# 寫入 app-b 的回應
kubectl exec deploy/app-b -- bash -c 'echo "Hello from App B" > /usr/share/nginx/html/index.html'
現在來建立第一個 Ingress 規則:根據 URL 路徑決定流量去哪裡。
建立 YAML 檔案:
vim ingress.yaml
寫入以下內容:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /app-a
pathType: Prefix
backend:
service:
name: app-a
port:
number: 80
- path: /app-b
pathType: Prefix
backend:
service:
name: app-b
port:
number: 80
關鍵欄位說明
rewrite-target: /— 將符合規則的請求路徑改寫為/後,再轉送至後端 Service。ingressClassName: nginx— 指定由 NGINX Ingress Controller 處理這個 Ingress。rules[].http.paths[]— 定義不同路徑要轉送到哪個 Service。pathType: Prefix— 使用路徑前綴進行匹配,例如/app-a也可以匹配/app-a/xxx。
套用並查看狀態:
kubectl apply -f ingress.yaml
kubectl get ingress demo-ingress
用 curl 測試(把 <NODE_IP> 和 <NODE_PORT> 替換成實際值):
# 打 /app-a 路徑
curl http://<NODE_IP>:<NODE_PORT>/app-a
# 打 /app-b 路徑
curl http://<NODE_IP>:<NODE_PORT>/app-b
你應該會看到:


同一個入口,不同路徑,自動導到不同的 Service! 這就是 Ingress 的核心價值。
除了路徑,Ingress 也可以根據 域名(Host) 來分流。這在多個應用共用同一個 IP 時特別有用。
建立 YAML 檔案:
vim host-ingress.yaml
寫入以下內容:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-ingress
spec:
ingressClassName: nginx
rules:
- host: a.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-a
port:
number: 80
- host: b.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-b
port:
number: 80
套用:
kubectl apply -f host-ingress.yaml
在測試機器上加入 DNS 映射(把 <NODE_IP> 換成你的 Node IP):
echo "<NODE_IP> a.example.com b.example.com" | sudo tee -a /etc/hosts
curl http://a.example.com:<NODE_PORT>/
# → Hello from App A
curl http://b.example.com:<NODE_PORT>/
# → Hello from App B

同一個 IP 和 Port,不同域名,自動導到不同 Service。 這就是 Host-based Routing 的威力。
在生產環境中,通常會使用 HTTPS。Ingress Controller 可以在入口處進行 TLS 終止(TLS Termination),將外部 HTTPS 流量解密後,再以 HTTP 轉送至後端 Service。
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=a.example.com"
kubectl create secret tls demo-tls \
--cert=tls.crt \
--key=tls.key
建立 YAML 檔案:
vim tls-ingress.yaml
寫入以下內容:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- a.example.com
secretName: demo-tls
rules:
- host: a.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-a
port:
number: 80
因為 tls-ingress 和前面的 host-ingress 都定義了 a.example.com + / 的規則,NGINX Ingress Controller 不允許重複,所以要先刪掉 host-ingress 再套用:
kubectl delete ingress host-ingress
kubectl apply -f tls-ingress.yaml
測試 HTTPS(-k 忽略自簽憑證警告):
curl -k https://a.example.com:<HTTPS_NODE_PORT>/
# → Hello from App A

生產環境建議
手動管理 TLS 憑證較為繁瑣,建議使用 cert-manager 搭配 Let's Encrypt,自動申請與續期 TLS 憑證。
這部分會在後續章節再進一步介紹。
把今天學到的串起來,從外部請求到 Pod 的完整路徑:
Client(瀏覽器 / curl)
│
│ https://a.example.com/api/users
│
▼
Ingress Controller(NGINX Pod)
│
│ ① TLS 終止,解密 HTTPS
│ ② 根據 Ingress 規則進行路由判斷
│ ③ Host: a.example.com → 匹配對應規則
│ ④ Path: /api/users → 導向 app-a Service
│
▼
Service(ClusterIP)
│
│ 根據 kube-proxy 建立的轉送規則
│ 選擇一個後端 Endpoint
│
▼
Pod(實際處理請求)
今天我們學會了用 Ingress 統一管理微服務的入口流量:
| 概念 | 角色 | 說明 |
|---|---|---|
| Ingress | 路由規則 | 定義「哪個 Host / Path 要導向哪個 Service」。 |
| Ingress Controller | 規則執行者 | 監看 Ingress 規則,建立反向代理設定,並實際處理與轉送外部流量。 |
| Path-based Routing | 路徑分流 | 根據 URL Path 將流量導向不同 Service,例如 /app-a → Service A。 |
| Host-based Routing | 網域分流 | 根據 Host 將流量導向不同 Service,例如 a.example.com → Service A。 |
| TLS Termination | HTTPS 處理 | 由 Ingress Controller 在入口處終止 TLS,再將請求轉送至後端 Service。 |
到目前為止,我們已經完成 Pod → Service → Ingress 的完整流量路徑,了解外部請求如何一路被導向實際處理請求的 Pod。
不過,應用程式除了需要接收流量,也需要管理各種設定檔與機密資訊,例如資料庫密碼、API Key 等。
明天我們會接著介紹 ConfigMap 與 Secret,看看 Kubernetes 如何管理應用程式的設定與機密資料!