Path-based 的天花板
Ingress 入門篇我們用 path-based 路由:
myapp.com/ → frontend-svc
myapp.com/api → api-svc
myapp.com/admin → admin-svc
簡單清楚,但有個前提:所有服務都掛在同一個域名底下。
工作上常常不是這樣。比如:
- 公開站
www.example.com給使用者 - API
api.example.com給開發者 - 後台
admin.example.com給內部
這就是 Host-based routing 的場景。
Host-based vs Path-based
| 方式 | URL 範例 | 適合 |
|---|---|---|
| Path-based | myapp.com/ + myapp.com/api | 前後端同一產品 |
| Host-based | www.myapp.com + api.myapp.com | 微服務 / 多團隊 |
- Path-based ≈ Nginx 一個
server底下多個location - Host-based ≈ Nginx 多個
server各自有不同的server_name
Host-based YAML
跟 path-based 結構幾乎一樣,差別在 rules 裡多一個 host 欄位:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: traefik
rules:
- host: www.myapp.local # ← 第一個域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
- host: api.myapp.local # ← 第二個域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 3000
兩個 host 各自一條規則。底下也可以再接 paths(host + path 混用)。
本機驗證
開發環境用 /etc/hosts 把網域指到本機:
$ sudo vim /etc/hosts
# 加兩行(IP 是 Ingress Controller 的 ADDRESS)
192.168.97.2 www.myapp.local
192.168.97.2 api.myapp.local
然後驗證:
$ curl http://www.myapp.local/
Server: 10.42.0.5:80 (frontend-deploy-abc)
Message: Hello from frontend
$ curl http://api.myapp.local/
Server: 10.42.0.7:80 (api-deploy-xyz)
Message: Hello from api
同一個 IP 192.168.97.2,不同域名導到不同 Service。 Ingress Controller 看 HTTP 請求的 Host: header 來分流。
TLS:為什麼一定要 HTTPS?
把網站改成 HTTPS 三個理由:
http:// 顯示「不安全」,使用者直接退出K8s 怎麼做?把 TLS 憑證放進 Secret,Ingress 引用它。
手動配 TLS(理解原理)
Step 1:產生憑證並存進 Secret
# 開發用:自簽憑證
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=www.myapp.local"
# 把憑證存進 K8s Secret
$ kubectl create secret tls myapp-tls \
--cert=tls.crt --key=tls.key \
-n demo
kubectl create secret tls 是專門存 TLS 的指令。type: kubernetes.io/tls 是固定型別。
Step 2:Ingress 加上 tls 區塊
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: traefik
tls: # ← 新增這段
- hosts:
- www.myapp.local
- api.myapp.local
secretName: myapp-tls # ← 對應 Secret 名稱
rules:
- host: www.myapp.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
Step 3:用 HTTPS 連
$ curl -k https://www.myapp.local/ # -k 忽略自簽憑證警告
正式環境絕對不能用自簽,瀏覽器會擋。下面用 cert-manager 自動申請正式憑證。
cert-manager + Let's Encrypt
工作上沒人手動產憑證 — 90 天到期、要續、要 rotate,全人工搞會出事。
cert-manager 是 K8s 上的標準解:
- 從 Let's Encrypt(免費的公信 CA)自動申請憑證
- 自動寫進 Secret(你只要在 Ingress 引用名字)
- 到期前自動續,零維護
工作原理
Ingress 加 annotation
↓
cert-manager 偵測到,向 Let's Encrypt 申請
↓
Let's Encrypt:「證明你擁有 www.example.com」
↓
cert-manager 用 HTTP-01 challenge 自動回答
↓
拿到憑證 → 寫進 Secret
↓
Ingress Controller 自動 reload,HTTPS 上線
Ingress 接 cert-manager
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod # ← 這行
spec:
ingressClassName: nginx
tls:
- hosts:
- www.example.com
secretName: www-tls # cert-manager 會自動建這個 Secret
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
部署完幾分鐘後 www-tls Secret 自動出現,HTTPS 就通了。
排錯重點
| 症狀 | 檢查 |
|---|---|
| HTTPS 證書錯誤 | kubectl describe certificate -n demo 看 cert-manager 狀態 |
| 連不到 host | /etc/hosts 沒設好,ping www.myapp.local 確認 IP |
| 一直走 HTTP | Ingress 的 tls 區塊忘了加 |
| 自簽憑證瀏覽器擋 | Production 換成 cert-manager + Let's Encrypt |
重點整理
- Path-based:同域名分路徑,前後端同產品
- Host-based:多域名各分流,微服務 / 多團隊
- TLS = 憑證放進
type: kubernetes.io/tls的 Secret + Ingressspec.tls引用 - 開發用
openssl自簽,正式用 cert-manager + Let's Encrypt - cert-manager 自動申請 / 自動續期 / 寫進 Secret,Ingress 只要加一個 annotation
下一步
到這裡你已經能把整個服務從 Pod 部到對外 HTTPS 網域。
但設定值 怎麼管?比如資料庫連線字串、API key、debug flag — 寫死在 image 裡不行(換環境就要重 build),寫進 YAML 也不對(密碼裸奔)。
下一篇進入第 4 組:ConfigMap:把設定從程式裡抽出來。