生成AI時代のAI基盤を構築 Kubernetesの最新技術「DRA」と「GPU Operator」で実現するGPUクラスタとモニタリング環境構築方法総まとめクラウドサービスだけじゃない! ローカルPCやサーバ、Kubernetesで生成AI(7)

気軽に試せるラップトップ環境で、チャットbotを提供するオールインワンの生成AI環境構築から始め、Kubernetesを活用した本格的なGPUクラスタの構築やモデルのファインチューニングまで解説する本連載。今回はNVIDIA製GPUを用いたKubernetesクラスタの構築方法をモニタリング環境の構築手順を交えて解説します。

» 2025年08月19日 05時00分 公開
[多々納啓人, 野山瑛哲, 岡本隆史NTTドコモビジネス/NTTデータグループ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 前回の記事では、Visual Studio Codeで、生成AI(人工知能)を外部ツールと連携させるためのプロトコル「MCP」(Model Context Protocol)を利用したAIエージェントの高度な活用について概観しました。

 今回は、「生成AI時代のAI基盤構築」と題して、NVIDIA製GPUを用いたKubernetesクラスタを構築する方法を解説します。従来のDevice Pluginに代わる、Kubernetesの新しいGPU管理機構である「Dynamic Resource Allocation」(DRA)の導入と、「GPU Operator」によるコンポーネントの自動セットアップ、「Grafana LGTMスタック」(LGTM:Loki〈ログ〉、Grafana〈ダッシュボード〉、Tempo〈トレーシング〉、Mimir〈メトリクス〉)によるGPUモニタリング環境の構築手順まで一挙に紹介します。

KubernetesがGPUクラスタ環境に選ばれる理由

 生成AIの本格的な学習、ファインチューニングおよび推論環境を構築するには、複数のGPUとノードで構成されるクラスタが不可欠です。GPUを活用した生成AIクラスタの基盤として、Kubernetesが注目されており、以下の理由から選択される機会が増えてきています。

  • コンテナによるポータビリティとスケーラビリティ:ワークロードのポータビリティを確保し、GPUリソースを効率的にスケールできる
  • GPUリソースの動的管理:GPUリソースを動的に割り当て、利用状況に応じて最適化できる
  • KubeflowやMLflowとの統合性:ML(機械学習)プラットフォームであるKubeflowやMLflowとの高い統合性により、MLOpsのワークフローを効率化できる
  • DevOpsとMLOpsの統合:開発運用と機械学習運用の両方をKubernetes上で一元管理できる

 NVIDIAのAIスタック「NVIDIA AI Enterprise」にも、Kubernetesが採用されています。また、Linux Foundation傘下でAIとデータ分析のOSS(オープンソースソフトウェア)をサポートするAI & Dataプロジェクトでは、KServe、Flyte、DatasimといったKubernetesを利用したプロジェクトが推進されています。

 2025年に東京で開催された「KubeCon + CloudNativeCon Japan」では、GPUなどの特殊デバイスをPodへ割り当てるDRAに関する発表が特に注目されました。これに加え、GPUのスケーリング、マルチクラスタにおけるGPU管理、そしてKubernetes標準で開発されるモデルサービングに関する発表も行われました。こうした動向からも、データセンターにおけるGPUクラスタ運用において、Kubernetesが現在非常に注目されていることが分かります。

GPUクラスタを構築する際の課題

 しかし、KubernetesでGPUを利用できるようにするには、さまざまなコンポーネントを矛盾なくセットアップする必要があります。NVIDIA GPUを利用する場合、下記のようなコンポーネントが必要です。

GPUクラスタのアーキテクチャ GPUクラスタのアーキテクチャ
コンポーネント 説明
GPU Driver GPUをOSから利用できるデバイスとして制御
Container Toolkit コンテナランタイムがGPUを利用できるように設定
DRA Driver/Device Plugin Podに公開するGPUリソースの管理
DCGM Exporter GPUのモニタリング

 GPUの進化は目覚ましく、毎年、機能の拡充やコア数の増加が図られた新製品が登場しています。サーバ増設時に新しいGPUのノードを増やすと、ノードごとにGPUの種別を意識する必要があります。GPU Operatorは、ノード上のGPUを自動的に認識し、必要なコンポーネントを自動で用意するため、構築や運用の複雑さを解消します。

 なお、上記はGPUのPodの割り当てに限った話です。PyTorchやOllamaなどの機械学習フレームワークや推論フレームワークなどのセットアップも別途Pod内で対応が必要です。

 大規模なGPUクラスタを複数のジョブで利用するには、ジョブスケジューラなども必要となり、採用事例が既にあるVolcano、CNCF(Cloud Native Computing Foundation)で開発されているKueue、NVIDIAが2025年7月にOSSとして公開したKAI Schedulerなどがあります。

DRAについて

 Kubernetes環境において、従来のGPUデバイス管理には「デバイスプラグイン」という仕組みが用いられていました。DRAはKubernetes v1.26で試験的に導入された、FPGA、NIC、DPUなどの特殊なハードウェアを管理する新しい手法であり、以下のような特徴を持っています。

【GPUの静的、動的な確保】

 DRAでは、GPUを事前に確保することも、Pod作成時にTemplateから動的に確保することもできます。複数のPodによる分散処理をさせる場合、事前確保しておくことにより実行前にGPUを割り当てることができます

【GPUの分割と共有】

 MIG(Multi-Instance GPU)を利用したGPUの論理分割、MPS(Multi-Process Service)による複数プロセスでのGPU共有、Time Slicing(時間分割によるPod間での共有)など、さまざまな方法でGPUを複数のコンテナやPodで共有できます。これにより、ワークロードやセキュリティ要件に応じて柔軟な選択が可能です

 DRAは、2025年8月27日にリリースが予定されているKubernetes v1.34にて正式リリースされる予定です。本稿では、一足先にDRAの機能を利用します。

構築するAI基盤の仕様と構成の詳細

 本稿にて構築するAI基盤環境は、Intelのサーバ1台に下記のコンポーネントをインストールしたものとなります。

AI基盤の概要 AI基盤の概要

 GPUに「NVIDIA A100」を8枚利用していますが、GPU OperatorによりGPUが自動検出されるため、他のNVIDIA GPUであっても、本稿で紹介する手順で基盤を構築できるでしょう。GPU Operatorでサポートされるデバイスについては、NVIDIAの公式ドキュメント(NVIDIA GPU Operator / Supported NVIDIA Data Center GPUs and Systems)をご覧ください。

 緑の枠で囲まれた部分がGPUで利用するコンポーネントとなり、点線のコンポーネントはGPU Operatorが自動的にインストールしてくれます。オレンジ色の部分はモニタリング基盤です。

 端末からはUbuntuへSSH(Secure Shell)でログインし、kubectl、helm、kubeadmといったツールを利用してKubernetesクラスタの構築やPodの操作などを行います。WebブラウザからGrafanaへアクセスする際には、IngressコントローラーであるTraefikを介してアクセスします。

 なお本稿で紹介した設定ファイルは、GitHubで公開していますので、ぜひご利用ください。

サーバ/OS

 サーバ、OSは下記の通りです。

項目 利用コンポーネント
サーバ Intelサーバ
GPU NVIDIA A100 x 8
OS Ubuntu 22.04

 RHEL(Red Hat Enterprise Linux)系OSでも利用できますが、今回はUbuntuを利用しました。

Kubernetes環境

 Kubernetesの環境構築には、下記のコンポーネントを利用しました。

項目 利用コンポーネント
クラスタ構築 kubeadm
コンテナランライム containerd
CNI(ネットワーク) Calico
Ingress(トラフィックルーティング) Traefik
CSI(ストレージ) Local Path Provisioner

 今回は、1台の簡易環境なので、Local Path Provisioner(各ノードのローカルストレージ)を利用しました。大規模環境で利用する場合は、ストレージは別途ご検討ください。また、クラスタについては、クラウドベンダーのマネージドKubernetesやRed Hat OpenShiftなどKubernetesディストリビューションでも利用可能です。ベンダーの製品を利用する場合は、ベンダーが提供している手順も参考にしてください。

GPUコンポーネント

 GPU関連のセットアップには、下記のコンポーネントを利用しています。

コンポーネント 説明
NVIDIA GPU Operator GPUを検出しGPUに必要なコンポーネントのインストールと設定を行うOperator
DRA for NVIDIA GPUs GPUを管理しPodへの割り当てと解放を実施

 またGPU Operatorによって、下記のコンポーネントがインストールされます。

コンポーネント 説明
NVIDIA GPU Driver GPUドライバ
NVIDIA Container Toolkit containerdでGPUを利用可能にする
DCGM(Data Center GPU Manager) Exporter GPUメトリクスを取得する
Node Feature Discovery GPUの機能を検出し、ノードにラベル付けする
MIG Manager GPUのMIGによる分割を管理

モニタリング環境

 本稿後半にて、Grafana LGTMを利用したモニタリング環境を紹介していますので、ここでは割愛します。クラウド上でGPUクラスタを構築する場合は、クラウドのモニタリングサービスを利用してもよいでしょう。

 ここからは、下記の手順でAI基盤環境を構築していきます。

  1. OSの事前設定
  2. Kubernetesクラスタの構築
  3. Kubernetesアドオン(Calico、Local Path Provisioner、Traefik)のインストール
  4. GPUの設定
  5. Podの動作確認
  6. GPUのモニタリング(Grafana LGTMおよびKubernetes Monitoringの導入)

OSおよびKubernetesのインストール設定

 ここでは、Kubernetesクラスタを構築するためのOSおよびKubernetesのインストール手順を解説します。なお、既に構築済みのKubernetesのクラスタ環境にGPUの設定を追加する場合は、「GPUの設定」まで読み飛ばしてください。

OSの事前設定

スワップの無効化

 スワップはディスクI/O(Input/Output)を発生させ、アプリケーションの応答を遅らせるだけでなく、メモリ不足の診断を困難にします。また、Kubernetesの厳密なリソース管理とスケジューリングの整合性を損なうため、スワップを無効化し、OOM(Out of Memory)キルによる明確な障害と再起動を促す方が、スワップによる不安定な動作よりも望ましいとされます。スワップの無効化により、デバッグも容易になります。

sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

カーネルのネットワーク設定

 Pod間通信を正しく機能させるには、Linuxのカーネルパラメーターの設定が必要です。

 下記のコマンドを利用して、ブリッジ利用したネットワークトラフィックにiptablesを適用するカーネルモジュールをロードします。

sudo modprobe br_netfilter

 上記の設定が、OS再起動時に自動反映されるように下記のファイルを作成しておきます。

br_netfilter
/etc/modules-load.d/kubernetes.conf

 次に、カーネルパラメーターを設定します。下記のファイルを作成します。

# IPフォワーディングを有効にし、ノード間でPodのトラフィックをルーティング
net.ipv4.ip_forward = 1
# ブリッジを通過するパケットに対してもiptablesルールを適用(kube-proxyがiptablesモードの場合必要)
net.bridge.bridge-nf-call-iptables = 1
# 同IPv6への適用
net.bridge.bridge-nf-call-ip6tables = 1
/etc/sysctl.d/99-kubernetes.conf

 作成したらsysctlコマンドで適用します。

sudo sysctl -p /etc/sysctl.d/99-kubernetes.conf

OSパッケージ更新と必要なツールのインストール

 基本的なOSのパッケージをインストールします。

sudo apt update && sudo apt upgrade -y
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

 次に、containerdをインストールします。

sudo apt install -y containerd
sudo mkdir /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

 Kubernetes v1.33のコマンドをインストールします。

sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

Kubernetesクラスタの構築

 kubeadmの設定ファイルを下記の通り作成します。

apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.33.2
networking:
  serviceSubnet: "10.96.0.0/12"
  podSubnet: "192.168.0.0/16"
  dnsDomain: "cluster.local"
# Kubernetes v1.33以前のバージョンはDRAを有効にするため下記の設定が必要
apiServer:
  extraArgs:
    - name: runtime-config
      value: "resource.k8s.io/v1beta1=true"
    - name: feature-gates
      value: "DynamicResourceAllocation=true"
controllerManager:
  extraArgs:
    - name: feature-gates
      value: "DynamicResourceAllocation=true"
scheduler:
  extraArgs:
    - name: feature-gates
      value: "DynamicResourceAllocation=true"
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  DynamicResourceAllocation: true
kubeadm-config.yaml

 Kubernetes v1.33では、DRAが正式リリース前のため、feature-gatesによる明示的な有効化が必要です。v1.34以降は、上記apiServer以降の設定は不要となります。

 下記のコマンドでクラスタを作成します。

sudo kubeadm init --config kubeadm-config.yaml

 出力される内容に従って、クラスタにアクセスするためのkubeconfigファイルをコピーします。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

 以下のエラーが発生した場合、カーネルモジュールおよびパラメーターが正しく設定されているかどうか確認してください。

$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
[init] Using Kubernetes version: v1.33.1
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1
[preflight] If you know what you are doing, you can make a check ? non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

Kubernetesアドオンのインストール

ネットワークプラグイン(Calico)のインストール

 Podがネットワーク接続できるように、Calicoをインストールします。

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

 今回は1台構成なので、作成されたノードはコントロールプレーンとして認識され通常のPodをデプロイすることはできません。作成したPodをデプロイするワーカーとしても利用できるように、コントロールプレーンのTaintを解除します。

kubectl taint nodes $(kubectl get nodes -o name | cut -d/ -f2) node-role.kubernetes.io/control-plane-

 既にコントロールプレーンのノードが存在し、そのノードにワーカーとして追加する場合は、上記の設定は不要です。

ストレージプラグイン(Local Path Provisioner)のインストール

 Persistent Volume Claim(PVC)をノードのローカルボリュームで利用できるようにlocal-path-provisionerをインストールします。

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.31/deploy/local-path-storage.yaml

 以下のコマンドでlocal-path StorageClassをデフォルト(既定)として設定します。

kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Helmのインストール

 KubernetesのパッケージをインストールするためのHelmをインストールします。

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sudo bash

Ingressコントローラー(Traefik)のインストール

 Ingressを利用できるように、Traefikをインストールします。

 まず、下記のTraefikのHelmチャート用の設定ファイルを作成します。

ports:
  web:
    hostPort: 80
  websecure:
    hostPort: 443
gateway:
  enabled: true
  listeners:
   web:
     namespacePolicy: All
providers:
  kubernetesGateway:
    enabled: true
traefik-values.yaml

 Ingressの他、Gateway APIも有効にしています。下記の手順でインストールを実行します。

helm repo add traefik https://traefik.github.io/charts
helm repo update
helm upgrade -i traefik traefik/traefik --version 36.3.0 -n traefik --create-namespace -f traefik-values.yaml

GPUの設定

 ここから、GPUの設定をしていきます。

NVIDIA GPU Operator/DRA for NVIDIA GPUsの導入

 GPUに必要なコンポーネントとともに、NVIDIA GPU OperatorとDRA for NVIDIA GPUsを下記の手順でインストールします。

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
kubectl create namespace gpu-operator
helm install gpu-operator nvidia/gpu-operator \
  --version=v25.3.1 \
  -n gpu-operator \
  --set driver.enabled=true \
  --set toolkit.enabled=true \
  --set devicePlugin.enabled=false \
  --set cdi.enabled=true

 従来のDevice Pluginの代わりにDRAを利用するので、devicePlugin.enabledはfalseに設定します。

 次に、下記のコマンドでDRA for NVIDIA GPUsをインストールします。

helm upgrade -i my-nvidia-dra-driver-gpu nvidia/nvidia-dra-driver-gpu --version 25.3.0-rc.5 --set gpuResourcesEnabledOverride=true --create-namespace -nnvidia-dra-driver-gpu --set nvidiaDriverRoot=/run/nvidia/driver  --set cdi.enabled=true

 下記のコマンドでインストール結果を確認します(GPU関連のPodのみ表示)。

ubuntu@node1a-1:~$ kubectl get pods -A
NAMESPACE               NAME                                                          READY   STATUS      RESTARTS  AGE
gpu-operator            gpu-feature-discovery-wsq8r                                   1/1     Running     0         2m14s
gpu-operator            gpu-operator-857fc9cf65-xxb5x                                 1/1     Running     0         13m
gpu-operator            gpu-operator-node-feature-discovery-gc-86f6495b55-gmtx8       1/1     Running     0         13m
gpu-operator            gpu-operator-node-feature-discovery-master-694467d5db-w7qtf   1/1     Running     0         13m
gpu-operator            gpu-operator-node-feature-discovery-worker-77qng              1/1     Running     0         13m
gpu-operator            nvidia-container-toolkit-daemonset-4jn6l                      1/1     Running     0         7m38s
gpu-operator            nvidia-cuda-validator-dzl7c                                   0/1     Completed   0         2m3s
gpu-operator            nvidia-dcgm-exporter-8p2lb                                    1/1     Running     0         2m14s
gpu-operator            nvidia-driver-daemonset-hj98m                                 1/1     Running     0         2m14s
gpu-operator            nvidia-mig-manager-kqlqb                                      1/1     Running     0         2m14s
gpu-operator            nvidia-operator-validator-ft6dr                               1/1     Running     0         2m14
...
nvidia-dra-driver-gpu   nvidia-dra-driver-gpu-controller-589d5759f9-bwpfz             1/1     Running     0         1m5s
nvidia-dra-driver-gpu   nvidia-dra-driver-gpu-kubelet-plugin-z7dbp                    2/2     Running     0         1m5s
...

 次のようなNVIDIA Operatorのコンポーネントが実行されていることが確認できます。

コンポーネント名 説明
gpu-operator GPU Operatorのコア部分であり、他のGPU関連コンポーネントの設定とデプロイを管理
gpu-feature-discovery GPUに関する詳細な情報を検出し、その情報をKubernetesノードのラベルとして公開する。これにより、GPUの種類や機能に基づいてワークロードをスケジュール
gpu-operator-node-feature-discovery-gc Node Feature Discovery(NFD)のガベージコレクションを担当。NFDによって作成された不要なリソースを削除
gpu-operator-node-feature-discovery-master NFDのコントローラー。各ノードから検出されたハードウェア情報を集約し、KubernetesのノードにGPU用のラベルを付与
gpu-operator-node-feature-discovery-worker NFDのワーカー。各ノード上で実行され、そのノードのハードウェア(GPUを含む)に関する情報を検出し、マスターコンポーネントに送信
nvidia-container-toolkit-daemonset コンテナランタイムがGPUデバイスにアクセスできるようにするためのツールキットをインストールし、コンテナでGPUを利用可能に設定
nvidia-cuda-validator GPUの設定が正しく行われていることを確認
nvidia-dcgm-exporter NVIDIA DCGMからGPUのメトリクス(使用率、温度など)を抽出し、Prometheus形式のメトリクスとして公開
nvidia-mig-manager MIG機能を管理するためのコンポーネント。MIGが有効なGPU上で、GPUを複数の独立したインスタンスに分割し、それぞれを異なるワークロードに割り当て
nvidia-operator-validator 各コンポーネントの動作を検証し、問題があればエラーを出力
nvidia-dra-driver-gpu-controller GPUリソースの割り当て、解除、状態管理を制御
nvidia-dra-driver-gpu-kubelet-plugin 各ノード上で動作し、GPUの初期化、割り当てを実施

 正しくインストールされれば、下記のコマンドで各ノードで利用できるGPUを確認できます。

$ kubectl get resourceslices
NAME                                      NODE       DRIVER                      POOL       AGE
node1a-1-compute-domain.nvidia.com-vk6h5  node1a-1   compute-domain.nvidia.com   node1a-1   2m25s
node1a-1-gpu.nvidia.com-h82tn             node1a-1   gpu.nvidia.com              node1a-1   2m25s

 ResourceSliceリソースは、GPUの管理単位です。compute-domain.nvidia.comはMIGやMPSなどでGPUをリソース分割したときに利用されます。

 今回は、通常の分割なのでgpu.nvidia.comの方を利用します。下記のコマンドで認識されたGPUの詳細を確認できます。

$ kubectl describe resourceslices node1a-1-gpu.nvidia.com-4j5ll
Name:         node1a-1-gpu.nvidia.com-4j5ll
Namespace:
Labels:       <none>
Annotations:  <none>
API Version:  resource.k8s.io/v1beta1
Kind:         ResourceSlice
Metadata:
  Creation Timestamp:  2025-06-26T01:38:41Z
  Generate Name:       node1a-1-gpu.nvidia.com-
  Generation:          1
  Owner References:
    API Version:     v1
    Controller:      true
    Kind:            Node
    Name:            node1a-1
    UID:             b490538b-85b2-49b0-b7f4-347c1a76563f
  Resource Version:  8914636
  UID:               3d87eeb8-d80b-4706-9936-cef331d42d52
Spec:
  Devices:
    Basic:
      Attributes:
        Architecture:
          String:  Ampere
        Brand:
          String:  Nvidia
        Cuda Compute Capability:
          Version:  8.0.0
        Cuda Driver Version:
          Version:  12.8.0
        Driver Version:
          Version:  570.148.8
        Index:
          Int:  5
        Minor:
          Int:  7
        Product Name:
          String:  NVIDIA A100-PCIE-40GB
        Type:
          String:  gpu
        Uuid:
          String:  GPU-7274d657-2e08-df43-f06f-d4be16816916
      Capacity:
        Memory:
          Value:  40Gi
    Name:         gpu-5
    Basic:
      Attributes:
        Architecture:
          String:  Ampere
        Brand:
          String:  Nvidia
        Cuda Compute Capability:
          Version:  8.0.0
        Cuda Driver Version:
          Version:  12.8.0
        Driver Version:
          Version:  570.148.8
        Index:
          Int:  6
        Minor:
          Int:  5
        Product Name:
          String:  NVIDIA A100-PCIE-40GB
        Type:
          String:  gpu
        Uuid:
          String:  GPU-d0f7b6db-6dcf-b4f2-f1a9-858a807e855e
      Capacity:
        Memory:
          Value:  40Gi
    Name:         gpu-6
    Basic:
      Attributes:
        Architecture:
          String:  Ampere
        Brand:
          String:  Nvidia
        Cuda Compute Capability:
          Version:  8.0.0
        Cuda Driver Version:
          Version:  12.8.0
        Driver Version:
          Version:  570.148.8
        Index:
          Int:  7
        Minor:
          Int:  4
        Product Name:
          String:  NVIDIA A100-PCIE-40GB
        Type:
          String:  gpu
        Uuid:
          String:  GPU-2945b7e8-3bb0-14c1-99b9-986b6ce57629
      Capacity:
        Memory:
          Value:  40Gi
...(以下略)...

 このコマンドにより、ノードで認識されている各GPUのモデル(NVIDIA A100-PCIE-40GB)、ドライバやCUDAのバージョン、メモリなどを確認できます。

GPU Operatorの仕組み

 GPU Operatorは、NFDと呼ばれるコンポーネントが、ノードのGPUを検出し、ラベルを付与します。付与されたラベルに応じて、DaemonSetのPodが該当するノードに配置され、コンポーネントのインストールやGPUメトリクスの取得が行われます。

GPU Operatorの概要 GPU Operatorの概要

 また、GPU Operator ValidatorがGPU Operator各コンポーネントが正しく動作しているかどうかを検証し、CUDA Validatorがノード上のGPUの設定が正しく行われているかどうかを確認します。

 この仕組みを理解しておくことで、トラブル発生時の原因切り分けが容易になります。

PodからGPUを利用できるかどうか確認

 さて、GPUのセットアップが終わったら、GPUをPodから利用してみましょう。

 今回、GPUのアサインにDRAを利用していますが、DRAでは、下記の3つのリソースが利用されます。CSI(Container Storage Interface)で対応する機能を併記しておくので、参考にしてください。

リソース 説明 CSIにおける対応機能
DeviceClass 要求するリソースのデバイスを定義する。種類を定義する。NVIDIA GPU DRA driverでは、gpu.nvidia.com と mig.nvidia.com(MIG用)が提供される StorageClass
ResourceClaimTemplate リソース要求を定義したテンプレート。クラウドにおけるインスタスタイプに似ている volumeClaimTemplate
ResourceClaim Podに割り当てられる実際のリソース、Pod作成時にResourceClaimTemplateを元に自動的にリソースの空きノードに作成され、Podに割り当てられる。もしくはPersistentVolumeClaimのように手動で作成することもできる PersistentVolumeClaim

ResourceClaimTemplateの作成

 まずは、Podに割り当てるリソースを定義するResourceClaimTemplateを作成します。

apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaimTemplate
metadata:
  name: single-gpu
  namespace: test
spec:
  spec:
    devices:
      requests:
      - name: gpu
        deviceClassName: gpu.nvidia.com

 Kubernetes v1.34以降の場合は、apiVersionを下記のようにv1beta1ではなくv1としてください。

  • 1.33以前:apiVersion: resource.k8s.io/v1beta1
  • 1.34以降:apiVersion: resource.k8s.io/v1

 ResourceClaimTemplateリソースを作成します。

$ kubectl create ns test
$ kubectl apply -f rct-test.yaml
$ kubectl get resourceclaimtemplate
NAME         AGE
single-gpu   10s

 ResourceClaimTemplateはあくまでテンプレートなので、ResourceClaimTemplateリソースを作成した時点ではGPUはアサインされません。

 作成したテンプレートはアサインするGPU個数やタイプ(MIGの利用)などに応じて作成します。テンプレートは複数のPodで利用可能です。

 ResourceClaimTemplateを利用したPodは、次のようにResourceClaimを利用して定義します。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-test
  namespace: test
spec:
  restartPolicy: OnFailure
  containers:
    - name: gpu-container
      image: nvcr.io/nvidia/cuda:12.9.0-base-ubuntu24.04
      command: ["/bin/bash", "-c"]
      args: ["nvidia-smi -L && sleep 3600"]
      resources:
        claims:
        - name: gpu
  # 定義したsingle-gpuのアサイン
  resourceClaims:
  - name: gpu
    resourceClaimTemplateName: single-gpu
gpu-test.yaml

 下記のコマンドでPodを作成します。

$ kubectl apply -f gpu-test.yaml

 Pod作成後、以下のようにGPUを割り当てるResourceClaimが作成されていることを確認できます。kubectl describeの結果から、node1a-1上のGPUが割り当てられていることも確認できます。

$ kubectl -n test get resourceclaim
NAME                 STATE                AGE
gpu-test-gpu-ccxfx   allocated,reserved   56s
$ kubectl -n test describe resourceclaim gpu-test-gpu-ccxfx
Name:         gpu-test-gpu-ccxfx
Namespace:    test
Labels:       <none>
Annotations:  resource.kubernetes.io/pod-claim-name: gpu
API Version:  resource.k8s.io/v1beta1
Kind:         ResourceClaim
Metadata:
  Creation Timestamp:  2025-07-08T00:32:31Z
  Finalizers:
    resource.kubernetes.io/delete-protection
  Generate Name:  gpu-test-gpu-
  Owner References:
    API Version:           v1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Pod
    Name:                  gpu-test
    UID:                   c172503c-6010-47c2-bc8f-2ccb3455d53c
  Resource Version:        11761568
  UID:                     776facfe-de91-4769-91df-b794edf38300
Spec:
  Devices:
    Requests:
      Allocation Mode:    ExactCount
      Count:              1
      Device Class Name:  gpu.nvidia.com
      Name:               gpu
Status:
  Allocation:
    Devices:
      Results:
        Admin Access:  <nil>
        Device:        gpu-5
        Driver:        gpu.nvidia.com
        Pool:          node1a-1
        Request:       gpu
    Node Selector:
      Node Selector Terms:
        Match Fields:
          Key:       metadata.name
          Operator:  In
          Values:
            node1a-1
  Reserved For:
    Name:      gpu-test
    Resource:  pods
    UID:       c172503c-6010-47c2-bc8f-2ccb3455d53c
Events:        <none>

 今回は、ResourceClaimはテンプレートから作成しましたが、手動で作成することもできます。Pod実行時のGPU不足を避けるには、手動であらかじめResourceClaimを作成しておくとよいでしょう。

 Podのログを確認すると、nvidia-smiでGPUを認識していることが分かります。

$ kubectl logs -n test gpu-test
GPU 0: NVIDIA A100-PCIE-40GB (UUID: GPU-7274d657-2e08-df43-f06f-d4be16816916)

 利用可能なGPU総数、利用中のGPU数、利用可能なGPU数は以下のコマンドで確認できます。

$ USE=$(kubectl get resourceclaims -A -o json | jq '[.items[].status.allocation.devices.results | length]| add')
$ TOTAL=$(kubectl get resourceslices -o json | jq '[.items[] | select(.spec.driver == "gpu.nvidia.com") | .spec.devices | length] | add')
$ echo "Total GPU:     " $TOTAL
$ echo "Used GPU:      " $USE
Total GPU:      8
Used GPU:       7

その他のGPU割り当てサンプル

 DRA for NVIDIA GPUsのGitHubにてサンプルコードが公開されています。MPSやTime Slicingを用いて複数のPodで1つのGPUを共有したり、MIGでGPUを論理分割したりするコードが公開されていますので、興味がある人は参照してみてください。

GPUのモニタリング(Grafana LGTM/Kubernetes Monitoring)の導入

 ここからはメトリクス、ログ、トレーシングのオブザーバビリティ3要素を包括的に扱えるGrafana LGTMと、これと連携するGrafana Kubernetes Monitoringを利用して、KubernetesクラスタとGPUのモニタリング環境を構築します。

 Grafana LGTMとKubernetes Monitoringを利用することにより、耐障害性とスケーラビリティに優れたモニタリング環境を簡単に実装できます。

 今回、構築する構成の概要は、下記の図のようになります。

モニタリング環境の構成イメージ モニタリング環境の構成イメージ

 Kubernetes Monitoringは、オブザーバビリティにおけるシグナル(ログ、メトリクス、トレーシング)を収集するコンポーネントで、収集するシグナルごとに、alloy-metrics(メトリクス)、alloy-logs(ログ)、alloy-singleton(イベント)がデプロイされます。

 GPUのメトリクスはGPU Operatorによりデプロイされるdcgm exporterにより取得されますが、本稿では、dcgm exporter専用のAlloy(alloy dcgm sender)を利用しMimirへ転送します。

 LGTMの各コンポーネントはマイクロサービスにより実装され、複数のPodの組み合わせにより構成されます。その詳細については割愛します。

 Kubernetes Monitoringは、Alloyを利用して各種情報を収集してLGTMに送信しています。以前は、ログ収集のPromtailや総合的なオブザーバビリティエージェントであるGrafana Agentが提供されていましたが、2025年7月時点で、新規機能についてはAlloyとして開発が継続されています。

 今回は、Grafana Kubernetes Monitoringのアップグレードや構成変更の影響を受けないよう、GPUのメトリクスを送信するAlloyを個別にデプロイする構成を取りました。

 以下、下記の手順でモニタリング環境の構築について紹介します。

  1. Grafana LGTMのインストール
  2. Kubernetes Monitoringのインストール
  3. GPUのモニタリング設定
  4. Grafana に GPU ダッシュボードを追加

Grafana LGTMのインストール

 最初にモニタリングするためのLGTMスタックを構築します。下記のコマンドを実行し、YAMLファイルを準備します。

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
loki:
  loki:
    structuredConfig:
      # メタデータの構造化を行いGrafanaで読めるようにする
      limits_config:
        allow_structured_metadata: true
      # minio上のログデータの圧縮
      compactor:
        shared_store: s3
        working_directory: /var/loki/compactor
      storage_config:
        # インデックスをローカルのboltdbに保存しminioに同期
        boltdb_shipper:
          active_index_directory: /var/loki/index
          cache_location: /var/loki/cache
          shared_store: s3
        # S3ストレージをminioに設定
        aws:
          bucketnames: loki-chunks
          endpoint: lgtm-minio:9000
          access_key_id: ${MINIO_ACCESS_KEY_ID}
          secret_access_key: ${MINIO_SECRET_ACCESS_KEY}
          s3forcepathstyle: true
          insecure: true
      # boltdbの設定
      schema_config:
        configs:
          - from: "2024-01-01"
            store: boltdb-shipper
            object_store: s3
            schema: v12
            index:
              prefix: index_
              period: 24h
  extraEnv:
    # minioのシークレットの設定
    - name: MINIO_ACCESS_KEY_ID
      valueFrom:
        secretKeyRef:
          name: lgtm-minio
          key: rootUser
    - name: MINIO_SECRET_ACCESS_KEY
      valueFrom:
        secretKeyRef:
          name: lgtm-minio
          key: rootPassword
# GrafanaのIngressを設定
grafana:
  ingress:
    enabled: true
    hosts:
    - grafana.local
lgtm-values.yaml

 上記のYAMLファイルを使って、LGTMスタックをデプロイします。

$ helm upgrade -i lgtm grafana/lgtm-distributed --version 2.1.0 -n monitoring --create-namespace  -f lgtm-values.yaml

 インストールしたGrafanaのadminのユーザーのパスワードは、下記のコマンドで取得できます。

$ kubectl get secret -n monitoring  lgtm-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
wOUZ5u7Gx....(adminのパスワード)

 Grafanaにアクセスする端末のhostsファイルに、Ingressに指定したGrafanaのホスト名(ここではgrafana.local)を記述します。

<K8sをインストールしたホストのIPアドレス> grafana.local
[例]
192.168.1.46 grafana.local
/etc/hostsまたはC:\Windows\System32\drivers\etc\hosts

 端末からブラウザでhttp://grafana.local/にアクセスするとGrafanaが表示されます。先ほど取得したadminパスワードを利用して、adminユーザーでログインしてください。

 左のナビゲーションペインから「Connections」->「Data sources」を選択すると、Loki、Mimir、Tempoがデータソースとして設定されていることが確認できます。右側の「Explore」から各データソースのクエリを実行できます。

Grafanaの画面 Grafanaの画面

Kubernetes Monitoringのインストール

 LGTMのセットアップが完了したら、KubernetesをモニタリングするGrafana Kubernetes MonitoringをHelmでインストールします。下記の設定ファイルを準備します。

cluster:
  name: kubernetes
clusterMetrics:
  enabled: true
clusterEvents:
  enabled: true
alloy-metrics:
  enabled: true
podLogs:
  enabled: true
alloy-logs:
  enabled: true
alloy-singleton:
  enabled: true
destinations:
  - name: hostedMetrics
    type: prometheus
    url: http://lgtm-mimir-nginx/api/v1/push
  - name: localPrometheus
    type: prometheus
    url: http://lgtm-mimir-nginx/api/v1/push
  - name: hostedLogs
    type: loki
    url: http://lgtm-loki-gateway/loki/api/v1/push
k8s-monitoring-values.yaml

 Helmチャートをインストールします。

helm upgrade -i k8s-monitoring grafana/k8s-monitoring --version 3.1.0 -n monitoring -f k8s-monitoring-values.yaml 

GPUのモニタリング設定

 Grafana LGTMでGPUのモニタリングを行うには、AlloyでDCGM Exporterからメトリクスを取得し、Mimirに送信します。送信する設定を記述した下記のAlloy Helmチャートの設定ファイルを作成します。

alloy:
  configMap:
    create: true
    name: alloy-config
    key: config.alloy
    content: |-
      // メトリクスの書き込み先を定義
      prometheus.remote_write "mimir" {
        endpoint {
         url = "http://lgtm-mimir-nginx/api/v1/push"
        }
      }
      // dcgm-exporterのPodを動的に検出
      discovery.kubernetes "dcgm_exporter_pods" {
        role = "pod"
        namespaces {
          names = ["gpu-operator"]
        }
        selectors {
          role  = "pod"
          label = "app=nvidia-dcgm-exporter"
          // label = "app.kubernetes.io/name=dcgm-exporter"
        }
      }
      // スクレイプの設定
      prometheus.scrape "dcgm_scrape" {
        job_name = "nvidia/dcgm_exporter"
        targets    = discovery.kubernetes.dcgm_exporter_pods.targets
        forward_to = [prometheus.remote_write.mimir.receiver]
      }
alloy-dcgm-sender.yaml

 下記のコマンドでAlloyをデプロイします。

helm upgrade -i alloy-dcgm-sender grafana/alloy --version 1.1.2 -n monitoring -f alloy-dcgm-sender.yaml

GrafanaにGPUダッシュボードを追加

 Grafanaのサイトでは、DCGM Exporterに対応したダッシュボードが幾つか公開されています。ここでは、その中でも良さそうなBetter NVIDIA DCGM Dashboardを紹介します。

 先ほど開いたGrafanaのサイト(http://grafana.local/)をWebブラウザで開きます。

 画面上部の「+」から「Import」を選択しダッシュボードをインポートします。

GrafanaのImport dashboardの選択画面 GrafanaのImport dashboardの選択画面

 ダッシュボードID「22515」を入力して「Load」をクリックします。次にデータソースにMimirを選択します。ダッシュボードのインポートに成功すると、下記のようなダッシュボードが表示されます。

 Better NVIDIA DCGM Dashboardの画面 Better NVIDIA DCGM Dashboardの画面

おわりに

 NVIDIA GPUを活用した生成AI基盤をKubernetesで構築し、そのモニタリング環境を整備する一連のステップを解説しました。Helmを利用することでインストール作業は簡素化できているものの、全ての手順を見ると、依然として内容は多岐にわたります。

 とはいえ、いったん構築してしまえば、PodへのGPU割り当ては自動化され、GPU稼働状況もモニタリングできることから、生成AI基盤の運用環境として運用上のメリットがあるといえるでしょう。

 今回は、サーバ1台の環境で構築しましたが、GPU Operatorを利用していれば、GPUを自動検出するようになるため、サーバ数が増えたクラスタにノードを追加することも容易となります。

 次回は、本稿で構築した生成AI基盤で「gpt-oss」を動かしながら、その運用をAIで効率化するアプローチも交えて解説します。次回もお楽しみに!

Copyright © ITmedia, Inc. All Rights Reserved.

アイティメディアからのお知らせ

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。