K8s AI GPUスケジューリング実践:MIGパーティション、GPU共有とマルチテナントワークロードオーケストレーション

云原生

概要

  • GPUはAIワークロードの中核リソース:K8sクラスタのGPU利用率は平均30-40%に過ぎず、スケジューリング最適化により80%以上へ向上可能
  • NVIDIA MIGパーティション:A100 1枚を7インスタンスに分割、異なるAIタスクの並行実行をサポート、リソース利用率3倍向上
  • GPU共有3つのモード:タイムスライス(TS)、MPS、MIG、それぞれ推論、学習、ハイブリッドシナリオに適合
  • マルチテナントスケジューリング戦略:GPUクォータ管理、優先度プリエンプション、オートスケーリングでSLA達成を確保
  • 本記事ではK8s GPUスケジューリングのフルスタックソリューションを提供、Device Plugin設定とスケジューラ拡張の実践を含む

目次


GPUスケジューリング:AIクラスタの中核課題

GPUリソース浪費の現状

課題 原因 浪費割合
推論の低利用率 単一推論リクエストはGPUの10-20%のみ使用 40-60%
学習のフラグメンテーション 小規模モデル学習がカード全体を占有 20-30%
アイドル待機 タスクがGPU解放を待機してキューに滞留 15-25%
設定不適切 リソースリクエストと実際の使用量の不一致 10-15%

GPUスケジューリング進化ロードマップ

段階 時期 ソリューション 特徴
排他モード 2020年以前 1Pod=1GPU シンプルだが浪費が多い
タイムスライス 2021 GPUタイムスライス共有 推論に適合
MIGパーティション 2022 A100ハードウェアレベル分割 高い隔離性
MPS共有 2023 マルチプロセスGPU共有 学習に適合
エラスティックスケジューリング 2024-2026 動的MIG+優先度 インテリジェント化

2026年主流GPUスペック

GPU VRAM MIGインスタンス 適合シナリオ 価格($/h)
A100 80GB 80GB 7×10GBまたは2×40GB 汎用学習・推論 3.5
H100 80GB 80GB 7×10GBまたは2×40GB 大規模モデル学習 4.5
H200 141GB 141GB 7×20GBまたは2×70GB 超大規模モデル 6.0
L40S 48GB 48GB MIG非対応 推論/ファインチューニング 1.5
RTX 4090 24GB MIG非対応 開発・テスト 0.8

NVIDIA MIGパーティション実践

MIGアーキテクチャ解説

┌──────────────────────────────────────────────────────────────┐
│              A100 80GB MIGパーティション構成                              │
│                                                                │
│  構成1: 7× MIG 1g.10gb (最大並行度)                           │
│  ┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐   │
│  │ GI 0 ││ GI 1 ││ GI 2 ││ GI 3 ││ GI 4 ││ GI 5 ││ GI 6 │   │
│  │10GB  ││10GB  ││10GB  ││10GB  ││10GB  ││10GB  ││10GB  │   │
│  │14SM  ││14SM  ││14SM  ││14SM  ││14SM  ││14SM  ││14SM  │   │
│  └──────┘└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘   │
│  適合: 7つの軽量推論サービスの並行実行                                      │
│                                                                │
│  構成2: 2× MIG 3g.40gb (大規模モデル推論)                           │
│  ┌─────────────────────────────┐┌─────────────────────────────┐│
│  │          GI 0               ││          GI 1               ││
│  │          40GB               ││          40GB               ││
│  │          42SM               ││          42SM               ││
│  └─────────────────────────────┘└─────────────────────────────┘│
│  適合: 2つの70Bモデル推論(量子化後)                                    │
│                                                                │
│  構成3: 1× MIG 4g.40gb + 2× MIG 1g.10gb (ハイブリッド)               │
│  ┌─────────────────────────────┐┌──────┐┌──────┐              │
│  │          GI 0               ││ GI 1 ││ GI 2 │              │
│  │          40GB               ││10GB  ││10GB  │              │
│  │          56SM               ││14SM  ││14SM  │              │
│  └─────────────────────────────┘└──────┘└──────┘              │
│  適合: 1つの大規模モデル推論 + 2つの軽量推論                               │
└──────────────────────────────────────────────────────────────┘

MIG設定実践

# nvidia-mig-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-mig-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      all-1g.10gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 7
      all-2g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.20gb": 3
      all-3g.40gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.40gb": 2
      mixed:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            "3g.40gb": 2
        - devices: [1]
          mig-enabled: true
          mig-devices:
            "1g.10gb": 7
        - devices: [2, 3]
          mig-enabled: false
---
apiVersion: nvidia.com/v1alpha1
kind: MigManager
metadata:
  name: mig-manager
spec:
  config: nvidia-mig-config
  gpuClientsConfig:
    version: v1
    gpuClients:
      - namespace: "ai-inference"
        podSelector:
          matchLabels:
            workload: "llm-inference"
        migDevice: "3g.40gb"
      - namespace: "ai-inference"
        podSelector:
          matchLabels:
            workload: "light-inference"
        migDevice: "1g.10gb"

MIG Podスケジューリング

# 大規模モデル推論 - MIG 3g.40gbを使用
apiVersion: v1
kind: Pod
metadata:
  name: llm-inference-70b
  namespace: ai-inference
  labels:
    workload: llm-inference
spec:
  containers:
    - name: inference
      image: vllm/vllm-openai:latest
      resources:
        limits:
          nvidia.com/mig-3g.40gb: 1
      env:
        - name: MODEL_NAME
          value: "Qwen/Qwen2.5-72B-Instruct-AWQ"
        - name: GPU_MEMORY_UTILIZATION
          value: "0.95"
        - name: MAX_MODEL_LEN
          value: "8192"
---
# 軽量推論 - MIG 1g.10gbを使用
apiVersion: v1
kind: Pod
metadata:
  name: embedding-service
  namespace: ai-inference
  labels:
    workload: light-inference
spec:
  containers:
    - name: embedding
      image: huggingface/tei:latest
      resources:
        limits:
          nvidia.com/mig-1g.10gb: 1
      env:
        - name: MODEL_NAME
          value: "BAAI/bge-large-zh-v1.5"
        - name: MAX_BATCH_SIZE
          value: "256"

GPU共有3つのモード

モード比較

項目 タイムスライス(TS) MPS MIG
隔離レベル ソフトウェア ハードウェア(一部) ハードウェア(完全)
VRAM隔離 なし(共有) なし(共有) あり(独立)
パフォーマンス隔離
並行度
障害隔離
適用シナリオ 推論 学習 ハイブリッド
GPU要件 汎用 Volta+ A100+

タイムスライス設定

# gpu-time-slicing.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gpu-time-slicing-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        renameByDefault: false
        resources:
          - name: nvidia.com/gpu
            replicas: 4
            devices: all
---
# タイムスライスを使用するPod
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inference-pool
  namespace: ai-inference
spec:
  replicas: 8
  selector:
    matchLabels:
      app: inference
  template:
    metadata:
      labels:
        app: inference
    spec:
      containers:
        - name: inference
          image: vllm/vllm-openai:latest
          resources:
            limits:
              nvidia.com/gpu: 1
          env:
            - name: MODEL_NAME
              value: "Qwen/Qwen2.5-7B-Instruct"

MPS設定

# gpu-mps-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gpu-mps-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    sharing:
      mps:
        resources:
          - name: nvidia.com/gpu
            replicas: 2
            devices: all
---
apiVersion: v1
kind: Pod
metadata:
  name: training-job-mps
  namespace: ai-training
spec:
  containers:
    - name: training
      image: pytorch/pytorch:2.4-cuda12.4
      resources:
        limits:
          nvidia.com/gpu: 1
      command:
        - python
        - -m
        - torch.distributed.launch
        - --nproc_per_node=2
        - train.py

共有モード選定の判断フロー

A100/H100を保有しているか?
├── いいえ → タイムスライス(推論) / MPS(学習)
└── はい → 完全な隔離が必要か?
    ├── はい → MIGパーティション
    └── いいえ → 学習が必要か?
        ├── はい → MPS
        └── いいえ → タイムスライス

K8s GPU Device Plugin設定

NVIDIA Device Pluginデプロイ

# nvidia-device-plugin.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      tolerations:
        - key: nvidia.com/gpu
          operator: Exists
          effect: NoSchedule
      priorityClassName: system-node-critical
      containers:
        - name: nvidia-device-plugin
          image: nvcr.io/nvidia/k8s-device-plugin:v0.16.0
          args:
            - --config=default
            - --mig-strategy=mixed
            - --pass-device-specs=true
            - --device-list-strategy=configmap
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop: ["ALL"]
          volumeMounts:
            - name: device-plugin
              mountPath: /var/lib/kubelet/device-plugins
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins

GPUリソースモニタリング

# gpu-monitor.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gpu-monitor-config
  namespace: monitoring
data:
  gpu-metrics.json: |
    {
      "metrics": [
        "gpu_utilization",
        "gpu_memory_utilization",
        "gpu_memory_used_bytes",
        "gpu_memory_total_bytes",
        "gpu_power_usage_watts",
        "gpu_temperature_celsius",
        "gpu_sm_clock_mhz",
        "gpu_mem_clock_mhz"
      ],
      "scrape_interval": "15s",
      "labels": {
        "cluster": "production",
        "region": "cn-east"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: dcgm-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: dcgm-exporter
  template:
    metadata:
      labels:
        app: dcgm-exporter
    spec:
      containers:
        - name: dcgm-exporter
          image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.7
          ports:
            - containerPort: 9400
              name: metrics
          env:
            - name: DCGM_EXPORTER_COLLECTORS
              value: "/etc/dcgm-exporter/dcp-metrics-inventory.csv"
          resources:
            limits:
              nvidia.com/gpu: 1

マルチテナントGPUスケジューリング戦略

GPUクォータ管理

# gpu-resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: gpu-quota-team-a
  namespace: team-a
spec:
  hard:
    requests.nvidia.com/gpu: "8"
    limits.nvidia.com/gpu: "8"
    requests.nvidia.com/mig-3g.40gb: "4"
    limits.nvidia.com/mig-3g.40gb: "4"
    requests.nvidia.com/mig-1g.10gb: "14"
    limits.nvidia.com/mig-1g.10gb: "14"
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: gpu-quota-team-b
  namespace: team-b
spec:
  hard:
    requests.nvidia.com/gpu: "4"
    limits.nvidia.com/gpu: "4"
    requests.nvidia.com/mig-3g.40gb: "2"
    limits.nvidia.com/mig-3g.40gb: "2"

優先度プリエンプションスケジューリング

# gpu-priority-class.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: gpu-critical
value: 1000000
globalDefault: false
description: "Critical GPU workloads - can preempt others"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: gpu-high
value: 900000
globalDefault: false
description: "High priority GPU workloads"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: gpu-low
value: 100000
globalDefault: false
description: "Low priority GPU workloads - preemptible"
---
# オンライン推論 - 高優先度
apiVersion: apps/v1
kind: Deployment
metadata:
  name: online-inference
spec:
  template:
    spec:
      priorityClassName: gpu-critical
      containers:
        - name: inference
          resources:
            limits:
              nvidia.com/mig-3g.40gb: 1
---
# オフライン学習 - 低優先度
apiVersion: batch/v1
kind: Job
metadata:
  name: offline-training
spec:
  template:
    spec:
      priorityClassName: gpu-low
      containers:
        - name: training
          resources:
            limits:
              nvidia.com/gpu: 4

GPUオートスケーリング

# gpu-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: inference-hpa
  namespace: ai-inference
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: inference-pool
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: Pods
      pods:
        metric:
          name: gpu_utilization
        target:
          type: AverageValue
          averageValue: "70"
    - type: Pods
      pods:
        metric:
          name: request_latency_ms
        target:
          type: AverageValue
          averageValue: "200"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 50
          periodSeconds: 120
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 25
          periodSeconds: 300

GPUクラスタ本番運用管理

GPUノードラベルとスケジューリング

# gpu-node-labels.yaml
# GPUタイプのラベル付け
kubectl label nodes gpu-node-1 nvidia.com/gpu.product=A100-SXM4-80GB
kubectl label nodes gpu-node-2 nvidia.com/gpu.product=H100-SXM5-80GB
kubectl label nodes gpu-node-3 nvidia.com/gpu.product=L40S-48GB

# MIG設定のラベル付け
kubectl label nodes gpu-node-1 nvidia.com/mig.config=mixed
kubectl label nodes gpu-node-2 nvidia.com/mig.config=all-3g.40gb

# 特定GPUへのスケジューリング
apiVersion: v1
kind: Pod
metadata:
  name: h100-training
spec:
  nodeSelector:
    nvidia.com/gpu.product: H100-SXM5-80GB
  containers:
    - name: training
      resources:
        limits:
          nvidia.com/gpu: 8

GPU障害自己修復

# gpu-health-check.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: gpu-health-monitor
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: gpu-health-monitor
  template:
    metadata:
      labels:
        app: gpu-health-monitor
    spec:
      serviceAccountName: gpu-health-sa
      containers:
        - name: monitor
          image: custom/gpu-health-monitor:latest
          env:
            - name: CHECK_INTERVAL
              value: "60"
            - name: MEMORY_ERROR_THRESHOLD
              value: "10"
            - name: TEMPERATURE_THRESHOLD
              value: "90"
            - name: AUTO_CORDON
              value: "true"
          volumeMounts:
            - name: nvidia
              mountPath: /usr/local/nvidia
      volumes:
        - name: nvidia
          hostPath:
            path: /usr/local/nvidia

GPU利用率最適化効果

最適化施策 利用率向上 コスト削減
MIGパーティション +35% 30%
タイムスライス +25% 20%
優先度スケジューリング +15% 15%
オートスケーリング +10% 10%
総合最適化 +50% 50%

まとめと関連情報

主要ポイントの振り返り

  1. MIGパーティション:A100/H100の最大の武器、1カードを7インスタンスに分割、推論シナリオでの最適の選択
  2. GPU共有:タイムスライスは推論に適合、MPSは学習に適合、MIGはハイブリッドに適合
  3. マルチテナントスケジューリング:クォータ+優先度+オートスケーリングの3点セットでSLAを確保
  4. 総合最適化:MIG+スケジューリング+スケーリングの組み合わせで50%のコスト削減を実現

GPUスケジューリングソリューション推奨

クラスタ規模 推奨ソリューション 期待利用率
<8カード タイムスライス 60%
8-32カード MIG+タイムスライス 75%
32-128カード MIG+優先度スケジューリング 80%
>128カード フルセットソリューション 85%+

GPU推論APIをテストするcURLコマンドを素早く生成したい?cURL→コード変換ツールJSONフォーマッターをお試しください。

関連記事

ブラウザローカルツールを無料で試す →

#K8s GPU调度#AI推理调度#GPU共享#MIG分区#K8s AI工作负载#2026