前面我們已經把 Backend 做成 Docker Image。
例如:
backend:v1.0
然後可以啟動很多個 Container:
Container 1
Container 2
Container 3
如果只有三個 Container,人工管理還算容易。
例如:
docker run backend:v1.0
或:
docker stop container_1
docker restart container_2
都還可以接受。
但是如果系統規模變成:
30 個 Container
100 個 Container
甚至更多
問題就開始出現了。
假設現在有三台實體機:
Server A
Server B
Server C
每一台都可以跑 Docker。
現在有 30 個 Container。
那要怎麼分配?
例如:
Server A
├── Container 1
├── Container 2
├── Container 3
└── ...
Server B
├── Container 11
├── Container 12
└── ...
Server C
├── Container 21
├── Container 22
└── ...
如果全部靠人工決定,就要自己判斷:
哪台 Server CPU 比較低?
哪台 Memory 比較多?
哪台還有空間?
這個 Container 應該放哪裡?
Container 越多,管理就越困難。
假設:
Container 5
因為程式錯誤突然停止。
如果沒有自動管理機制,就只能靠人:
發現服務掛掉
│
▼
SSH 進 Server
│
▼
docker ps
│
▼
docker restart
問題是:
如果凌晨三點掛掉呢?
如果一次掛了五個呢?
如果管理的是數十台 Server 呢?
我們會希望系統可以自己做到:
Container 掛掉
│
▼
自動重新建立
而不是等待工程師手動處理。
這比 Container 掛掉更麻煩。
假設:
Server B
上面跑了:
Container 11
Container 12
Container 13
Container 14
結果 Server B 整台故障。
此時:
Container 11 X
Container 12 X
Container 13 X
Container 14 X
如果靠人工,就要:
找到其他正常 Server
│
▼
重新啟動這些 Container
│
▼
重新加入 Load Balancer
理想狀況應該是:
Server B 掛掉
│
▼
系統偵測到
│
▼
自動把 Container
搬到 Server A / C
這就是更進一步的自動化需求。
假設平常只需要:
3 個 Backend Container
但是促銷活動開始後:
CPU 90%
Request 大量增加
我們可能需要:
3 → 10 個 Container
如果人工:
docker run backend:v1.0
docker run backend:v1.0
docker run backend:v1.0
...
顯然很麻煩。
而且還要:
找 Server
分配 Port
加入 Load Balancer
確認 Health Check
因此我們希望:
CPU 過高
│
▼
自動增加 Container
流量降低後:
自動減少 Container
這就是前面提過的 Auto Scaling。
假設現在 Production 跑的是:
backend:v1.0
總共有:
10 個 Container
現在要部署:
backend:v1.1
最簡單但不好的方式是:
全部停止 v1.0
│
▼
全部啟動 v1.1
這樣中間可能會出現服務中斷。
比較理想的方式是:
v1.0
v1.0
v1.0
v1.0
↓
v1.1
v1.0
v1.0
v1.0
↓
v1.1
v1.1
v1.0
v1.0
↓
v1.1
v1.1
v1.1
v1.1
也就是逐步替換。
這叫做:
Rolling Update
這樣就可以在不中斷服務的情況下更新版本。
Container 是會變動的。
例如:
Container 1
Container 2
Container 3
過了一段時間:
Container 2 掛掉
新增 Container 4
現在 Backend 變成:
Container 1
Container 3
Container 4
Load Balancer 必須知道新的位置。
否則還可能繼續把 Request 傳給:
Container 2
所以系統必須具備:
Service Discovery
也就是自動知道:
目前有哪些 Container 可以提供服務?
到這裡,Container 管理就已經不只是:
docker run
而是需要解決:
Container 放在哪台 Server?
掛掉誰重啟?
Server 掛掉怎麼搬?
流量變大怎麼擴充?
流量變小怎麼縮減?
新版怎麼更新?
Load Balancer 怎麼知道有哪些 Container?
怎麼監控 Container 健康狀況?
如果全部自己寫 Script 解決,會越來越複雜。
因此就需要一個系統:
專門負責管理大量 Container。
這類系統叫做:
Container Orchestration
也就是「Container 編排」。
Kubernetes,常簡稱:
K8s
就是一套 Container Orchestration Platform。
它的核心概念可以先簡單理解成:
你告訴 Kubernetes「我想要什麼狀態」,它會盡量幫你維持這個狀態。
例如你告訴 Kubernetes:
我要 3 個 Backend
Kubernetes 就會確保:
Backend 1
Backend 2
Backend 3
都存在。
如果 Backend 2 掛掉:
Backend 1 ✓
Backend 2 X
Backend 3 ✓
Kubernetes 會發現:
目前只有 2 個
但你要求的是:
3 個
因此它會自動建立新的:
Backend 4
最後又恢復:
Backend 1
Backend 3
Backend 4
重新變成三個。
這種概念叫:
Desired State
也就是「期望狀態」。
傳統 Docker 操作比較像:
請幫我啟動 Container
也就是命令式。
例如:
docker run backend:v1.0
而 Kubernetes 的思維更像:
我要一直維持 3 個 backend:v1.0
例如概念上:
replicas: 3
image: backend:v1.0
Kubernetes 會自己想辦法維持:
3 個 Container
如果少了:
補回來
如果多了:
減少
所以 Kubernetes 的重點是:
不是告訴它每一步要怎麼做
而是告訴它最後應該長什麼樣子
開始進入 Kubernetes 名詞前,先看整體。
假設現在有三台 Server:
Server A
Server B
Server C
我們把它們交給 Kubernetes 管理。
這一整群 Server 就可以形成:
Kubernetes Cluster
例如:
Kubernetes Cluster
┌──────────┼──────────┐
▼ ▼ ▼
Server A Server B Server C
Cluster 可以理解成:
一整組由 Kubernetes 管理的運算資源。
Kubernetes 不太會一直叫:
Server A
Server B
Server C
而是稱為:
Node
所以:
Kubernetes Cluster
│
├── Node 1
├── Node 2
└── Node 3
Node 本質上可以是:
Physical Server
或
Virtual Machine
例如 AWS EC2、Google Compute Engine、Azure VM,都可以成為 Node。
接下來是一個 Kubernetes 很重要的概念:
Pod
很多人第一次學 Kubernetes 會問:
為什麼不直接管理 Container?
因為 Kubernetes 最小的部署單位不是 Container,而是 Pod。
最簡單的情況:
Pod
└── FastAPI Container
所以一開始可以先把:
Pod ≈ 一個 Container
這樣理解。
例如:
Pod 1
└── backend:v1.0
Pod 2
└── backend:v1.0
Pod 3
└── backend:v1.0
實際上 Pod 可以包含多個 Container,但初學時先理解一個 Pod 裡面跑一個主要 Container 就足夠。
Cluster:
Cluster
│
├── Node 1
├── Node 2
└── Node 3
Pod 則會被放到 Node 裡面:
Node 1
├── Pod A
└── Pod B
Node 2
├── Pod C
└── Pod D
Node 3
└── Pod E
Kubernetes 會負責決定:
哪一個 Pod
要放在哪一個 Node
這個過程叫:
Scheduling
因此工程師不一定要自己指定:
backend-3 一定放 Server B
Kubernetes 可以根據:
CPU
Memory
Resource Request
限制條件
選擇適合的 Node。
如果我們直接建立 Pod:
Pod 1
Pod 2
Pod 3
這些 Pod 本身還是不夠好管理。
所以 Kubernetes 通常會透過:
Deployment
來描述:
我要跑什麼 Image
我要幾個 Pod
我要怎麼更新
例如:
replicas: 3
image: backend:v1.0
概念就是:
Deployment
│
│ 我要 3 個
▼
┌──┼──┐
▼ ▼ ▼
Pod Pod Pod
因此:
Deployment
= 管理一組相同用途的 Pod
如果其中一個 Pod 掛掉:
Pod 1 ✓
Pod 2 X
Pod 3 ✓
Deployment 會透過 Kubernetes 機制補回:
Pod 4
維持 replicas:
3
原本的問題:
Container 掛掉怎麼辦?
現在:
Deployment
↓
維持 Pod 數量
↓
自動補 Pod
原本:
Container 放哪一台 Server?
現在:
Scheduler
↓
選 Node
原本:
我要 3 個 Backend
現在只需要描述:
replicas = 3
因此 Kubernetes 已經開始幫我們處理很多底層管理工作。
現在我們有:
Pod 1
Pod 2
Pod 3
問題是:
前端到底要連哪一個 Pod?
Pod 的 IP 可能是:
Pod 1 → 10.1.0.10
Pod 2 → 10.1.0.11
Pod 3 → 10.1.0.12
如果 Pod 2 掛掉,新 Pod 可能變成:
Pod 4 → 10.1.0.20
也就是:
Pod IP 不是固定的
所以 Frontend 不應該直接記住:
10.1.0.10
10.1.0.11
10.1.0.12
這時 Kubernetes 就需要下一個重要元件:
Service
Service 可以理解成:
幫一組 Pod 提供一個穩定入口。
例如:
Service
backend-service
│
┌────────┼────────┐
▼ ▼ ▼
Pod 1 Pod 2 Pod 3
Frontend 不需要知道 Pod IP。
只需要找:
backend-service
Service 再把流量分配到後面的 Pod。
即使:
Pod 2
消失,變成:
Pod 4
Frontend 還是使用:
backend-service
不用修改。
可以先這樣理解:
Service
≈ Internal Load Balancer
例如:
Frontend Pod
│
│ http://backend-service
▼
Backend Service
│
┌───┼───┐
▼ ▼ ▼
Pod Pod Pod
Service 會幫忙把 Request 分配到健康的 Pod。
因此:
Pod 可以一直變
Service 的入口保持穩定
這就是 Service 很重要的原因。
目前我們有:
Internet
?
?
Service
│
▼
Backend Pods
Service 通常主要解決 Cluster 內部服務互相溝通。
但是外部 Browser 還需要一個入口。
例如:
https://api.example.com
這時就會遇到另一個 Kubernetes 概念:
Ingress
可以先把 Ingress 理解成:
Kubernetes Cluster 的 HTTP / HTTPS 對外入口。
例如:
Internet
│
▼
Ingress
│
├── /api → Backend Service
│
└── / → Frontend Service
這其實就很像前面學過的 Nginx Reverse Proxy。
前面單機部署可能是:
Browser
│
▼
Nginx
│
┌─┴─────┐
▼ ▼
Frontend Backend
Kubernetes 裡面則可能變成:
Browser
│
▼
Ingress
│
├── /
│ ▼
│ Frontend Service
│ ▼
│ Frontend Pods
│
└── /api
▼
Backend Service
▼
Backend Pods
所以很多 Kubernetes 概念,其實不是突然出現的新東西。
而是把原本:
Nginx
Load Balancer
Server
Container
這些概念做成更加自動化、標準化的管理方式。
先不用記很多細節。
只要先理解:
Cluster
│
▼
Node
│
▼
Pod
其中:
Cluster
= 一群 Server
Node
= 一台 Server / VM
Pod
= 執行 Application 的最小單位
再加上:
Deployment
= 管理 Pod
Service
= 幫 Pod 提供穩定入口
Ingress
= 讓外部 HTTP/HTTPS 流量進入
完整關係:
Internet
│
▼
Ingress
│
▼
Service
│
┌─────────┼─────────┐
▼ ▼ ▼
Pod Pod Pod
│ │ │
└──────── Node ─────┘
Kubernetes Cluster
一開始我們的問題是:
有 100 個 Container
要怎麼管理?
Kubernetes 幫忙處理:
Container 放在哪裡
→ Scheduler
Container 掛掉
→ 自動重建 Pod
我要維持幾個 Backend
→ Deployment
Pod IP 一直變
→ Service
外部 Request 怎麼進來
→ Ingress
新版怎麼逐步部署
→ Rolling Update
流量增加怎麼增加 Pod
→ Auto Scaling
因此 Kubernetes 的核心並不是:
讓 Container 跑起來
Docker 本來就能做到。
Kubernetes 真正解決的是:
如何管理大量分散在不同 Server 上的 Container,並讓系統自動維持我們想要的狀態。
Docker 的問題比較像:
我要怎麼跑這個 Application?
答案:
Container
Kubernetes 的問題則是:
我要怎麼長期管理
幾十、幾百、甚至幾千個 Container?
答案變成:
Cluster
Node
Pod
Deployment
Service
Ingress
因此:
Docker
│
▼
標準化 Application 執行環境
│
▼
大量 Container
│
▼
Kubernetes
│
▼
管理 Container 的生命週期
這就是從 Docker 走到 Kubernetes 最自然的一條路。