AKS on Azure Local のコンピューティング集中型ワークロードに GPU を使用してマルチラックデプロイを行う

この記事では、Azure Local のマルチラック展開環境において、Azure Arc 対応 AKS で GPU 対応ノード プールをデプロイおよび構成する方法について説明します。 グラフィカル処理ユニット (GPU) は、機械学習、ディープ ラーニング、AI 推論などのコンピューティング集中型ワークロードに役立ちます。

Azure Local プラットフォームは、vfio-pci PCI パススルーを使用して個別のデバイス割り当て (DDA) を使用して、物理 GPU を AKS Arc worker 仮想マシン (VM) に公開します。 AKS Arc クラスター内のワークロードは、デバイスに対して直接実行できます。

サポートされている GPU モデルと VM サイズ

マルチラック展開用の AKS on Azure Localでは、次の GPU ハードウェアと SKU がサポートされています。

GPU モデル サポートされている VM サイズ vCPU メモリ (GiB) VM あたりの GPU 数
NVIDIA RTX Pro 6000 Blackwell (96 GiB) Standard_NC16_RTX6000Pro_1 16 64 1
NVIDIA RTX Pro 6000 Blackwell (96 GiB) Standard_NC32_RTX6000Pro_1 32 128 1

Note

マルチ GPU SKU ( Standard_NC16_RTX6000Pro_2Standard_NC32_RTX6000Pro_2など) はカタログに存在しますが、まだ一般公開されていません。

始める前の準備

GPU 対応ノード プールを作成するには、次の要件が満たされていることを確認します。

  • マルチラック展開用のAzure Local クラスターがデプロイされ、Azure Arcに登録されます。詳細については、マルチラック展開の概要を参照してください。

  • Azure Local クラスターのカスタムの場所に、使用可能な NVIDIA RTX Pro 6000 GPU を備えた物理コンピューティング ノードがあることを確認します。 Azure Local管理者は、コンピューティング ロール ノード上のnvidia.com/nvidia-rtx-pro-6000 リソースについてプラットフォーム クラスターにクエリを実行することで、管理ノードからこれを確認できます。

    kubectl get nodes -l platform.afo-nc.microsoft.com/role=compute -o json \
      | jq -r '.items[] | .metadata.name as $n
               | .status.allocatable | to_entries[]
               | select(.key | test("nvidia|gpu|vfio"; "i"))
               | "\($n)\t\(.key) = \(.value)"'
    

    出力には、各コンピューティング ノードとその割り当て可能な GPU 関連リソースが一覧表示されます。次に例を示します。

    nvidia.com/gpu_vfio = 0
    nvidia.com/nvidia-rtx-pro-6000 = 2
    nvidia.com/gpu_vfio = 0
    nvidia.com/nvidia-rtx-pro-6000 = 2
    

    少なくとも 1 つのコンピューティング ノードが 0 以外の nvidia.com/nvidia-rtx-pro-6000 値を報告する必要があり、コンピューティング ノード間の合計は、手順 2 で要求する予定の --node-count 以上である必要があります。 ノードが表示されない場合、またはすべての値が0場合は、先に進む前に管理者またはMicrosoft サポートに問い合わせてください。

  • 最新バージョンのAzure CLIaksarc拡張機能をインストールします。

  • NVIDIA ソフトウェアへの送信アクセスを有効にする前に、テナント プロキシまたは論理ネットワーク接続を構成します。 BYO プロキシの手順については、Azure Local のマルチラック上の AKS に BYO プロキシを追加する方法を参照してください。

  • クラスター作成時に、AKS Arc クラスターが SSH キーを使用して作成され、これらの SSH キーにアクセスできることを確認します。 この記事の手順 3 と 4 では、NVIDIA ドライバーと Container Toolkit をインストールするために各 GPU ワーカー VM への SSH アクセスが必要であり、SSH キーはクラスターの作成時にのみ構成できます。

Note

GPU がポッド スペックから nvidia.com/gpu としてスケジュール可能になるように、NVIDIA ドライバー、NVIDIA Container Toolkit、NVIDIA Kubernetes デバイス プラグインを手動でインストールする必要があります。 この記事の手順 3 - 5 では、各部分について説明します。手順 6 では、ポッド ワークロードを使用してエンド ツー エンドで検証します。

手順 1: 使用可能な GPU 対応 VM サイズを一覧表示する

Azure Local クラスターをデプロイした後、GPU 対応 SKU がカスタムの場所に表示されていることを確認します。

az aksarc vmsize list --custom-location <custom location ID> --resource-group <resource group name> --output table

このリリースの場合、出力には Standard_NC*_RTX6000Pro_* SKU が含まれます。

手順 2: GPU 対応ノード プールを使用してクラスターを作成する

AKS Arc クラスターに GPU ノード プールを追加します。 コントロール プレーンとシステム ノード プールでは、標準の GPU 以外の VM サイズが使用されます。 GPU SKU は、ワークロードを実行するユーザー ノード プール専用です。

Important

初期 (システム) ノード プールとして GPU 対応 SKU を持つ AKS Arc クラスターを作成することはできません。 最初に、GPU 以外の標準の VM サイズでクラスターを作成してから、GPU 対応のユーザー ノード プールを追加する必要があります。

  1. (GPU ノード プールを使用せずに) AKS Arc クラスターを作成します。 詳細な手順とパラメーターのガイダンスについては、Azure CLIを使用した Kubernetes クラスターの作成に関する記事を参照してください。

  2. GPU 対応の Linux ノード プールを追加します。 次の例では、 Standard_NC16_RTX6000Pro_1 VM の 2 ノード プール (ノードあたり 1 つの NVIDIA RTX Pro 6000 GPU) を追加します。

    az aksarc nodepool add \
      --cluster-name <aks cluster name> \
      --resource-group <resource group name> \
      --name <nodepool name> \
      --node-count <node count> \
      --node-vm-size Standard_NC16_RTX6000Pro_1 \
      --os-type Linux
    

    プラットフォームは、コマンドの実行時に GPU 容量を検証します。 クラスターに、要求されたノード数をバックアップするための十分な物理 GPU がない場合、コマンドは失敗します。

  3. (省略可能)Azure Arc プロキシを使用してクラスターに接続します。

    az connectedk8s proxy --name <aks cluster name> --resource-group <resource group name>
    

手順 3: ワーカー VM 内に NVIDIA ドライバーをインストールする

Azure Local プラットフォームは PCI パススルーを介してワーカー VM に物理 GPU を配信しますが、ゲスト オペレーティング システム内の NVIDIA ドライバーはプレインストールされていません。 ワーカー VM は Azure Linux 3 で実行され、サポートされているインストール方法は、cuda-open から入手する Microsoft 署名済みの packages.microsoft.com RPM です。

Important

NVIDIA RTX Pro 6000 (Blackwell アーキテクチャ) には 、オープン カーネル モジュールが必要です。 cuda-open パッケージを使用します。 Azure Linux 3 では、署名されていないモジュールの実行を妨げるセキュリティの強制により、cuda インストーラーが実行されないため、NVIDIA .run パッケージを使用できません。

GPU ノード プール内の各ワーカー VM で、このセクションの手順を繰り返します。 ゲスト内シェルを開くには、SSH を使用します (SSH を使用した Windows または Linux ワーカー ノードへの接続を参照)。

  1. GPU デバイスがゲストに表示されていることを確認します。

    lspci -nn | grep -i nvidia
    

    次のようなものが予想されます。

    0e:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2bb5] (rev a1)
    
  2. ワーカー VM が、 packages.microsoft.comへの送信 HTTPS アクセス権を持っていることを確認します。

    環境で送信トラフィックに HTTPS プロキシが必要な場合は、それを使用するように tdnf を構成します。 <proxy-url>を、packages.microsoft.comに到達することが許可されているプロキシに置き換えます。

    echo 'proxy=<proxy-url>' | sudo tee -a /etc/tdnf/tdnf.conf
    

    Note

    tdnf は、 /etc/tdnf/tdnf.confからプロキシを読み取ります。 手順 4 とワーカー VM での今後のパッケージの更新には、同じプロキシが必要です。

    リポジトリへの接続を確認します。 上記でプロキシを構成した場合は、 -xを使用して明示的に渡します。それ以外の場合は、 -x フラグを省略します。

    curl -sI -x <proxy-url> https://packages.microsoft.com/azurelinux/3.0/prod/nvidia/x86_64/ | head -1
    

    予期される応答: HTTP/2 200

  3. Azure Linux NVIDIA リポジトリを有効にします。 既定では、ベース、 ms-oss、および ms-non-oss リポジトリのみが構成されます。 cuda-open パッケージは、1 回追加する必要がある別の NVIDIA リポジトリに存在します。

    sudo tee /etc/yum.repos.d/azurelinux-nvidia.repo > /dev/null <<'EOF'
    [azurelinux-official-nvidia]
    name=Azure Linux Official NVIDIA 3.0 x86_64
    baseurl=https://packages.microsoft.com/azurelinux/3.0/prod/nvidia/x86_64
    gpgkey=https://packages.microsoft.com/keys/microsoft.asc
    gpgcheck=1
    enabled=1
    sslverify=1
    EOF
    
    sudo tdnf makecache
    
  4. カーネル パッケージとtdnfが同じバージョンになるように、ビルドの前提条件と NVIDIA ドライバーを単一のcuda-openトランザクションでインストールします。 パッケージ名にもかかわらず、 cuda-open はカーネル モジュールを開いた ドライバー パッケージです。手順 4 で個別にインストールされている CUDA ツールキット (nvcc) は含まれません。

    sudo tdnf install -y \
      kernel kernel-devel kernel-headers kernel-drivers-gpu \
      libdrm-devel gcc make glibc-devel \
      cuda-open
    

    cuda-open は Mariner Trusted Base によって署名されているため、 lockdown=integrity が有効になっている場合でもカーネル モジュールが読み込まれます。

    Important

    cuda-open は、特定のカーネル ABI に対してビルドされます ( cuda-open-580.105.08-4_6.6.139.1.1.azl3など、バージョン サフィックスを参照)。 現在実行中のカーネルよりも新しいカーネルをインストールする場合は、モジュールを読み込む前に再起動する必要があります。または、modprobe nvidiaModule nvidia not found in directory /lib/modules/<running-kernel>で失敗します。 uname -rに対してrpm -q kernelを確認し、異なる場合はsudo reboot実行します。

  5. NVIDIA カーネル モジュールを読み込み、 nvidia-smiで確認します。 ドライバーが /dev/nvidia* デバイス ノードを作成できるようにするには、最初の呼び出しをルートとして実行する必要があります。ノードはモード 0666で作成されるため、後続の特権のない呼び出しは機能します。

    sudo modprobe nvidia
    sudo modprobe nvidia_uvm
    sudo modprobe nvidia_drm
    
    lsmod | grep '^nvidia'
    sudo nvidia-smi
    

    sudo nvidia-smiからの正常な出力には、インストールされているドライバーバージョンの NVIDIA RTX Pro 6000 が一覧表示されます。 この時点で、ドライバーはワーカー VM 内で完全に検証されます。

手順 4: 各 GPU ワーカー VM に NVIDIA Container Toolkit をインストールする

ドライバーはワーカー VM のホスト OS から GPU を使用できるようにしますが、コンテナーには、 /dev/nvidia* と一致するユーザー空間ライブラリ (libcuda.solibnvidia-ml.so) を確認するためのランタイム フックが必要です。 nvidia-container-toolkit パッケージは、そのフックを提供し、containerdに登録します。

各 GPU ワーカー VM で実行します。

sudo tdnf install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=containerd --set-as-default
sudo systemctl restart containerd

パッケージがインストールされていることと、 nvidia ランタイムが containerdに登録されていることを確認します。

rpm -q nvidia-container-toolkit
grep -A3 'runtimes.nvidia' /etc/containerd/config.toml

grep コマンドは、[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]runtime_type であり、io.containerd.runc.v2BinaryName を指している /usr/bin/nvidia-container-runtime ブロックを出力する必要があります。 ブロックがない場合は、 sudo nvidia-ctk runtime configure --runtime=containerd --set-as-default 再実行し、 containerdを再起動します。

手順 5: AKS Arc クラスターに NVIDIA Kubernetes デバイス プラグインをインストールする

デバイス プラグインは、 リソースとして GPU を AKS Arc クラスターのスケジューラにアドバタイズします。 これがないと、nvidia.com/gpu: 1 を要求するポッドは Pending のままになります。

次のマニフェストでは、Microsoft Container Registry (MCR) にミラー化されたデバイス プラグイン イメージを使用します。 GitHubやNvidiaのウェブサイトでも見つけることができます。

  1. az connectedk8s proxyを使用して AKS Arc クラスターに接続します。 詳細なガイダンスについては、「 クラスターへの接続」を参照してください。 --file オプションを使用して、専用の kubeconfig (たとえば、./<aks cluster name>.kubeconfig) を記述し、プロキシを実行したままにし、残りの手順のために 2 番目のターミナルのその kubeconfig でkubectlをポイントします。

  2. 次のマニフェストを 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
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            name: nvidia-device-plugin-ds
        spec:
          tolerations:
            - key: nvidia.com/gpu
              operator: Exists
              effect: NoSchedule
          priorityClassName: "system-node-critical"
          containers:
            - image: mcr.microsoft.com/oss/v2/nvidia/k8s-device-plugin:v0.19.1
              name: nvidia-device-plugin-ctr
              env:
                - name: FAIL_ON_INIT_ERROR
                  value: "false"
              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
    
  3. マニフェストを適用します。

    kubectl apply -f nvidia-device-plugin.yaml
    

DaemonSet が実行されており、GPU がアドバタイズされていることを確認します。

kubectl get pods -n kube-system -l name=nvidia-device-plugin-ds -o wide

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.allocatable.nvidia\.com/gpu}{"\n"}{end}'

GPU 対応ノードは、1の下にnvidia.com/gpuを報告する必要があります。 その場合は、手順 6 に進みます。 GPU の可用性を確認するか、期待される値が表示されない場合は、Microsoft サポートにお問い合わせください。

手順 6: (省略可能) GPU 対応ポッド ワークロードを実行する

GPU が Kubernetes ポッドからエンド ツー エンドで使用可能であることを確認するには、小さな CUDA ワークロードをデプロイし、GPU に対して完了していることを確認します。 この手順は、手順 4 と 5 が完了していること(コンテナー ツールキットがインストールされ、nvidia.com/gpu がノード上で公開されていること)を前提としています。

Note

手順 5 で kubeconfig ファイルを指定したのと同じシェルで、次の kubectl コマンドを実行します。

  1. まず、 kubectl get nodesを使用してクラスター内のノードを一覧表示します。 出力は次の例のようになります。

    NAME             STATUS  ROLES                 AGE   VERSION
    moc-l9qz36vtxzj  Ready   control-plane,master  6m14s  v1.29.0
    moc-lhbkqoncefu  Ready   <none>                3m19s  v1.29.0
    moc-li87udi8l9s  Ready   <none>                3m5s   v1.29.0
    
  2. kubectl describe nodeを使用して、GPU がワーカー ノードでスケジュール可能であることを確認します。 [ 容量 ] セクションでは、GPU は nvidia.com/gpu: 1として表示されます。

    kubectl describe <node> | grep -i gpu
    

    出力にはワーカー ノードの GPU が表示され、次の例のようになります。

    Capacity:
      cpu:                16
      ephemeral-storage:  103110508Ki
      memory:             65536000Ki
      nvidia.com/gpu:     1
      pods:               110
    
  3. 次の内容を含む gpupod.yaml という名前の新しいファイルを作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-vector-add
    spec:
      restartPolicy: OnFailure
      containers:
        - name: cuda-vector-add
          image: "k8s.gcr.io/cuda-vector-add:v0.1"
          resources:
            limits:
              nvidia.com/gpu: 1
    
  4. マニフェストを適用してサンプル アプリケーションをデプロイします。

    kubectl apply -f gpupod.yaml
    
  5. ポッドが起動し、実行が完了し、GPU が割り当てられていることを確認します。

    kubectl describe pod cuda-vector-add | grep -i gpu
    

    前のコマンドでは、1 つの GPU が割り当てられている必要があります。

    nvidia.com/gpu: 1
    nvidia.com/gpu: 1
    
  6. ポッドのログ ファイルを調べて、テストに合格したかどうかを確認します。

    kubectl logs cuda-vector-add
    

    前のコマンドからの出力例を次に示します。

    [Vector addition of 50000 elements]
    Copy input data from the host memory to the CUDA device
    CUDA kernel launch with 196 blocks of 256 threads
    Copy output data from the CUDA device to the host memory
    Test PASSED
    Done
    

次のステップ