Kubernetes Ingress 使用指南
什麼是 Ingress?
Kubernetes Ingress 是一個 API 物件,用於管理對叢集內服務的外部存取,通常是 HTTP/HTTPS 流量。Ingress 提供了負載平衡、SSL 終止和基於名稱的虛擬主機功能。
Ingress 的主要功能:
- 路由管理:根據 URL 路徑或主機名稱將流量路由到不同的服務
- 負載平衡:在多個後端服務之間分配流量
- SSL/TLS 終止:處理 HTTPS 加密和解密
- 域名綁定:支援基於域名的虛擬主機
為什麼使用 Ingress?
相較於直接使用 NodePort 或 LoadBalancer 類型的 Service,Ingress 提供了更靈活的流量管理方式:
- 成本效益:一個 Ingress Controller 可以處理多個服務的外部存取
- 統一管理:集中管理所有外部流量的路由規則
- 高級功能:支援路徑重寫、認證、限流等進階功能
實作範例
這篇沿用前一篇 Service 建立好的 Spring Boot 應用程式與 dockertest-clusterip Service,直接示範如何用 Ingress 將外部 HTTP 流量導向叢集內的 Service。
整體流量會是:
1 | 使用者瀏覽器 |
確認前置資源
Namespace、Registry Secret、Deployment 與 ClusterIP Service 的建立方式前一篇 Service 已經示範過,這裡直接沿用那個結果,把重點放在 Ingress 如何接住外部 HTTP 流量。
開始前只要確認叢集裡已有下列資源:
dockertestnamespacedockertest-deploymentDeployment,並且 Pod 已經 Readydockertest-clusteripService,對外提供8080port- Service Endpoints 已經出現後端 Pod IP
可以用下列指令快速檢查:
1 | # 等待 Deployment 完成 rollout |
如果 Endpoints 有出現 Pod IP,代表 Service 已經找到符合 app: dockertest label 的 Pod。接下來就不再重複 Deployment 與 Service 的 YAML,直接進入 Ingress 設定。
啟用 Ingress Controller
Ingress 只是 Kubernetes 的路由規則,真正接收外部流量的是 Ingress Controller。以 Minikube 為例,可以先啟用內建的 NGINX Ingress Controller:
1 | minikube addons enable ingress |
確認 Controller 已啟動:
1 | kubectl get pods -n ingress-nginx |
建立 Ingress 規則
接著建立 Ingress,讓外部使用者可以透過 dockertest.local 這個網域名稱存取 Spring Boot 服務。
1 | apiVersion: networking.k8s.io/v1 |
這段設定的重點是 backend.service.name 必須指向前面建立的 dockertest-clusterip Service,而 backend.service.port.number 則要對應 Service 的 port: 8080。Ingress 不會直接連到 Pod,而是透過 Service 將流量送到符合 selector 的後端 Pod。
設定本機 hosts
在本機測試時,需要讓 dockertest.local 指向 Minikube IP:
1 | minikube ip |
取得 IP 後,將下面這行加入 hosts 檔案:
1 | <MINIKUBE_IP> dockertest.local |
不同作業系統的 hosts 檔案位置如下:
| 作業系統 | hosts 檔案位置 |
|---|---|
| Windows | C:\Windows\System32\drivers\etc\hosts |
| Linux / macOS | /etc/hosts |
部署與測試 Ingress
將 Ingress 設定存成 dockertest-ingress.yaml 後,可以使用下列指令部署:
1 | # 建立 Ingress |
完成本機 hosts 設定後,就可以測試 Ingress 是否能從外部導流到 Spring Boot 應用程式:
1 | curl http://dockertest.local/hello |
預期會取得下列回應:
1 | Hello, World! |
若無法連線,可以先確認 dockertest.local 是否正確指向 Minikube IP,再檢查 Ingress Controller、Ingress 規則、Service Endpoints 與 Pod readinessProbe 狀態。
多路由設定規則
當系統內有多個服務需要共用同一個 Ingress Controller 對外提供 HTTP 入口時,可以在同一份 Ingress 中定義多組 rules 或多個 paths。常見做法有兩種:一種是依照不同網域名稱導向不同 Service,另一種是依照 URL path 導向不同 Service。
以下範例中的 dockertest-admin-clusterip 與 dockertest-api-clusterip 代表額外的後端 Service。實際測試前,需要先用相同方式建立對應的 Deployment 與 Service,否則 Ingress 會找不到可導流的後端。
多網域路由
多網域路由適合用在不同應用程式使用不同 domain 的情境。例如 dockertest.local 導向 Spring Boot 服務,admin.dockertest.local 導向後台管理服務:
1 | apiVersion: networking.k8s.io/v1 |
這種設定會先比對 host,再將流量送到對應的 Service。測試時 hosts 檔案也需要同時加入兩個網域:
1 | <MINIKUBE_IP> dockertest.local |
多路徑路由
多路徑路由適合用在同一個 domain 下,依照 API 或功能路徑拆分後端服務。例如 / 導向前台服務,/admin 導向後台服務,/api 導向 API 服務:
1 | apiVersion: networking.k8s.io/v1 |
使用 Prefix 時,/admin 會匹配 /admin 與 /admin/users,/api 會匹配 /api 與 /api/hello。如果多個 path 都可能匹配同一個請求,Ingress Controller 通常會優先使用最長、最精確的路徑,因此建議把較明確的路徑寫清楚,再保留 / 作為預設入口。
多路由設定時要特別確認每個 backend.service.name 都已經有對應的 Service,而且 Service 的 port 要和 Ingress 的 backend.service.port.number 一致。Ingress 只負責 HTTP 路由規則,真正的 Pod 選取仍然由各自的 Service selector 決定。
多路由部署與測試
如果要測試多網域路由,可以將設定存成 dockertest-multi-host-ingress.yaml 後套用:
1 | kubectl apply -f dockertest-multi-host-ingress.yaml |
測試多網域路由前,hosts 檔案需要同時加入主要服務與後台服務的網域:
1 | <MINIKUBE_IP> dockertest.local |
接著分別測試兩個網域是否導向正確的 Service:
1 | # 測試前台服務 |
如果要測試多路徑路由,可以將設定存成 dockertest-multi-path-ingress.yaml 後套用:
1 | kubectl apply -f dockertest-multi-path-ingress.yaml |
接著用同一個 domain 搭配不同 path 測試導流結果:
1 | # 測試前台服務 |
測試多路由時,如果某一條路由無法正常回應,可以先檢查該路由對應的 Service 是否存在,以及 Service Endpoints 是否有 Pod IP:
1 | kubectl get service -n dockertest |
如果應用程式正常回應,代表外部流量已經成功經過 Ingress Controller、Ingress 規則、ClusterIP Service,最後抵達後端 Pod。
Ingress 欄位說明
| 欄位 | 說明 |
|---|---|
ingressClassName |
指定由哪一種 Ingress Controller 處理這份規則,例如 nginx |
rules.host |
指定要匹配的網域名稱,例如 dockertest.local |
paths.path |
指定 URL 路徑匹配規則,/ 代表從根路徑開始 |
paths.pathType |
指定路徑比對方式,常見值為 Prefix 與 Exact |
backend.service.name |
指定要導流到哪一個 Service |
backend.service.port.number |
指定 Service 對外提供的 port |
小結
在這個案例中,Deployment 負責建立 Spring Boot Pod,dockertest-clusterip Service 負責提供穩定的叢集內入口,而 Ingress 則負責把 dockertest.local 的外部 HTTP 流量導向該 Service。這也是 Ingress 最常見的使用方式:應用程式本身不需要直接暴露成 NodePort 或 LoadBalancer,而是透過 Service 作為內部入口,再由 Ingress Controller 統一管理對外路由。