完整程式碼可在 GitHub 專案中找到:Finetune-30-days-demo / day-28
當平台同時服務多組使用者(研究人員或專案團隊)時,
常會出現以下問題:
這代表系統仍是「單租戶」模式,所有人共用相同環境。
為了讓平台具備生產級隔離與治理能力,今天我們引入多租戶雛形:
Control Plane 共用,Worker Plane 分租戶隔離。
┌───────────────────────┐
│ lora-system │
│ (Control Plane) │
│ ─────────────────── │
│ FastAPI (API) │
│ Redis / Broker │
│ MongoDB / MLflow │
└──────────┬────────────┘
│
┌───────────────────┼───────────────────┐
│ │
┌───────────────┐ ┌───────────────┐
│ tenant-admin │ │ tenant-user │
│ (Worker Plane)│ │ (Worker Plane)│
│ ───────────── │ │ ───────────── │
│ Jobs / Pods │ │ Jobs / Pods │
│ Quota: High │ │ Quota: Limited│
└───────────────┘ └───────────────┘
層級 | Namespace | 範例服務 | 隔離策略 |
---|---|---|---|
Control Plane(共用層) | lora-system |
FastAPI API Server、Redis、Celery Broker、MLflow、MongoDB 等 | 共用一組,集中控制、統一管理與監控 |
Worker Plane(租戶層) | tenant-admin , tenant-user |
Celery Worker、K8s Job、訓練任務容器 | 各租戶分開 Namespace,依角色 ResourceQuota 限制 |
lora-system
。當後端收到訓練任務時,會從 Token 解析出 tenant
屬性:
tenant-admin
tenant-user
不同租戶的 Worker Job 運行在獨立命名空間內,
具備自己的 CPU / GPU / Pod 數量配額。
Namespace 間的 Log、Volume、Events 皆互不干擾,
這樣即使 B 組 Worker Crash,也不會影響 A 組的進度。
Worker Plane 的 Pod 仍可透過 Kubernetes DNS 存取共用服務,例如:
mlflow.lora-system.svc.cluster.local
redis.lora-system.svc.cluster.local
這樣即可保持「控制面集中、執行面隔離」的彈性。
# k8s/tenants/namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: tenant-admin
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant-user
# k8s/tenants/ns-user-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: user-quota
namespace: tenant-user
spec:
hard:
pods: "3"
requests.cpu: "1"
requests.memory: "2Gi"
✅ Admin 租戶:無配額限制
✅ User 租戶:限制最多 3 個 Pod、1 CPU、2Gi 記憶體
在 JWT payload 中增加 tenant
:
payload = {
"user_id": user_id,
"role": role,
"tenant": "tenant-admin" if role == "admin" else "tenant-user",
"exp": int(time.time()) + TOKEN_EXPIRE_MINUTES * 60,
}
訓練任務提交邏輯(training.py
):
tenant
tenant-user
namespace = payload.get("tenant", "tenant-user")
job.metadata.namespace = namespace
當我們完成這個多租戶雛形後,平台正式具備「治理」的能力。透過 Control Plane 共用、Worker Plane 隔離 的設計,管理層維持集中控制(API、Redis、MLflow 統一管理),而執行層則依租戶分開運行、互不干擾。Admin 與一般使用者的任務各自落在不同命名空間,資源分配透過 Quota 精準控管,Grafana 也能針對各租戶獨立觀測。這一步讓平台從「能運作」進化到「能治理」,為日後的自動化部署、計費與監控奠定基礎。
📎 AI 協作記錄:今日開發指令
# 1️⃣ JWT 擴充
請修改 app/auth/jwt_utils.py:
- create_token() 新增 tenant 欄位
- admin → tenant-admin, user → tenant-user
- decode_token() 回傳 tenant
# 2️⃣ 任務分派
請修改 app/tasks/training.py:
- 從 JWT 取得 tenant
- 動態設定 Job metadata.namespace
- 預設 tenant-user
# 3️⃣ 建立 Namespace / Quota
請新增:
- k8s/tenants/namespaces.yaml (admin, user)
- k8s/tenants/ns-user-quota.yaml (pods=3, cpu=1, mem=2Gi)
# 4️⃣ 測試流程
kubectl apply -f k8s/tenants/namespaces.yaml
kubectl apply -f k8s/tenants/ns-user-quota.yaml
kubectl get namespaces
curl -X POST /train (admin / user)
kubectl get pods -A | grep train