完整程式碼可在 GitHub 專案中找到:Finetune-30-days-demo / day-11
在前幾天,我們用 Docker Compose 成功整合了 Redis、FastAPI、Worker、Streamlit UI,專案已經能跑通非同步訓練。但隨著服務越來越多,Docker Compose 的限制逐漸浮現:
資源共享問題
缺乏調度能力
難以應付異質工作負載
👉 如果我們希望系統進一步邁向 平台化,就必須引入 Kubernetes (K8s),利用它的調度能力來解決上述問題。
K8s 的核心觀念是:每個 Pod 在啟動前,要先聲明自己需要多少資源。這讓排程器能根據需求,把 Pod 安排到合適的節點上。
這裡有兩個關鍵欄位:
requests
limits
以下是一個範例 PodSpec(以 worker 為例):
apiVersion: v1
kind: Pod
metadata:
name: worker-small
spec:
containers:
- name: worker
image: myapp/worker:latest
resources:
requests:
cpu: "500m" # 至少 0.5 CPU
memory: "512Mi" # 至少 512MB 記憶體
limits:
cpu: "1" # 最多 1 CPU
memory: "1Gi" # 最多 1GB 記憶體
這樣的配置告訴 K8s:
透過這種寫法,我們就能設計出:
為了落實資源調度,我把整個專案拆分成一組完整的 K8s manifests,集中放在 k8s/ 目錄下:
k8s/
├── manifests/ # Kubernetes 配置檔案
│ ├── namespace.yaml # 命名空間定義
│ ├── configmap.yaml # 環境變數配置(統一管理 Redis、API 等參數)
│ ├── pvc.yaml # 持久化儲存,保存 results/ 與 DB
│ ├── redis.yaml # Redis Broker/Backend
│ ├── worker.yaml # Celery Worker(定義 requests/limits)
│ ├── api.yaml # FastAPI 服務
│ └── ui.yaml # Streamlit UI
├── Makefile # 常用指令,啟動/停止/清理一行完成
└── README.md # 使用說明文件
這樣一來,從環境變數、儲存、服務到資源限制,都有明確的 YAML 配置,不再需要額外的腳本或手動設定。開發者或團隊只要執行 make deploy,就能在 K8s 上啟動一整套平台。
Day 11 的價值不在於「跑得多快」,而是讓系統第一次擁有了雲原生的樣貌。透過 requests/limits,每個服務都有清楚的資源邊界;透過 manifests 與 Makefile,部署過程高度自動化、可重現。雖然現在只能在 Mac 上模擬 CPU,但邏輯已經完整,未來換成 GPU 叢集,只需要在 YAML 加上 nvidia.com/gpu 的 requests/limits,就能把整個微調平台搬上雲端。Day 11 是專案正式跨入「雲原生微調平台」的第一步。
📎 AI 協作記錄:今日開發指令
請幫我把以下 docker-compose.yml 轉換成 Kubernetes YAML,能在 minikube 上執行:
服務:
1. Redis
- 使用官方 redis:latest image
- Port 6379
- PersistentVolumeClaim 保存資料
- 健康檢查用 `redis-cli ping`
2. Celery Worker
- 從本地 Dockerfile build 出來
- command: python -m celery -A tasks worker --loglevel=info -P solo
- 共用 PVC:results/
- env 變數由 ConfigMap 提供(來自 .env)
- 可 scale up 多個 replicas
3. FastAPI
- 從本地 Dockerfile build 出來
- command: python -m uvicorn api:app --host 0.0.0.0 --port 8000 --reload
- Port 8000
- 共用 PVC:results/
- Service 暴露 NodePort,方便本地存取
- 健康檢查 `GET /docs`
4. Streamlit UI
- 從本地 Dockerfile build 出來
- command: python -m streamlit run stepper_ui.py
- Port 8501
- 共用 PVC:results/
- Service 暴露 NodePort,方便本地存取
- 健康檢查 `/_stcore/health`
其他需求:
- 所有服務放在同一個 namespace: `lora-system`
- ConfigMap 匯入 `.env` 參數(提供 CELERY_BROKER_URL, CELERY_RESULT_BACKEND, API_URL, TZ...)
- PersistentVolumeClaim: `results-pvc`
- 輸出完整的 YAML:namespace.yaml, configmap.yaml, redis.yaml, worker.yaml, api.yaml, ui.yaml
- 驗收方式:使用 `kubectl apply -f .` 後,應能訪問
- API: http://localhost:8000
- UI: http://localhost:8501
- Redis: cluster 內 redis:6379