다중 랙 배포를 위해 Azure 로컬 AKS의 계산 집약적 워크로드에 GPU 사용

이 문서에서는 다중 랙 배포를 위해 Azure 로컬 Azure Arc 사용하도록 설정된 AKS에서 GPU 사용 노드 풀을 배포하고 구성하는 방법을 설명합니다. GPU(그래픽 처리 장치)는 기계 학습, 딥 러닝 및 AI 추론과 같은 계산 집약적 워크로드에 유용합니다.

Azure 로컬 플랫폼은 vfio-pci PCI 통과와 함께 DDA(불연속 디바이스 할당)를 사용하여 AKS Arc VM(가상 머신)에 물리적 GPU를 노출합니다. AKS Arc 클러스터 내의 워크로드는 디바이스에 대해 직접 실행할 수 있습니다.

지원되는 GPU 모델 및 VM 크기

다중 랙 배포를 위한 Azure 로컬 AKS는 다음 GPU 하드웨어 및 SKU를 지원합니다.

GPU 모델 지원되는 VM 크기 vCPU (가상 중앙 처리 장치) 메모리(GiB) VM당 GPU
NVIDIA RTX Pro 6000 Blackwell(96GiB) Standard_NC16_RTX6000Pro_1 16 64 1
NVIDIA RTX Pro 6000 Blackwell(96GiB) Standard_NC32_RTX6000Pro_1 32 128 1

메모

다중 GPU SKU(예: Standard_NC16_RTX6000Pro_2Standard_NC32_RTX6000Pro_2)는 카탈로그에 있지만 아직 일반 공급되지 않습니다.

시작하기 전 주의 사항:

GPU 사용 노드 풀을 만들려면 다음 요구 사항이 충족되는지 확인합니다.

  • 다중 랙 배포를 위한 Azure 로컬 클러스터가 배포되고 Azure Arc 등록됩니다. 자세한 내용은 다중 랙 배포 개요를 참조하세요.

  • Azure 로컬 클러스터의 사용자 지정 위치에 사용 가능한 NVIDIA RTX Pro 6000 GPU가 있는 물리적 컴퓨팅 노드가 있는지 확인합니다. Azure 로컬 관리자는 컴퓨팅 역할 노드의 리소스에 대한 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
    

    하나 이상의 컴퓨팅 노드가 nvidia.com/nvidia-rtx-pro-6000 값으로 0이 아닌 값을 보고해야 하며, 컴퓨팅 노드 전체의 합계는 2단계에서 요청할 계획인 --node-count 이상이어야 합니다. 노드가 표시되지 않거나 모든 값이 있는 0경우 계속하기 전에 관리자 또는 Microsoft 지원 문의하세요.

  • 최신 버전의 Azure CLI 및 확장을 설치합니다aksarc.

  • NVIDIA 소프트웨어에 대한 아웃바운드 액세스를 사용하도록 계속하기 전에 테넌트 프록시 또는 논리 네트워크 연결을 구성합니다. BYO 프록시 지침은 Azure 로컬 다중 랙에서 AKS에 대한 BYO 프록시 추가 방법을 참조하세요.

  • 클러스터를 만들 때 SSH 키를 사용하여 AKS Arc 클러스터를 만들고 이러한 SSH 키에 액세스할 수 있는지 확인합니다. 이 문서의 3단계와 4단계에서는 NVIDIA 드라이버 및 컨테이너 도구 키트를 설치하기 위해 각 GPU 작업자 VM에 대한 SSH 액세스 권한이 필요하며, SSH 키는 클러스터를 만드는 동안에만 구성할 수 있습니다.

메모

GPU가 pod 사양에서 nvidia.com/gpu로 스케줄 가능하도록 NVIDIA 드라이버, NVIDIA Container Toolkit 및 NVIDIA Kubernetes 디바이스 플러그인을 수동으로 설치해야 합니다. 이 문서의 3~5단계에서는 각 구성 요소를 하나씩 설명합니다. 6단계에서는 Pod 워크로드로 엔드투엔드 검증을 수행합니다.

1단계: 사용 가능한 GPU 사용 VM 크기 나열

Azure 로컬 클러스터를 배포한 후 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 노드 풀을 추가합니다. 다음 예제에서는 VM의 Standard_NC16_RTX6000Pro_1 2노드 풀(노드당 하나의 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 로컬 플랫폼은 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
    

    메모

    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-ossms-non-oss 리포지토리만 구성됩니다. 패키지는 cuda-open 한 번 추가해야 하는 별도의 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 nvidia이(가) Module 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 컨테이너 도구 키트 설치

드라이버는 작업자 VM의 호스트 OS에서 GPU를 사용할 수 있게 하지만, 컨테이너가 /dev/nvidia* 및 이에 대응하는 사용자 공간 라이브러리(libcuda.so, libnvidia-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를 nvidia.com/gpu 리소스로 AKS Arc 클러스터의 스케줄러에 알립니다. 그것이 없으면 nvidia.com/gpu: 1를 요청하는 Pod는 Pending 상태로 유지됩니다.

다음 매니페스트는 MICROSOFT MCR(Container Registry)에 미러된 디바이스 플러그 인 이미지를 사용합니다. GitHub 또는 엔비디아 웹 사이트에서도 찾을 수 있습니다.

  1. az connectedk8s proxy를 사용하여 AKS Arc 클러스터에 연결합니다. 단계별 지침은 클러스터에 연결을 참조하세요. --file 옵션을 사용하여 전용 kubeconfig(예: ./<aks cluster name>.kubeconfig)를 생성하고, 프록시를 계속 실행한 상태로 둔 다음, 나머지 단계를 위해 두 번째 터미널에서 kubectl가 해당 kubeconfig를 가리키도록 설정합니다.

  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 사용 Pod 워크로드 실행

GPU가 Kubernetes Pod에서 엔드투엔드로 사용할 수 있는지 확인하려면 작은 CUDA 워크로드를 배포하고 GPU에 대해 완료되었는지 확인합니다. 이 단계에서는 4단계와 5단계가 완료되었다고 가정합니다(노드에 컨테이너 도구 키트가 설치되고 nvidia.com/gpu 보급됨).

메모

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. Pod가 시작되고 실행이 완료되었으며 GPU가 할당되었는지 확인합니다.

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

    이전 명령은 할당된 GPU 하나를 표시해야 합니다.

    nvidia.com/gpu: 1
    nvidia.com/gpu: 1
    
  6. Pod의 로그 파일을 확인하여 테스트가 통과되었는지 확인합니다.

    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
    

다음 단계