iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

昨天幫 todo-api 和 todo-frontend 各建了一個 Service,Cluster 內部的溝通沒問題了。今天要學 Ingress,建立一個統一的對外入口,把整個 Todo App 的請求路徑完整跑通 !


為什麼需要 Ingress

昨天學了三種 Service 類型,你可能會想:「直接用 LoadBalancer 對外不就好了?」

問題是:

  • 每個 LoadBalancer Service 都會建立一個獨立的雲端負載平衡器,費用和管理成本直線上升。Todo App 有前端和後端兩個服務,如果都用 LoadBalancer,就要維護兩個負載平衡器,兩個對外 IP。

  • 沒有辦法根據路徑做路由。使用者打 /api/todos 要送到後端、打 / 要送到前端,LoadBalancer 沒有這個能力,它只能把流量全部送給同一個 Service。

Ingress 解決這兩個問題:一個入口、根據路徑或 Host 決定流量送給哪個 Service。


Ingress 是什麼

Ingress 是 K8s 的 HTTP/HTTPS 路由規則,定義「什麼樣的請求要送給哪個 Service」。

使用者
  │
  ▼
Ingress(唯一對外入口)
  │
  ├── /api/*   →  todo-api-service   →  todo-api Pod
  │
  └── /        →  todo-frontend-service  →  todo-frontend Pod

整個 Todo App 只需要一個對外 IP,Ingress 根據路徑把請求分流到對應的 Service。


Ingress YAML 拆解

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: todo-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: todo-api-service
                port:
                  number: 80
          - path: /()(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: todo-frontend-service
                port:
                  number: 80
  • ingressClassName: nginx:指定使用哪個 Ingress Controller 來處理這份規則。這裡用 nginx,minikube 有內建的 nginx Ingress Controller。

  • annotations:rewrite-target: /$2 是告訴 nginx 把路徑重寫,例如 /api/todos 在進到後端之前會被改成 /todos,這樣 FastAPI 的路由不需要加 /api 前綴。

  • rules:路由規則列表,按順序比對。pathType: ImplementationSpecific 搭配 capture group (.*) 讓路徑可以正確被重寫。

  • 路由順序很重要:/api 放在 / 前面,因為 / 是萬用規則,放在前面會把所有請求都攔截掉。


實際操作

今天目標:啟用 minikube 的 nginx Ingress Controller,建立 Ingress 把 /api/* 路由到後端、/ 路由到前端,用 port-forward 驗證整個 Todo App 的請求路徑完整跑通。

Step 1: 啟用 minikube 的 Ingress Controller

  1. minikube 預設沒有開啟 Ingress Controller,需要手動啟用:
minikube addons enable ingress
  1. 確認 Ingress Controller 跑起來了:
kubectl get pods -n ingress-nginx

https://ithelp.ithome.com.tw/upload/images/20260918/20183863ZPF8Vfg35j.png

Step 2: 建立 Ingress

  1. 在 /Todo-App/k8s 目錄下,建立 todo-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: todo-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: todo-api-service
                port:
                  number: 80
          - path: /()(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: todo-frontend-service
                port:
                  number: 80
kubectl apply -f todo-ingress.yaml
  1. 確認 Ingress 狀態:
kubectl get ingress

https://ithelp.ithome.com.tw/upload/images/20260921/20183863Ywnfalsbv7.png

⚠️ 使用 Docker driver 時 ADDRESS 欄位可能是空白的
使用 Docker driver 時,minikube 跑在 Docker 的網路環境裡,Ingress 拿不到可對外的 IP,ADDRESS 欄位會一直空白。這不影響實際運作,Ingress 路由規則還是有效的,改用下方的 port-forward 方式存取即可。

Step3: 存取 Ingress

本系列使用 Docker driver,minikube 的 Node IP(192.168.49.2)是 Docker 內部網路的 IP,本機連不到,需要用 port-forward 把流量轉進 Ingress Controller:

kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8888:80

這個視窗要保持開著,之後用 http://127.0.0.1:8888 存取即可。

  • port-forward 只是解決本機進入 minikube 網路的通道問題,流量進去之後一樣完整經過 Ingress 路由,所有 YAML 不需要修改。實際的雲端環境(AWS、GCP)上,Ingress 會有真正的外部 IP,不需要這個步驟。
  • 非 Docker driver(Linux)使用者:ADDRESS 欄位會顯示 minikube 的 IP(例如 192.168.49.2),可以直接用這個 IP 存取,不需要 port-forward。

測試完整路徑

# 測試 API(後端)
curl http://127.0.0.1:8888/api/todos

# 測試前端(瀏覽器打開)
# http://127.0.0.1:8888

前端打 API 的完整流量路徑是:

瀏覽器
  │
  ▼
Ingress(127.0.0.1:8888)
  │
  ├── /api/*  →  todo-api-service  →  todo-api Pod(FastAPI)
  │
  └── /       →  todo-frontend-service  →  todo-frontend Pod(React + nginx)

從 Day 03 架構圖說的「使用者 → Ingress → Service → Pod」,今天完整跑通了。


延伸筆記:Ingress Controller 是什麼

Ingress 本身只是一份路由規則的設定,它不會自己做任何事。真正處理流量的是 Ingress Controller。

K8s 沒有內建 Ingress Controller,需要另外安裝。常見的選擇:

  • nginx:最普遍,minikube 有內建
  • Traefik:支援自動 HTTPS、middleware
  • AWS ALB:在 AWS 上使用 Application Load Balancer

可以把 Ingress 想成「nginx 的設定檔」,Ingress Controller 就是那個跑著 nginx 的 Pod,負責讀取你寫的 Ingress 規則並真正執行路由。

這也是為什麼 Ingress 的 annotation 要加 nginx.ingress.kubernetes.io/...——這些是告訴 nginx Ingress Controller 怎麼設定 nginx,不同的 Controller 有不同的 annotation。


小結

今天學了 Ingress,把整個 Todo App 的請求路徑跑通了:

  • Ingress 提供統一的對外入口,根據路徑把流量送給對應的 Service
  • Ingress Controller 是真正執行路由的元件,Ingress 只是規則設定
  • /api/* 送後端、/ 送前端,一個 IP 搞定兩個服務
  • Service 可以改回 ClusterIP,統一讓 Ingress 當對外入口
  • Docker driver 下用 port-forward 當進入 minikube 的通道,流量進去後一樣走完整的 Ingress 路由

從 Day 04 到今天,Todo App 已經完整跑在 K8s 上了:Deployment 管理 Pod、Service 處理內部路由、Ingress 統一對外入口。

明天會學 ConfigMap,把 todo-api 的環境變數設定從 YAML 裡抽出來,讓設定和程式碼分離。


上一篇
Day 08|Service
下一篇
Day 10|ConfigMap
系列文
從零學 K8s|30 天核心概念 × 實作,新手也能真正掌握 Kubernetes 共 15 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言