PyTorch, Ray, Google Kubernetes Engine (GKE)을 사용하여 모델 학습

이 가이드에서는 Ray, PyTorch, Ray Operator 부가기능을 사용하여 Google Kubernetes Engine(GKE)에서 모델을 학습하는 방법을 보여줍니다.

Ray 정보

Ray는 AI/ML 애플리케이션을 위한 확장 가능한 오픈소스 컴퓨팅 프레임워크입니다. Ray Train은 분산형 모델 학습 및 미세 조정을 위해 설계된 Ray 내의 구성요소입니다. Ray Train API를 사용하여 여러 머신에서 학습을 확장하고 PyTorch와 같은 머신러닝 라이브러리와 통합할 수 있습니다.

RayCluster 또는 RayJob 리소스를 사용하여 Ray 학습 작업을 배포할 수 있습니다. 다음과 같은 이유로 프로덕션에 Ray 작업을 배포할 때는 RayJob 리소스를 사용해야 합니다.

  • RayJob 리소스는 작업이 완료될 때 자동으로 삭제될 수 있는 임시 Ray 클러스터를 만듭니다.
  • RayJob 리소스는 탄력적인 작업 실행을 위한 재시도 정책을 지원합니다.
  • 익숙한 Kubernetes API 패턴을 사용하여 Ray 작업을 관리할 수 있습니다.

목표

이 가이드는 Ray를 사용하여 모델을 서빙하기 위해 Kubernetes 컨테이너 조정 기능을 사용하는 데 관심이 있는 생성형 AI 고객, GKE의 신규 또는 기존 사용자, ML 엔지니어, MLOps(DevOps) 엔지니어, 플랫폼 관리자를 대상으로 합니다.

  • GKE 클러스터 만들기
  • RayCluster 커스텀 리소스를 사용하여 Ray 클러스터를 만듭니다.
  • Ray 작업을 사용하여 모델을 학습합니다.
  • RayJob 커스텀 리소스를 사용하여 Ray 작업을 배포합니다.

비용

이 문서에서는 비용이 청구될 수 있는 Google Cloud구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.

Google Cloud 신규 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

Cloud Shell에는 kubectlgcloud CLI 등 이 튜토리얼에 필요한 소프트웨어가 사전 설치되어 있습니다. Cloud Shell을 사용하지 않는 경우에는 gcloud CLI를 설치해야 합니다.

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud CLI를 설치합니다.

  3. 외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.

  4. gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.

    gcloud init
  5. Google Cloud 프로젝트를 만들거나 선택합니다.

    프로젝트를 선택하거나 만드는 데 필요한 역할

    • 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
    • 프로젝트 만들기: 프로젝트를 만들려면 resourcemanager.projects.create 권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 생성한 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.

  6. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  7. GKE API를 사용 설정합니다.

    API 사용 설정에 필요한 역할

    API를 사용 설정하려면 serviceusage.services.enable 권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기

    gcloud services enable container.googleapis.com
  8. Google Cloud CLI를 설치합니다.

  9. 외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.

  10. gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.

    gcloud init
  11. Google Cloud 프로젝트를 만들거나 선택합니다.

    프로젝트를 선택하거나 만드는 데 필요한 역할

    • 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
    • 프로젝트 만들기: 프로젝트를 만들려면 resourcemanager.projects.create 권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 생성한 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.

  12. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  13. GKE API를 사용 설정합니다.

    API 사용 설정에 필요한 역할

    API를 사용 설정하려면 serviceusage.services.enable 권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기

    gcloud services enable container.googleapis.com
  14. 사용자 계정에 역할을 부여합니다. 다음 IAM 역할마다 다음 명령어를 1회 실행합니다. roles/container.clusterAdmin, roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    다음을 바꿉니다.

    • PROJECT_ID: 프로젝트 ID입니다.
    • USER_IDENTIFIER: 사용자 계정의 식별자입니다. 예를 들면 myemail@example.com입니다.
    • ROLE: 사용자 계정에 부여하는 IAM 역할입니다.

개발 환경 준비

환경을 준비하려면 다음 단계를 수행합니다.

  1. Google Cloud 콘솔에서 Cloud Shell 세션을 시작합니다. Google Cloud 콘솔에서 Cloud Shell 활성화 아이콘 Cloud Shell 활성화를 클릭합니다. 그러면 Google Cloud 콘솔 하단 창에서 세션이 실행됩니다.

  2. 환경 변수를 설정합니다.

    export PROJECT_ID=PROJECT_ID
    export CLUSTER_NAME=ray-cluster
    export COMPUTE_REGION=us-central1
    export COMPUTE_ZONE=us-central1-c
    export CLUSTER_VERSION=CLUSTER_VERSION
    export TUTORIAL_HOME=`pwd`
    

    다음을 바꿉니다.

    • PROJECT_ID: Google Cloud프로젝트 ID입니다.
    • CLUSTER_VERSION: 사용할 GKE 버전입니다. 1.30.1 이상이어야 합니다.
  3. GitHub 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. 작업 디렉터리로 변경합니다.

    cd kubernetes-engine-samples/ai-ml/gke-ray/raytrain/pytorch-mnist
    
  5. Python 가상 환경을 만듭니다.

    python -m venv myenv && \
    source myenv/bin/activate
    
  6. Ray를 설치합니다.

GKE 클러스터 만들기

Autopilot 또는 표준 GKE 클러스터를 만듭니다.

Autopilot

Autopilot 클러스터를 만듭니다.

gcloud container clusters create-auto ${CLUSTER_NAME}  \
    --enable-ray-operator \
    --cluster-version=${CLUSTER_VERSION} \
    --location=${COMPUTE_REGION}

표준

표준 클러스터 만들기

gcloud container clusters create ${CLUSTER_NAME} \
    --addons=RayOperator \
    --cluster-version=${CLUSTER_VERSION}  \
    --machine-type=e2-standard-8 \
    --location=${COMPUTE_ZONE} \
    --num-nodes=4

RayCluster 리소스 배포

클러스터에 RayCluster 리소스를 배포합니다.

  1. 다음 매니페스트를 검토합니다.

    apiVersion: ray.io/v1
    kind: RayCluster
    metadata:
      name: pytorch-mnist-cluster
    spec:
      rayVersion: '2.37.0'
      headGroupSpec:
        rayStartParams:
          dashboard-host: '0.0.0.0'
        template:
          metadata:
          spec:
            containers:
            - name: ray-head
              image: rayproject/ray:2.37.0
              ports:
              - containerPort: 6379
                name: gcs
              - containerPort: 8265
                name: dashboard
              - containerPort: 10001
                name: client
              resources:
                limits:
                  cpu: "2"
                  ephemeral-storage: "9Gi"
                  memory: "4Gi"
                requests:
                  cpu: "2"
                  ephemeral-storage: "9Gi"
                  memory: "4Gi"
      workerGroupSpecs:
      - replicas: 4
        minReplicas: 1
        maxReplicas: 5
        groupName: worker-group
        rayStartParams: {}
        template:
          spec:
            containers:
            - name: ray-worker
              image: rayproject/ray:2.37.0
              resources:
                limits:
                  cpu: "4"
                  ephemeral-storage: "9Gi"
                  memory: "8Gi"
                requests:
                  cpu: "4"
                  ephemeral-storage: "9Gi"
                  memory: "8Gi"

    이 매니페스트는 RayCluster 커스텀 리소스를 설명합니다.

  2. 매니페스트를 GKE 클러스터에 적용합니다.

    kubectl apply -f ray-cluster.yaml
    
  3. RayCluster 리소스가 준비되었는지 확인합니다.

    kubectl get raycluster
    

    출력은 다음과 비슷합니다.

    NAME                    DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
    pytorch-mnist-cluster   2                 2                   6      20Gi     0      ready    63s
    

    이 출력에서 STATUS 열의 ready는 RayCluster 리소스가 준비되었다는 것을 나타냅니다.

RayCluster 리소스에 연결

RayCluster 리소스에 연결하여 Ray 작업을 제출합니다.

  1. GKE에서 RayCluster 서비스가 생성되었는지 확인합니다.

    kubectl get svc pytorch-mnist-cluster-head-svc
    

    출력은 다음과 비슷합니다.

    NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                AGE
    pytorch-mnist-cluster-head-svc   ClusterIP   34.118.238.247   <none>        10001/TCP,8265/TCP,6379/TCP,8080/TCP   109s
    
  2. Ray 헤드에 대한 포트 전달 세션을 설정합니다.

    kubectl port-forward svc/pytorch-mnist-cluster-head-svc 8265:8265 2>&1 >/dev/null &
    
  3. Ray 클라이언트가 localhost를 사용하여 Ray 클러스터에 연결할 수 있는지 확인합니다.

    ray list nodes --address http://localhost:8265
    

    출력은 다음과 비슷합니다.

    Stats:
    ------------------------------
    Total: 3
    
    Table:
    ------------------------------
        NODE_ID                                                   NODE_IP     IS_HEAD_NODE    STATE    NODE_NAME    RESOURCES_TOTAL                 LABELS
    0  1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2  10.28.1.21  False           ALIVE    10.28.1.21   CPU: 2.0                        ray.io/node_id: 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2
    # Several lines of output omitted
    

모델 학습

Fashion MNIST 데이터 세트를 사용하여 PyTorch 모델을 학습합니다.

  1. Ray 작업을 제출하고 작업이 완료될 때까지 기다립니다.

    ray job submit --submission-id pytorch-mnist-job --working-dir . --runtime-env-json='{"pip": ["torch", "torchvision"], "excludes": ["myenv"]}' --address http://localhost:8265 -- python train.py
    

    출력은 다음과 비슷합니다.

    Job submission server address: http://localhost:8265
    
    --------------------------------------------
    Job 'pytorch-mnist-job' submitted successfully
    --------------------------------------------
    
    Next steps
      Query the logs of the job:
        ray job logs pytorch-mnist-job
      Query the status of the job:
        ray job status pytorch-mnist-job
      Request the job to be stopped:
        ray job stop pytorch-mnist-job
    
    Handling connection for 8265
    Tailing logs until the job exits (disable with --no-wait):
    ...
    ...
    
  2. 작업 상태를 확인합니다.

    ray job status pytorch-mnist
    

    출력은 다음과 비슷합니다.

    Job submission server address: http://localhost:8265
    Status for job 'pytorch-mnist-job': RUNNING
    Status message: Job is currently running.
    

    Status for jobCOMPLETE가 될 때까지 기다립니다. 이 작업은 15분 이상 걸릴 수 있습니다.

  3. Ray 작업 로그 보기

    ray job logs pytorch-mnist
    

    출력은 다음과 비슷합니다.

    Training started with configuration:
    ╭─────────────────────────────────────────────────╮
    │ Training config                                  │
    ├──────────────────────────────────────────────────┤
    │ train_loop_config/batch_size_per_worker       8  │
    │ train_loop_config/epochs                     10  │
    │ train_loop_config/lr                      0.001  │
    ╰─────────────────────────────────────────────────╯
    
    # Several lines omitted
    
    Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
    ╭───────────────────────────────╮
    │ Training result                │
    ├────────────────────────────────┤
    │ checkpoint_dir_name            │
    │ time_this_iter_s      25.7394  │
    │ time_total_s          351.233  │
    │ training_iteration         10  │
    │ accuracy               0.8656  │
    │ loss                  0.37827  │
    ╰───────────────────────────────╯
    
    # Several lines omitted
    -------------------------------
    Job 'pytorch-mnist' succeeded
    -------------------------------
    

RayJob 배포

RayJob 커스텀 리소스는 단일 Ray 작업 실행 중에 RayCluster 리소스의 수명 주기를 관리합니다.

  1. 다음 매니페스트를 검토합니다.

    apiVersion: ray.io/v1
    kind: RayJob
    metadata:
      name: pytorch-mnist-job
    spec:
      shutdownAfterJobFinishes: true
      entrypoint: python ai-ml/gke-ray/raytrain/pytorch-mnist/train.py
      runtimeEnvYAML: |
        pip:
          - torch
          - torchvision
        working_dir: "https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/archive/main.zip"
        env_vars:
          NUM_WORKERS: "4"
          CPUS_PER_WORKER: "2"
      rayClusterSpec:
        rayVersion: '2.37.0'
        headGroupSpec:
          rayStartParams: {}
          template:
            spec:
              containers:
                - name: ray-head
                  image: rayproject/ray:2.37.0
                  ports:
                    - containerPort: 6379
                      name: gcs-server
                    - containerPort: 8265
                      name: dashboard
                    - containerPort: 10001
                      name: client
                  resources:
                    limits:
                      cpu: "2"
                      ephemeral-storage: "9Gi"
                      memory: "4Gi"
                    requests:
                      cpu: "2"
                      ephemeral-storage: "9Gi"
                      memory: "4Gi"
        workerGroupSpecs:
          - replicas: 4
            minReplicas: 1
            maxReplicas: 5
            groupName: small-group
            rayStartParams: {}
            template:
              spec:
                containers:
                  - name: ray-worker
                    image: rayproject/ray:2.37.0
                    resources:
                      limits:
                        cpu: "4"
                        ephemeral-storage: "9Gi"
                        memory: "8Gi"
                      requests:
                        cpu: "4"
                        ephemeral-storage: "9Gi"
                        memory: "8Gi"

    이 매니페스트는 RayJob 커스텀 리소스를 설명합니다.

  2. 매니페스트를 GKE 클러스터에 적용합니다.

    kubectl apply -f ray-job.yaml
    
  3. RayJob 리소스가 실행 중인지 확인합니다.

    kubectl get rayjob
    

    출력은 다음과 비슷합니다.

    NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME   AGE
    pytorch-mnist-job   RUNNING      Running             2024-06-19T15:43:32Z              2m29s
    

    이 출력에서 DEPLOYMENT STATUS 열은 RayJob 리소스가 Running임을 나타냅니다.

  4. RayJob 리소스 상태를 확인합니다.

    kubectl logs -f -l job-name=pytorch-mnist-job
    

    출력은 다음과 비슷합니다.

    Training started with configuration:
    ╭─────────────────────────────────────────────────╮
    │ Training config                                  │
    ├──────────────────────────────────────────────────┤
    │ train_loop_config/batch_size_per_worker       8  │
    │ train_loop_config/epochs                     10  │
    │ train_loop_config/lr                      0.001  │
    ╰─────────────────────────────────────────────────╯
    
    # Several lines omitted
    
    Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
    ╭───────────────────────────────╮
    │ Training result                │
    ├────────────────────────────────┤
    │ checkpoint_dir_name            │
    │ time_this_iter_s      25.7394  │
    │ time_total_s          351.233  │
    │ training_iteration         10  │
    │ accuracy               0.8656  │
    │ loss                  0.37827  │
    ╰───────────────────────────────╯
    
    # Several lines omitted
    -------------------------------
    Job 'pytorch-mnist' succeeded
    -------------------------------
    
  5. Ray 작업이 완료되었는지 확인합니다.

    kubectl get rayjob
    

    출력은 다음과 비슷합니다.

    NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME               AGE
    pytorch-mnist-job   SUCCEEDED    Complete            2024-06-19T15:43:32Z   2024-06-19T15:51:12Z   9m6s
    

    이 출력에서 DEPLOYMENT STATUS 열은 RayJob 리소스가 Complete임을 나타냅니다.

Ray 워크로드 관찰

RayJob의 세부정보를 보려면 Google Cloud 콘솔에서 Kubernetes Engine > AI/ML > Jobs 섹션으로 이동합니다.

Google Cloud 콘솔에서 RayJobs 보기

삭제

프로젝트 삭제

    Google Cloud 프로젝트를 삭제합니다.

    gcloud projects delete PROJECT_ID

개별 리소스 삭제

기존 프로젝트를 사용한 경우 삭제하지 않으려면 개별 리소스를 삭제하면 됩니다. 클러스터를 삭제하려면 다음을 입력하세요.

gcloud container clusters delete ${CLUSTER_NAME}

다음 단계

  • Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항 살펴보기 Cloud 아키텍처 센터 살펴보기