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 服務 (service1service2)。這裡使用 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

  1. 取得 IP: minikube ip (假設是 192.168.49.2)
  2. 編輯 hosts: sudo vi /etc/hosts
    192.168.49.2 foo.bar.com
    
  3. 測試存取: 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

操作步驟:

  1. 產生憑證 (本機測試用自簽憑證):

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
      -keyout tls.key -out tls.crt -subj "/CN=foo.bar.com"
    
  2. 建立 K8s Secret

    kubectl create secret tls my-tls-secret --key tls.key --cert tls.crt
    
  3. 套用 Ingress: 加上 TLS 設定後 kubectl apply,現在你可以用 https://foo.bar.com 訪問了(瀏覽器會警告自簽憑證不安全,這是正常的)。

總結

Ingress 是現代 K8s 應用對外服務的標準入口。透過 Ingress Controller,我們可以輕鬆管理複雜的 HTTP 路由規則與 SSL 加密。