AKS에서 Ray를 사용하여 LLM 학습

이 문서에서는 LLaMA-Factory와 분산 Ray Train을 사용해 viggo NLG 데이터 세트를 기반으로 Qwen2.5-7B-Instruct를 미세 조정하는 RayJob을 제출합니다. 이 작업은 각각 하나의 GPU로 4명의 작업자를 사용하고, Azure Blob Storage 학습 데이터를 읽고, 다운스트림 유추를 위해 학습된 LoRA 어댑터를 업로드합니다.

중요

오픈 소스 소프트웨어는 AKS 설명서와 샘플 전반에서 언급되어 있습니다. 배포하는 소프트웨어는 AKS 서비스 수준 계약, 제한된 보증 및 Azure 지원 제외됩니다. AKS와 함께 오픈 소스 기술을 사용하는 경우 각 커뮤니티 및 프로젝트 유지 관리자에서 사용할 수 있는 지원 옵션을 참조하여 계획을 개발합니다.

Microsoft는 AKS에 배포하는 오픈 소스 패키지를 빌드하는 역할을 담당합니다. 해당 책임에는 컨테이너 이미지의 이진 파일에 대한 제어와 함께 빌드, 스캔, 서명, 유효성 검사 및 핫픽스 프로세스의 완전한 소유권이 포함됩니다. 자세한 내용은 AKS의 취약성 관리 및 AKS 지원 범위를 참조하세요.

필수 조건

  • AKS에서 Ray 및 Kueue에 대한 인프라 배포에 따라 배포된 인프라입니다.
  • KUEue 큐는 AKS에서 Ray 워크로드에 대한 Kueue 큐 구성에 따라 구성됩니다.
  • 클러스터에서 사용할 수 있는 최소 4개의 A100 GPU(이 예제에서는 각각 하나의 GPU로 4명의 작업자를 사용).
  • Blob Storage llm-pipeline/data/ 에 업로드된 Viggo 데이터 세트(인프라 Terraform 모듈에서 자동으로 수행).
  • envsubst 설치됨(gettext Linux의 패키지, brew install gettext macOS).

환경 변수 설정

복제된 리포지토리에서 LLM 학습 예제로 이동하고 필요한 환경 변수를 구성합니다.

cd <path-to-cloned-repo>/AKS/examples/kueue-and-ray-on-aks/3-workloads/llm-training
export AZURE_STORAGE_ACCOUNT_NAME=$(terraform -chdir=../../1-infrastructure/terraform output -raw storage_account_name)
source env.example

참고

팀 큐(옵션 B)를 구성한 경우, source env.example를 실행하기 전에 export QUEUE_NAME=team-a 또는 export QUEUE_NAME=team-b을 설정합니다. 기본값 QUEUE_NAME=default 은 단일 큐 구성(옵션 A)에서만 작동합니다.

워크로드 제출

분산 학습 RayJob을 제출합니다.

./submit.sh

스크립트는 학습 스크립트에서 ConfigMap을 만들고, 4명의 GPU 작업자가 있는 매니페스트 템플릿을 envsubst렌더링하고, 적용합니다. Kueue는 구성된 큐에서 4개의 GPU를 사용할 수 있는 경우 작업을 인정합니다.

Tip

실행 ./submit.sh --dry-run 하여 클러스터에 적용하지 않고 렌더링된 매니페스트의 유효성을 검사합니다.

진행 상황 모니터링

새 셸을 사용 중인 경우 작업 이름을 찾아 export합니다:

export JOB_NAME=$(kubectl -n ray get rayjob --no-headers -o custom-columns=":metadata.name" | grep llm-training)

RayJob 상태와 Kueue 승인 여부를 확인합니다:

kubectl -n ray get rayjob ${JOB_NAME} -w
kubectl -n ray get workload -w

작업이 완료될 때 예상되는 출력:

NAME                      JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME               AGE
llm-training-xxxxxxxxxx   SUCCEEDED    Complete            2026-01-01T00:00:00Z   2026-01-01T00:19:00Z   19m
NAME                                   QUEUE     RESERVED IN     ADMITTED   FINISHED   AGE
rayjob-llm-training-xxxxxxxxxx-xxxxx   default   cluster-queue   True       True       19m

헤드 pod 로그의 끝부분을 확인합니다.

kubectl -n ray logs -f -l ray.io/cluster=$(kubectl -n ray get rayjob ${JOB_NAME} -o jsonpath='{.status.rayClusterName}') -c ray-head

결과 확인

LoRA 어댑터 업로드를 확인합니다.

az storage blob list -c llm-pipeline --prefix lora/ \
  --account-name ${AZURE_STORAGE_ACCOUNT_NAME} --auth-mode login -o table

예상 출력:

Name                                       Blob Type    Blob Tier    Length    Content Type
-----------------------------------------  -----------  -----------  --------  ------------------------
lora/latest.txt                            BlockBlob    Hot          86        application/octet-stream
lora/<job-name>/rng_state_3.pth            BlockBlob    Hot          14725     application/octet-stream

포인터가 latest.txt 작성되었는지 확인합니다(자동 검색을 위해 일괄 처리 유추 예제에서 사용됨).

az storage blob download -c llm-pipeline -n lora/latest.txt \
  --account-name ${AZURE_STORAGE_ACCOUNT_NAME} --auth-mode login

예상 출력:

azure://llm-pipeline@<storage-account>.blob.core.windows.net/lora/<job-name>

구성 참조

변수 Default Description
AZURE_STORAGE_ACCOUNT_NAME (필수) 모듈 1의 스토리지 계정
NUM_WORKERS 4 GPU 작업자 복제본(각각 4 x 1 GPU)
QUEUE_NAME default Kueue LocalQueue 이름
LLM_DATA_CONTAINER llm-pipeline 입력 데이터에 대한 Blob 컨테이너
LLM_LORA_CONTAINER llm-pipeline LoRA 업로드용 Blob 컨테이너
CONFIGMAP_NAME llm-training-scripts 학습 스크립트를 포함하는 ConfigMap의 이름

자원을 정리하세요

RayJob 및 해당 ConfigMap을 삭제합니다.

kubectl -n ray delete rayjob ${JOB_NAME}
kubectl -n ray delete configmap ${CONFIGMAP_NAME}

다음 단계