빠른 시작: Azure CLI 사용하여 GPU Linux 기반 AKS(Azure Kubernetes Service) 클러스터 만들기

AKS(Azure Kubernetes Service) 클러스터를 신속하게 배포하고 관리하는 데 사용할 수 있는 관리되는 Kubernetes 서비스입니다. 이 빠른 시작에서 다음을 수행하는 방법을 알아봅니다.

  • Azure CLI 사용하여 AKS 클러스터를 배포합니다.
  • 관리되는 GPU 노드를 사용하도록 설정된 Linux 기반 GPU 노드 풀을 추가합니다.
  • 예약을 위해 AKS가 GPU 소프트웨어 스택을 설치하고 구성했는지 확인합니다.

완전 관리형 GPU 노드는 미리 보기 기능입니다. 관리되는 GPU 노드를 사용하도록 설정하면 AKS는 NVIDIA GPU 드라이버, NVIDIA Kubernetes 디바이스 플러그 인, DCGM(Data Center GPU Manager) 메트릭 내보내기 및 GPU 노드 풀에 대한 GPU 상태 모니터링 구성 요소를 설치하고 관리합니다. 또한 관리되는 GPU 노드는 Azure Managed Prometheus에서 수집을 위한 실시간 GPU 메트릭과 Prometheus용 Azure Monitor 관리되는 서비스를 통합합니다. 자세한 내용은 Azure Kubernetes Service(AKS)에서 완전 관리형 GPU 노드 풀 만들기(미리 보기) 및 Azure Kubernetes Service(AKS)의 GPU 관찰 가능성을 참조하세요.

비고

이 문서에는 평가 목적으로만 클러스터를 배포하는 단계가 포함되어 있습니다. 프로덕션 지원 클러스터를 배포하기 전에 기본 참조 아키텍처 를 숙지하여 비즈니스 요구 사항에 맞게 조정하는 방법을 고려합니다.

Important

AKS 미리 보기 기능은 셀프 서비스에서 사용할 수 있습니다(옵트인 방식). 미리 보기는 "있는 그대로" 및 "사용 가능한 상태로" 제공되며 서비스 수준 계약 및 제한적 보증에서 제외됩니다. AKS 미리 보기의 일부는 고객 지원팀에서 최선을 다해 지원합니다. 따라서 이러한 기능은 프로덕션 용도로 사용할 수 없습니다. 자세한 내용은 다음 지원 문서를 참조하세요.

시작하기 전 주의 사항:

이 빠른 시작에서는 Kubernetes 기본 개념을 이해하고 있다고 가정합니다. 자세한 내용은 AKS(Azure Kubernetes Service)의 Kubernetes 핵심 개념을 참조하세요.

  • Azure 계정이 없는 경우 시작하기 전에 체험 계정을 만듭니다.

aks-preview CLI 확장 설치

aks-preview az extension add 명령을 사용하여 CLI 확장을 설치합니다.

az extension add --name aks-preview

az extension update 명령을 사용하여 최신 버전이 있는지 확인하도록 확장을 업데이트합니다.

az extension update --name aks-preview

미리 보기 기능 등록

ManagedGPUExperiencePreview az feature register 명령을 사용하여 구독에 기능 플래그를 등록합니다.

az feature register --namespace Microsoft.ContainerService --name ManagedGPUExperiencePreview

상태가 Registered로 표시되는 데 몇 분 정도 걸립니다. az feature show 명령을 사용하여 등록 상태를 확인합니다.

az feature show --namespace Microsoft.ContainerService --name ManagedGPUExperiencePreview --query properties.state

상태가 등록됨으로 표시되면 az provider register 명령을 사용하여 리소스 공급자의 Microsoft.ContainerService 등록을 새로 고칩니다.

az provider register --namespace Microsoft.ContainerService

환경 변수 정의

이 빠른 시작 전체에서 사용할 다음 환경 변수를 정의합니다.

export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
export RESOURCE_GROUP="myAKSResourceGroup$RANDOM_STRING"
export CLUSTER_NAME="myAKSCluster$RANDOM_STRING"
export GPU_NP="gpunp"
export GPU_VM_SIZE="Standard_NC4as_T4_v3"
export LOCATION="westus"

변수는 RANDOM_STRING 임의의 10자리 문자열을 저장합니다. RESOURCE_GROUP 변수 값과 CLUSTER_NAME 변수 값이 RANDOM_STRING 값과 연결되어 고유한 이름을 만듭니다. 변수는 GPU_NP 관리되는 GPU 노드 풀의 이름을 저장합니다. 변수는 GPU_VM_SIZE 노드 풀에 대한 GPU 지원 VM 크기를 저장합니다. 변수의 LOCATION 값은 westus입니다. 이러한 변수 값을 사용하거나 직접 만들 수 있습니다. echo 명령을 사용하여 echo $RANDOM_STRING와 같은 변수 값을 확인합니다.

리소스 그룹 만들기

Azure 리소스 그룹은 Azure 리소스를 배포하고 관리하기 위한 논리 그룹입니다. 리소스 그룹을 만들 때 위치를 지정합니다. 이 위치는 리소스 그룹 메타데이터가 저장되는 위치이며 리소스를 만드는 동안 다른 지역을 지정하지 않으면 리소스가 Azure 실행됩니다.

az group create 명령을 사용하여 리소스 그룹을 만듭니다.

az group create --name $RESOURCE_GROUP --location $LOCATION

다음 예제에서는 결과를 보여줍니다.

{
  "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/myAKSResourceGroup<randomStringValue>",
  "location": "westus",
  "managedBy": null,
  "name": "myAKSResourceGroup<randomStringValue>",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

AKS 클러스터 만들기

az aks create 명령을 사용하여 AKS 클러스터를 만듭니다. 다음 예제에서는 하나의 시스템 노드가 있는 클러스터를 만들고 시스템 할당 관리 ID를 사용하도록 설정합니다.

az aks create \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --node-count 1 \
  --generate-ssh-keys

새 클러스터를 만들면 AKS는 AKS 리소스를 저장할 두 번째 리소스 그룹을 자동으로 만듭니다. 자세한 내용은 AKS를 통해 두 개의 리소스 그룹이 생성되는 이유는 무엇인가요?를 참조하세요.

이 예제의 클러스터는 시간과 리소스를 절약하기 위해 노드 수를 1로 지정합니다. 프로덕션 환경에서는 노드 수가 3개 이상인 노드 수를 사용합니다. az aks create 노드 수를 지정하지 않으면 이 명령은 기본적으로 3개의 노드로 설정됩니다.

관리되는 GPU 노드 풀 추가

az aks nodepool add 명령을 사용하여 Linux 기반 관리 GPU 노드 풀을 클러스터에 추가합니다. 매개 변수는 --enable-managed-gpu=true 노드 풀에 NVIDIA GPU 드라이버, NVIDIA Kubernetes 디바이스 플러그 인, DCGM 메트릭 내보내기 및 GPU 상태 모니터링 구성 요소를 설치하고 관리하도록 AKS를 구성합니다.

다음 예제에서는 기본 Ubuntu Linux 운영 체제를 사용하여 관리되는 GPU 노드 풀을 추가합니다.

az aks nodepool add \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name $GPU_NP \
  --node-count 1 \
  --node-vm-size $GPU_VM_SIZE \
  --node-taints sku=gpu:NoSchedule \
  --enable-managed-gpu=true

--node-taints sku=gpu:NoSchedule 매개변수는 워크로드에 일치하는 톨러레이션이 포함되지 않는 한, GPU가 아닌 워크로드가 GPU 노드 풀에 배치되지 않도록 합니다.

노드 풀을 만든 후 az aks nodepool show 명령을 사용하여 관리되는 GPU 프로필이 사용하도록 설정되어 있는지 확인합니다.

az aks nodepool show \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name $GPU_NP \
  --query "{Name:name, Mode:mode, VmSize:vmSize, Taints:nodeTaints, GpuProfile:gpuProfile}"

출력에는 다음 값이 포함되어야 합니다.

{
  "GpuProfile": {
    "driver": "Install",
    "driverType": "",
    "nvidia": {
      "managementMode": "Managed",
      "migStrategy": null
    }
  },
  "Mode": "User",
  "Name": "gpunp",
  "Taints": [
    "sku=gpu:NoSchedule"
  ],
  "VmSize": "Standard_NC4as_T4_v3"
}

클러스터에 연결

Kubernetes 클러스터를 관리하려면 Kubernetes 명령줄 클라이언트인 kubectl을 사용합니다. Azure Cloud Shell을 사용하는 경우 kubectl이 이미 설치되어 있습니다. kubectl을(를) 로컬로 설치하려면 az aks install-cli 명령을 사용합니다.

  1. az aks get-credentials 명령을 사용하여 Kubernetes 클러스터에 연결하도록 구성 kubectl 합니다. 이 명령은 자격 증명을 다운로드하고 이를 사용하도록 Kubernetes CLI를 구성합니다.

    az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
    
  2. kubectl get 명령을 사용하여 클러스터에 대한 연결을 확인합니다. 이 명령은 클러스터 노드 목록을 반환하고 각 노드에 대한 노드 풀을 표시합니다.

    kubectl get nodes -L kubernetes.azure.com/agentpool,kubernetes.azure.com/mode
    
    NAME                                STATUS   ROLES    AGE     VERSION   AGENTPOOL   MODE
    aks-nodepool1-123456789-vmss000000  Ready    <none>   20m     v1.34.4   nodepool1   system
    aks-gpunp-123456789-vmss000000      Ready    <none>   5m36s   v1.34.4   gpunp       user
    
  3. Kubernetes가 관리되는 GPU 노드 풀에서 GPU 워크로드를 예약할 수 있는지 확인합니다.

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

    출력에는 관리되는 GPU 노드 풀의 각 노드에 대해 할당 가능한 GPU 수가 표시됩니다.

    aks-gpunp-123456789-vmss000000  1
    

GPU 메트릭 수집 활성화

관리되는 GPU 노드 풀에는 DCGM 메트릭 내보내기가 포함됩니다. GPU 메트릭을 Azure Managed Prometheus로 수집하려면 먼저 AKS 클러스터에서 prometheus에 Azure Monitor 관리되는 서비스를 사용하도록 설정합니다. 그런 다음 Azure Monitor 에이전트에서 스크래핑 프로필을 사용하도록 설정하는 dcgmexporter ConfigMap을 만듭니다.

cat <<EOF | kubectl create -f -
kind: ConfigMap
apiVersion: v1
data:
  schema-version:
    v1
  config-version:
    ver1
  default-scrape-settings-enabled: |-
    dcgmexporter = true
metadata:
  name: ama-metrics-settings-configmap
  namespace: kube-system
EOF

이 ConfigMap을 적용하면 클러스터의 모든 기존 및 새 NVIDIA GPU 노드 풀이 자동으로 스크래핑됩니다. Azure Managed Grafana GPU 메트릭을 보려면 AKS(Azure Kubernetes Service) GPU 관찰 가능성을 참조하세요.

애플리케이션 배포

GPU 워크로드를 배포하여 관리되는 GPU 노드 풀이 실제 애플리케이션을 실행할 수 있음을 확인합니다. 이 예제에서는 OpenAI 호환 API를 통해 작은 오픈 소스 큰 언어 모델(Llama 3.2 1B)을 제공하는 Ollama를 실행합니다. Ollama는 이 빠른 시작에서 사용하는 Standard_NC4as_T4_v3 노드 풀의 NVIDIA T4 GPU를 지원하는 llama.cpp를 기반으로 합니다.

다음 매니페스트는 Deployment와 Service를 생성합니다. Deployment는 GPU 하나(nvidia.com/gpu: 1)를 요청하고, sku=gpu:NoSchedule 테인트에 대한 톨러레이션을 포함하며, 노드 선택기를 사용해 관리형 GPU 노드 풀을 대상으로 합니다. 컨테이너가 시작되면 Ollama 서버를 시작하고 llama3.2:1b 모델을 가져와 Pod가 요청을 처리할 준비를 마칩니다.

다음 명령을 사용하여 애플리케이션을 배포합니다.

cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ollama
  labels:
    app: ollama
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ollama
  template:
    metadata:
      labels:
        app: ollama
    spec:
      # Schedule onto the managed GPU node pool created in this quickstart.
      nodeSelector:
        kubernetes.azure.com/agentpool: gpunp
      # Tolerate the GPU node pool taint (sku=gpu:NoSchedule).
      tolerations:
        - key: "sku"
          operator: "Equal"
          value: "gpu"
          effect: "NoSchedule"
      containers:
        - name: ollama
          image: ollama/ollama:0.30.10
          ports:
            - name: http
              containerPort: 11434
          env:
            # Listen on all interfaces so the Service and kubelet probes can reach it.
            - name: OLLAMA_HOST
              value: "0.0.0.0:11434"
            # Model to pull and serve on startup. Fits comfortably on a 16-GB T4.
            - name: MODEL
              value: "llama3.2:1b"
          # Start the server, wait until it's ready, and then pull the model so the
          # pod is self-contained (no manual "ollama pull" step required).
          command: ["/bin/sh", "-c"]
          args:
            - |
              ollama serve &
              pid=$!
              echo "Waiting for the Ollama server to be ready..."
              until ollama list >/dev/null 2>&1; do sleep 2; done
              echo "Server ready. Pulling model: $MODEL"
              ollama pull "$MODEL" || echo "WARN: pull failed; run 'kubectl exec deploy/ollama -- ollama pull $MODEL' manually"
              echo "Model $MODEL is ready to serve."
              wait $pid
          resources:
            requests:
              cpu: "1"
              memory: 4Gi
            limits:
              cpu: "4"
              memory: 16Gi
              nvidia.com/gpu: 1
          startupProbe:
            httpGet:
              path: /api/tags
              port: http
            periodSeconds: 5
            failureThreshold: 60
          readinessProbe:
            httpGet:
              path: /api/tags
              port: http
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /
              port: http
            periodSeconds: 20
          volumeMounts:
            - name: ollama-data
              mountPath: /root/.ollama
      volumes:
        - name: ollama-data
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: ollama
  labels:
    app: ollama
spec:
  type: ClusterIP
  selector:
    app: ollama
  ports:
    - name: http
      port: 11434
      targetPort: http
EOF

비고

이 매니페스트는 노드 풀을 gpunp 대상으로 합니다. 변수에 GPU_NP 다른 값을 사용한 경우 매니페스트를 적용하기 전에 일치하도록 노드 선택기 값을 업데이트 kubernetes.azure.com/agentpool 합니다.

kubectl 롤아웃 상태 명령을 사용하여 배포가 준비되어 있는지 확인합니다. 초기 모델 다운로드에는 몇 분 정도 걸릴 수 있습니다.

kubectl rollout status deployment/ollama --timeout=600s

kubectl get 명령을 사용하여 관리되는 GPU 노드 풀에서 Pod가 실행되고 있는지 확인합니다.

kubectl get pods -l app=ollama -o wide

출력 결과에는 gpunp 노드 풀의 노드에서 실행 중인 Pod가 표시되어야 합니다.

NAME                      READY   STATUS    RESTARTS   AGE   IP            NODE                            NOMINATED NODE   READINESS GATES
ollama-5b8f6c9d4f-2xq7p   1/1     Running   0          5m    10.244.1.10   aks-gpunp-12345678-vmss000000   <none>           <none>

애플리케이션 테스트

kubectl port-forward 명령을 사용하여 로컬 포트를 Service로 전달합니다. 이 명령을 계속 실행하고 나머지 단계에 대해 두 번째 터미널을 엽니다.

kubectl port-forward svc/ollama 11434:11434

두 번째 터미널에서 OpenAI 호환 채팅 완료 엔드포인트를 사용하여 모델에 프롬프트를 보냅니다.

curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.2:1b",
    "messages": [{"role": "user", "content": "In one sentence, what is Azure Kubernetes Service?"}]
  }'

모델은 생성된 답변이 포함된 JSON 응답을 반환합니다. 이 응답은 워크로드가 관리되는 GPU 노드 풀에서 유추를 제공하고 있음을 확인합니다.

명령을 사용하여 모델이 GPU에 로드되어 있는지 확인합니다 ollama ps . PROCESSOR 열에는 모델이 T4에서 실행될 때 100% GPU이(가) 표시됩니다.

kubectl exec deploy/ollama -- ollama ps
NAME          ID              SIZE      PROCESSOR    CONTEXT   UNTIL
llama3.2:1b   baf6a787fdff    1.5 GB    100% GPU     4096      4 minutes from now

명령을 사용하여 Pod 내부에서 직접 GPU를 볼 수도 있습니다 nvidia-smi .

kubectl exec deploy/ollama -- nvidia-smi

테스트를 마치면 해당 터미널에서 kubectl port-forwardCtrl+C 를 선택하여 프로세스를 중지합니다. 다음 단계에서 클러스터를 삭제하면 애플리케이션이 제거됩니다.

클러스터 삭제

AKS 자습서를 수행할 계획이 없는 경우 불필요한 리소스를 정리하여 Azure 청구 요금을 방지합니다. az group delete 명령을 사용하여 리소스 그룹, 컨테이너 서비스 및 모든 관련 리소스를 제거할 수 있습니다.

az group delete --name $RESOURCE_GROUP --no-wait --yes

이 빠른 시작에서 사용되는 기본 ID 옵션인 시스템 할당 관리 ID를 사용하여 AKS 클러스터를 만들었습니다. 플랫폼이 이 ID를 관리하므로 수동으로 제거할 필요가 없습니다.

다음 단계

이 빠른 시작에서는 Kubernetes 클러스터를 배포한 다음 Linux 기반 관리형 GPU 노드 풀을 추가했습니다. 관리되는 GPU 노드 및 GPU 메트릭에 대한 자세한 내용은 다음 문서를 참조하세요.

AKS에 대해 자세히 알아보고 전체 코드 배포 예제를 수행하려면 Kubernetes 클러스터 자습서를 계속 진행하세요.