次の方法で共有


Azure Kubernetes Service (AKS) 上に Ray クラスターを構成してデプロイする

この記事では、KubeRay を使用して Azure Kubernetes Service (AKS) 上で Ray クラスターを構成してデプロイします。 また、Ray クラスターを使用して単純な機械学習モデルをトレーニングし、結果を Ray ダッシュボードに表示する方法についても説明します。

この記事では、AKS に Ray クラスターをデプロイする 2 つの方法について説明します。

  • 非対話型デプロイ: GitHub リポジトリの deploy.sh スクリプトを使用して、完全な Ray サンプルを非対話形式でデプロイします。
  • 手動デプロイ: 手動デプロイの手順に従って、Ray サンプルを AKS にデプロイします。

前提条件

Ray サンプルを非対話形式でデプロイする

完全な Ray サンプルを非対話形式でデプロイする場合は、GitHub リポジトリ (deploy.sh) にある https://github.com/Azure-Samples/aks-ray-sample スクリプトを使用できます。 このスクリプトによって、「Ray のデプロイ プロセス」セクションで説明されている手順が完了します。

  1. 次のコマンドを使用して、GitHub リポジトリをローカルにクローンし、リポジトリのルートに移動します。

    git clone https://github.com/Azure-Samples/aks-ray-sample
    cd aks-ray-sample
    
  2. 次のコマンドを使用して、完全なサンプルをデプロイします。

    chmod +x deploy.sh
    ./deploy.sh
    
  3. デプロイが完了したら、ログの出力と Azure portal のリソース グループを確認して、作成されたインフラストラクチャを確かめます。

Ray サンプルを手動でデプロイする

Fashion MNIST は、60,000 個の例からなるトレーニング セットと 10,000 個の例からなるテスト セットで構成される Zalando の記事画像のデータセットです。 各例は、10 個のクラスのラベルが関連付けられた 28 x 28 のグレースケール画像です。 このガイドでは、Ray クラスターを使用して、簡単な PyTorch モデルをこのデータセットでトレーニングします。

RayJob 仕様をデプロイする

モデルをトレーニングするには、プライベート AKS クラスターで実行されている KubeRay オペレーターに Ray Job 仕様を送信する必要があります。 Ray Job 仕様は、Docker イメージ、実行するコマンド、使用するワーカーの数など、ジョブの実行に必要なリソースを記述した YAML ファイルです。

Ray Job の説明を確認して、環境に合わせていくつかのフィールドを変更することが必要になる場合があります。

  • replicasworkerGroupSpecs セクションにある rayClusterSpec フィールドには、KubeRay によって Kubernetes クラスターにスケジュールされるワーカー ポッドの数を指定します。 各ワーカー ポッドには、"3 個の CPU" と "4 GB のメモリ" が必要です。 ヘッド ポッドには、"1 個の CPU" と "4 GB のメモリ" が必要です。 replicas フィールドを 2 に設定するには、ジョブの RayCluster の実装に使用するノード プールに "8 個の vCPU" が必要です。
  • NUM_WORKERSruntimeEnvYAML にある spec フィールドには、起動する Ray アクターの数を指定します。 各 Ray アクターは Kubernetes クラスター内のワーカー ポッドによって処理されなければならないため、このフィールドは replicas フィールドに等しいかそれより少ない必要があります。 この例では、NUM_WORKERS2 に設定します。これは replicas フィールドに一致します。
  • CPUS_PER_WORKER フィールドは、"各ワーカー ポッドに割り当てられた CPU の数から 1 を引いた値に等しいかそれより少なく" 設定する必要があります。 この例では、ワーカー ポッドあたりの CPU リソース要求は 3 であるため、CPUS_PER_WORKER2 に設定されます。

要約すると、PyTorch モデルのトレーニング ジョブを実行するには、ノード プールに合計 "8 個の vCPU" が必要です。 ユーザー ポッドをスケジュールできないようにシステム ノード プールにテイントを追加したので、Ray クラスターをホストするために、少なくとも "8 個の vCPU" を含む新しいノード プールを作成する必要があります。

  1. 次のコマンドを使用して、Ray Job 仕様ファイルをダウンロードします。

    curl -LO https://raw.githubusercontent.com/ray-project/kuberay/master/ray-operator/config/samples/pytorch-mnist/ray-job.pytorch-mnist.yaml
    
  2. Ray Job 仕様ファイルに必要な変更を加えます。

  3. kubectl apply コマンドを使用して、PyTorch モデルのトレーニング ジョブを起動します。

    kubectl apply -n kuberay -f ray-job.pytorch-mnist.yaml
    

RayJob のデプロイを検証する

  1. kubectl get pods コマンドを使用して、名前空間で 2 つのワーカー ポッドと 1 つのヘッド ポッドが実行されていることを確認します。

    kubectl get pods -n kuberay
    

    出力は次の出力例のようになります。

    NAME                                                      READY   STATUS    RESTARTS   AGE
    kuberay-operator-7d7998bcdb-9h8hx                         1/1     Running   0          3d2h
    pytorch-mnist-raycluster-s7xd9-worker-small-group-knpgl   1/1     Running   0          6m15s
    pytorch-mnist-raycluster-s7xd9-worker-small-group-p74cm   1/1     Running   0          6m15s
    rayjob-pytorch-mnist-fc959                                1/1     Running   0          5m35s
    rayjob-pytorch-mnist-raycluster-s7xd9-head-l24hn          1/1     Running   0          6m15s
    
  2. kubectl get コマンドを使用して、RayJob の状態を確認します。

    kubectl get rayjob -n kuberay
    

    出力は次の出力例のようになります。

    NAME                   JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME   AGE
    rayjob-pytorch-mnist   RUNNING      Running             2024-11-22T03:08:22Z              9m36s
    
  3. RayJob が完了するまで待ちます。 この処理には数分かかる場合があります。 JOB STATUSSUCCEEDED になったら、トレーニング ログを確認できます。 そのためには、kubectl get pods コマンドを使用して、RayJob を実行しているポッドの名前を最初に取得します。

    kubectl get pods -n kuberay
    

    出力には、次の出力例のように、rayjob-pytorch-mnist で始まる名前のポッドが表示されます。

    NAME                                                      READY   STATUS      RESTARTS   AGE
    kuberay-operator-7d7998bcdb-9h8hx                         1/1     Running     0          3d2h
    pytorch-mnist-raycluster-s7xd9-worker-small-group-knpgl   1/1     Running     0          14m
    pytorch-mnist-raycluster-s7xd9-worker-small-group-p74cm   1/1     Running     0          14m
    rayjob-pytorch-mnist-fc959                                0/1     Completed   0          13m
    rayjob-pytorch-mnist-raycluster-s7xd9-head-l24hn          1/1     Running     0          14m
    
  4. kubectl logs コマンドを使用して RayJob のログを表示します。 rayjob-pytorch-mnist-fc959 は、RayJob を実行しているポッドの名前に置き換えてください。

    kubectl logs -n kuberay rayjob-pytorch-mnist-fc959
    

    出力には、次の出力例のような、PyTorch モデルのトレーニング ログが表示されます。

    2024-11-21 19:09:04,986 INFO cli.py:39 -- Job submission server address: http://rayjob-pytorch-mnist-raycluster-s7xd9-head-svc.kuberay.svc.cluster.local:8265
    2024-11-21 19:09:05,712 SUCC cli.py:63 -- -------------------------------------------------------
    2024-11-21 19:09:05,713 SUCC cli.py:64 -- Job 'rayjob-pytorch-mnist-hndpx' submitted successfully
    2024-11-21 19:09:05,713 SUCC cli.py:65 -- -------------------------------------------------------
    2024-11-21 19:09:05,713 INFO cli.py:289 -- Next steps
    2024-11-21 19:09:05,713 INFO cli.py:290 -- Query the logs of the job:
    2024-11-21 19:09:05,713 INFO cli.py:292 -- ray job logs rayjob-pytorch-mnist-hndpx
    2024-11-21 19:09:05,713 INFO cli.py:294 -- Query the status of the job:
    ...
    
    View detailed results here: /home/ray/ray_results/TorchTrainer_2024-11-21_19-11-23
    To visualize your results with TensorBoard, run: `tensorboard --logdir /tmp/ray/session_2024-11-21_19-08-24_556164_1/artifacts/2024-11-21_19-11-24/TorchTrainer_2024-11-21_19-11-23/driver_artifacts`
    
    Training started with configuration:
    ╭─────────────────────────────────────────────────╮
    │ Training config                                 │
    ├─────────────────────────────────────────────────┤
    │ train_loop_config/batch_size_per_worker      16 │
    │ train_loop_config/epochs                     10 │
    │ train_loop_config/lr                      0.001 │
    ╰─────────────────────────────────────────────────╯
    (RayTrainWorker pid=1193, ip=10.244.4.193) Setting up process group for: env:// [rank=0, world_size=2]
    (TorchTrainer pid=1138, ip=10.244.4.193) Started distributed worker processes:
    (TorchTrainer pid=1138, ip=10.244.4.193) - (node_id=3ea81f12c0f73ebfbd5b46664e29ced00266e69355c699970e1d824b, ip=10.244.4.193, pid=1193) world_rank=0, local_rank=0, node_rank=0
    (TorchTrainer pid=1138, ip=10.244.4.193) - (node_id=2b00ea2b369c9d27de9596ce329daad1d24626b149975cf23cd10ea3, ip=10.244.1.42, pid=1341) world_rank=1, local_rank=0, node_rank=1
    (RayTrainWorker pid=1341, ip=10.244.1.42) Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz
    (RayTrainWorker pid=1193, ip=10.244.4.193) Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to /home/ray/data/FashionMNIST/raw/train-images-idx3-ubyte.gz
    (RayTrainWorker pid=1193, ip=10.244.4.193)
      0%|          | 0.00/26.4M [00:00<?, ?B/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
      0%|          | 65.5k/26.4M [00:00<01:13, 356kB/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    100%|██████████| 26.4M/26.4M [00:01<00:00, 18.9MB/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193) Extracting /home/ray/data/FashionMNIST/raw/train-images-idx3-ubyte.gz to /home/ray/data/FashionMNIST/raw
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    100%|██████████| 26.4M/26.4M [00:01<00:00, 18.7MB/s]
    ...
    Training finished iteration 1 at 2024-11-21 19:15:46. Total running time: 4min 22s
    ╭───────────────────────────────╮
    │ Training result               │
    ├───────────────────────────────┤
    │ checkpoint_dir_name           │
    │ time_this_iter_s        144.9 │
    │ time_total_s            144.9 │
    │ training_iteration          1 │
    │ accuracy                0.805 │
    │ loss                  0.52336 │
    ╰───────────────────────────────╯
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 0:  97%|█████████▋| 303/313 [00:01<00:00, 269.60it/s]
    Test Epoch 0: 100%|██████████| 313/313 [00:01<00:00, 267.14it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Train Epoch 1:   0%|          | 0/1875 [00:00<?, ?it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 0: 100%|██████████| 313/313 [00:01<00:00, 270.44it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 0: 100%|█████████▉| 1866/1875 [00:24<00:00, 82.49it/s] [repeated 35x across cluster]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Train Epoch 0: 100%|██████████| 1875/1875 [00:24<00:00, 77.99it/s]
    Train Epoch 0: 100%|██████████| 1875/1875 [00:24<00:00, 76.19it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 0:   0%|          | 0/313 [00:00<?, ?it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 0:  88%|████████▊ | 275/313 [00:01<00:00, 265.39it/s] [repeated 19x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:  19%|█▉        | 354/1875 [00:04<00:18, 82.66it/s] [repeated 80x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:   0%|          | 0/1875 [00:00<?, ?it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:  40%|████      | 757/1875 [00:09<00:13, 83.01it/s] [repeated 90x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:  62%|██████▏   | 1164/1875 [00:14<00:08, 83.39it/s] [repeated 92x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:  82%|████████▏ | 1533/1875 [00:19<00:05, 68.09it/s] [repeated 91x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 1:  91%|█████████▏| 1713/1875 [00:22<00:02, 70.20it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Train Epoch 1:  91%|█████████ | 1707/1875 [00:22<00:02, 70.04it/s] [repeated 47x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 1:   0%|          | 0/313 [00:00<?, ?it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 1:   8%|▊         | 24/313 [00:00<00:01, 237.98it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 1:  96%|█████████▋| 302/313 [00:01<00:00, 250.76it/s]
    Test Epoch 1: 100%|██████████| 313/313 [00:01<00:00, 262.94it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Train Epoch 2:   0%|          | 0/1875 [00:00<?, ?it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 1:  92%|█████████▏| 289/313 [00:01<00:00, 222.57it/s]
    
    Training finished iteration 2 at 2024-11-21 19:16:12. Total running time: 4min 48s
    ╭───────────────────────────────╮
    │ Training result               │
    ├───────────────────────────────┤
    │ checkpoint_dir_name           │
    │ time_this_iter_s       25.975 │
    │ time_total_s          170.875 │
    │ training_iteration          2 │
    │ accuracy                0.828 │
    │ loss                  0.45946 │
    ╰───────────────────────────────╯
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 1: 100%|██████████| 313/313 [00:01<00:00, 226.04it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Train Epoch 1: 100%|██████████| 1875/1875 [00:24<00:00, 76.24it/s] [repeated 45x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 2:  13%|█▎        | 239/1875 [00:03<00:24, 67.30it/s] [repeated 64x across cluster]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 1:   0%|          | 0/313 [00:00<?, ?it/s]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 1:  85%|████████▍ | 266/313 [00:01<00:00, 222.54it/s] [repeated 20x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    ..
    
    Training completed after 10 iterations at 2024-11-21 19:19:47. Total running time: 8min 23s
    2024-11-21 19:19:47,596 INFO tune.py:1009 -- Wrote the latest version of all result files and experiment state to '/home/ray/ray_results/TorchTrainer_2024-11-21_19-11-23' in 0.0029s.
    
    Training result: Result(
      metrics={'loss': 0.35892221605786073, 'accuracy': 0.872},
      path='/home/ray/ray_results/TorchTrainer_2024-11-21_19-11-23/TorchTrainer_74867_00000_0_2024-11-21_19-11-24',
      filesystem='local',
      checkpoint=None
    )
    (RayTrainWorker pid=1341, ip=10.244.1.42) Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz [repeated 7x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42) Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to /home/ray/data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz [repeated 7x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42) Extracting /home/ray/data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to /home/ray/data/FashionMNIST/raw [repeated 7x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 9:  91%|█████████ | 1708/1875 [00:21<00:01, 83.84it/s] [repeated 23x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Train Epoch 9: 100%|██████████| 1875/1875 [00:23<00:00, 78.52it/s] [repeated 37x across cluster]
    (RayTrainWorker pid=1341, ip=10.244.1.42)
    Test Epoch 9:   0%|          | 0/313 [00:00<?, ?it/s]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 9:  89%|████████▉ | 278/313 [00:01<00:00, 266.46it/s] [repeated 19x across cluster]
    (RayTrainWorker pid=1193, ip=10.244.4.193)
    Test Epoch 9:  97%|█████████▋| 305/313 [00:01<00:00, 256.69it/s]
    Test Epoch 9: 100%|██████████| 313/313 [00:01<00:00, 267.35it/s]
    2024-11-21 19:19:51,728 SUCC cli.py:63 -- ------------------------------------------
    2024-11-21 19:19:51,728 SUCC cli.py:64 -- Job 'rayjob-pytorch-mnist-hndpx' succeeded
    2024-11-21 19:19:51,728 SUCC cli.py:65 -- ------------------------------------------
    

Ray ダッシュボードでトレーニング結果を表示する

RayJob が正常に完了すると、Ray ダッシュボードでトレーニング結果を表示できます。 Ray ダッシュボードで Ray クラスターのリアルタイムの監視と視覚化ができます。 Ray ダッシュボードを使用すると、Ray クラスターの状態の監視、ログの表示、機械学習ジョブの結果の視覚化を行うことができます。

Ray ダッシュボードにアクセスするには、ポート 8265 ではなく、ポート 80 で Ray ヘッド サービスを公開する "サービス shim" を作成して、Ray ヘッド サービスをパブリック インターネットに公開する必要があります。

Note

前のセクションで説明した deploy.sh は、Ray ヘッド サービスをパブリック インターネットに自動的に公開します。 以下の手順は、deploy.sh スクリプトに含まれています。

  1. 次のコマンドを使用して、Ray ヘッド サービスの名前を取得してシェル変数に保存します。

    rayclusterhead=$(kubectl get service -n $kuberay_namespace | grep 'rayjob-pytorch-mnist-raycluster' | grep 'ClusterIP' | awk '{print $1}')
    
  2. kubectl expose service コマンドを使用して、ポート 80 で Ray ヘッド サービスを公開するサービス shim を作成します。

    kubectl expose service $rayclusterhead \
    -n $kuberay_namespace \
    --port=80 \
    --target-port=8265 \
    --type=NodePort \
    --name=ray-dash
    
  3. 次のコマンドを使用して、イングレス コントローラーを使用してサービス shim を公開するイングレスを作成します。

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ray-dash
      namespace: kuberay
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      ingressClassName: webapprouting.kubernetes.azure.com
      rules:
      - http:
          paths:
          - backend:
              service:
                name: ray-dash
                port:
                  number: 80
            path: /
            pathType: Prefix
    EOF
    
  4. kubectl get service コマンドを使用して、イングレス コントローラーのパブリック IP アドレスを取得します。

    kubectl get service -n app-routing-system
    
  5. 出力には、イングレス コントローラーに接続されているロード バランサーのパブリック IP アドレスが表示されます。 パブリック IP アドレスをコピーし、Web ブラウザーに貼り付けます。 Ray ダッシュボードが表示されます。

リソースをクリーンアップする

このガイドで作成したリソースをクリーンアップするには、AKS クラスターを含む Azure リソース グループを削除します。

次のステップ

AKS での AI と機械学習のワークロードの詳細については、次の記事を参照してください。

共同作成者

Microsoft では、この記事を保持しています。 最初の寄稿者は次のとおりです。

  • Russell de Pina | プリンシパル TPM
  • Ken Kilty | プリンシパル TPM
  • Erin Schaffer |コンテンツ開発者 2
  • Adrian Joian | プリンシパル カスタマー エンジニア
  • Ryan Graham | プリンシパル テクニカル スペシャリスト