iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
生成式 AI

打造 AI 微調平台:從系統設計到 AI 協作的 30 天實戰筆記系列 第 28

[Day 28] 多租戶最小雛形:Control Plane × Worker Plane

  • 分享至 

  • xImage
  •  

完整程式碼可在 GitHub 專案中找到:Finetune-30-days-demo / day-28


當平台同時服務多組使用者(研究人員或專案團隊)時,
常會出現以下問題:

  • A 組佔滿 GPU,B 組任務排不上。
  • 不同團隊的任務 Log、模型、Volume 相互干擾。
  • 管理者難以掌握各組使用情況與資源配額。

這代表系統仍是「單租戶」模式,所有人共用相同環境。
為了讓平台具備生產級隔離與治理能力,今天我們引入多租戶雛形:
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 限制

二、設計理念說明

1️⃣ 控制層(Control Plane)保持單一

  • 所有任務入口(API Server)仍集中在 lora-system
  • 登入驗證、租戶解析、任務分派等都在共用層進行。
  • 這樣可避免「每個租戶都要重新部署 API + Redis」的高維運成本。

2️⃣ 工作層(Worker Plane)進行租戶隔離

  • 當後端收到訓練任務時,會從 Token 解析出 tenant 屬性:

    • Admin → 提交到 tenant-admin
    • User → 提交到 tenant-user
  • 不同租戶的 Worker Job 運行在獨立命名空間內,
    具備自己的 CPU / GPU / Pod 數量配額。

  • Namespace 間的 Log、Volume、Events 皆互不干擾,
    這樣即使 B 組 Worker Crash,也不會影響 A 組的進度。


3️⃣ 控制層與工作層的互通

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):

  1. 從 JWT 中解析 tenant
  2. 動態設定 Job 的命名空間
  3. 預設命名空間為 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

上一篇
[Day 27] 壓測與穩定性分析:模擬真實使用者
下一篇
[Day 29] Demo Day:從訓練到監控的完整演示
系列文
打造 AI 微調平台:從系統設計到 AI 協作的 30 天實戰筆記29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言