kubectlを利用したモデル学習

Prev Next

VPC環境で利用できます。

モデル学習のための複数のフレームワーク Jobを提供しています。
学習の基本となる単一ノード学習、分散ノード学習を最も多く使用される形態である単一ノード学習(Job)、分散ノード学習(PytorchJob)形態で説明します。

Job vs PytorchJob

単一ノード学習の場合、Job の使用をお勧めします。
PytorchJobを使用する場合、分散ノード学習のための機能により、Masterと Workerの形態でリリース管理されるため、不要なリソースが浪費されることがあります。

単一ノード学習(Job)を実行する

学習のために Kubernetes Job明細は次のユースケースのように作成できます。

# job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: mnist
  namespace: p-{projectName}
spec:
  backoffLimit: 1
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      restartPolicy: Never
      containers:
        - name: main
          image: { 学習画像 (e.g.example.com/mnist:latest ) } # NVIDIA Base画像を基準に作成された学習コード
          imagePullPolicy: Always
          resources:
            limits:
              memory: "8Gi"
              cpu: "4"
              nvidia.com/gpu: "1"
          command: ["python"]
          args:
            - /opt/mnist/src/mnist.py
            - --checkpoint_path
            - /opt/mnist/checkpoints/mnist.pt
            - --log_path
            - /opt/mnist/log
            - --data_path
            - /opt/mnist/data
            - --download_data
kubectl apply -f job.yaml
batch/mnist created

外部コンテナレジストリの使用

コンテナレジストリに Secret情報が必要な場合、 Container Secretを作成するを参照して作成できます。
作成された Secretは、次のように使用できます。

...
spec:
    imagePullSecrets:
    - name: my-harbor-secret  # 事前に作成した Docker Credential Secretの名前
...

既存 Volumeの使用

Volumesを通じて作成された Volumeを使用するには、次のように使用できます。

...
spec:
    containers:
    - name: main
      ...
      volumeMounts:
      - mountPath: /data
        name: mnist-data # 下部の spec.volumesに記載した名前
    volumes:
    - name: mnist-data
      persistentVolumeClaim:
        claimName: mnist-data # Volumesを通じて作成された PVC名
...

Jobライフサイクル

Jobが終了した場合、一定時間コンテナログとステータスを残すために削除されず、リストに残ります。
リストに残れる Jobの最大数制限があるため、TTLを通じてライフサイクルを管理する必要があります。詳細は Kubernetes Job APIドキュメントをご参照ください。

Jobを作成する際、TTL(Time To Live)を任意に設定できます。TTLは Jobが完了(成功/失敗)した後に有効になり、TTLだけ経過すると Jobとそれに属する Podがすべて自動的に削除されます。

以下は、3週間の TTLを適用した例です。

apiVersion: batch/v1
kind: Job
metadata:
  name: mnist
  namespace: p-{projectName}
spec:
  ttlSecondsAfterFinished: 1814400 # TTLを直接設定するフィールド(単位: sec)

分散ノード学習(PytorchJob)を実行する

PyTorchJobの利用時に以下のようなメリットがあります。

  • 作成されたコンテナ specをベースに Master、Worker Podを適切に作成します。
  • PyTorch分散学習で一般的に必要な環境変数(i.e., WORLD_SIZE、RANK、MASTER_ADDRなど)を自動的に設定します。
  • 学習に使用される Podが相互に通信できるように、K8s Serviceを自動的に作成します。Masterは <pytorch-job-name>-master-0、Workerは <pytorch-job-name>-worker-<idx> のような名前でアクセスできます。
  • 必要な場合、Elastic Policyを使用するを通じて torchrunで使用する引数を環境変数として作成します(--nnodes--nproc-per-node--rdzv-endpointなど)。

PytorchJobを作成する

Pytorchでの分散学習時は torchrun(Elastic Launch)を使用することをお勧めします。また、 torchrun 使用時にマスター Podを別途明示しません。Torch Elasticではマスターノードの役割をする RANK=0 Podが実行中に変更されることがあります。

  • spec.elasticPolicy - torchrun関連の設定です。ここに明示した設定が環境変数として注入されます。詳細は Elastic Policyを使用するをご参照ください。
  • spec.runPolicy - PyTorchJobの実行および終了後の処理に関連するパラメータを明示できます。詳細は Run Policyを使用するをご参照ください。
  • spec.pytorchReplicaSpecs.Worker - 分散学習を行う Worker Podに関する情報です。

学習のために PytorchJob明細は次のユースケースのように作成できます

:::(Warning) (使用時に以下の事項を必ず遵守する必要があります)。

  • 学習を進行するコンテナの名前(e.g.spec.pytorchReplicaSpecs.Worker.template.spec.containers[*].name)は必ず pytorch である必要があります。
  • 円滑な分散学習のために、Istio Sidecarが Injectにならないよう、spec.pytorchReplicaSpecs.Worker.template.metadata.annotationssidecar.istio.io/inject: "false"を必ず明記する必要があります。当該 annotationが設定されていない場合、RuntimeError: Connection reset by peer などのノード間通信に関連するエラーが発生します。

:::

# pytorchjob.yaml
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
    name: pytorch-mnist-dist-nccl
    namespace: p-{ projectName } # プロジェクトに該当する Kubernetes Namespace名
spec:
    pytorchReplicaSpecs:
        Worker:
            replicas: 2
            restartPolicy: OnFailure
            template:
                metadata:
                    annotations:
                        sidecar.istio.io/inject: "false"  # Istio sidecar injectionの無効化は必須
                spec:
                    nodeSelector:
                        mlx.navercorp.com/zone: { 提供された GPU Zone名 } # GPU Resourcesで確認できる Zone名 
                containers:
                - name: pytorch  # PyTorchJobの container名を必ず pytorchに設定
                   image: examples.com/pytorch-mnist-dist:23.03-py3
                   imagePullPolicy: Always
                   command: ["bash", "-c"]
                   args:
                   - >
                      torchrun --nnodes ${PET_NNODES} --nproc_per_node ${PET_NPROC_PER_NODE} --rdzv_id ${PET_RDZV_ID} --rdzv_backend ${PET_RDZV_BACKEND} --rdzv_endpoint ${PET_RDZV_ENDPOINT}
                      /opt/mnist/src/mnist.py --checkpoint_path /data/checkpoints/mnist.pt --log_path /data/logs --data_path /data/dataset
                    env:
                    - name: NCCL_DEBUG
                       value: INFO
kubectl apply -f pytorchjob.yaml
pytorchjob.kubeflow.org/pytorch-elastic-mnist-nccl created

Elastic Policyを使用する

torchrun を使用するために elasticPolicy を作成します。

...
spec:
    ...
    elasticPolicy:
        rdzvId: mnist
        rdzvBackend: c10d
        minReplicas: 2
        maxReplicas: 2
        nProcPerNode: 8
    ...

elasticPolicy 各フィールド値に基づいて、 PyTorchJob に使用される環境変数が設定されます。環境変数は torchrun 引数の設定に使用できます。torchrun で使用する引数などに関する詳細な説明は、 公式ドキュメントをご参照ください。

elasticPolicy フィールド 対応環境変数 関連 torchrun 因子 説明
rdzvId PET_RDZV_ID --rdzv-id ランデブー用 Job ID
rdzvBackend PET_RDZV_BACKEND --rdzv-backend ランデブーバックエンド(i.e., c10d)
minReplicas, maxReplicas PET_NNODES --nnodes ノード数
nProcPerNode PET_NPROC_PER_NODE --nproc-per-node ノード当たりの GPU数
maxRestarts PET_MAX_RESTARTS --max-restarts 最大再起動回数

Run Policyを使用する

torchrunを使用するためにrunPolicyを作成します。

...
spec:
  runPolicy:
    cleanPodPolicy: None
    ttlSecondsAfterFinished: 1814400 # TTLを直接設定するフィールド(単位: sec)
...

spec.runPolicyには PyTorchJob の実行および整理に関連するパラメータを明示できます。明示しない場合、デフォルト値が使用されます。spec.runPolicy の下位に明示できるパラメータは、次の通りです。(参考資料: Kubeflow Trainer API Reference v1.9)

  • cleanPodPolicy - PytorchJob の完了後、Podをどう整理するか決定します。
    • デフォルト値: None
    • None: Jobの完了後に Podを削除しないため、今後ログの確認に役立ちます。
    • All: Jobの完了後、すべての Podを削除します。
    • Running は Jobの完了後に実行中の Podを削除します。特殊な場合を除き、使用することはありません。
  • ttlSecondsAfterFinished - Jobの完了後、何秒後に Jobを削除するか決めます。
  • activeDeadlineSeconds - Jobの最大実行時間です。明示された時間が経過した後は失敗処理となります。設定されていない場合、jobの実行時間に制限はありません。
  • backoffLimit - Jobの失敗時の最大再試行回数です。

Infinibandの使用

InfiniBandネットワークで接続されたノードで分散学習を行うと、ノード間通信を高速化できます。

以前のセクションで示したユースケースを InfiniBand環境に合わせるには追加すべき明細がいくつかあり、次のように要約できます。

  • InfiniBandネットワークが構成された区域の名前を Annotationとして明示します(i.e., mlx.navercorp.com/zone=a100-ib)
  • InfiniBandの使用のために IPC_LOCK capabilityを securityContext に追加します。
  • ResourceRequestの作成時に InfiniBand用リソース(rdma/hca_shared_devices_a: 1)を割り当てられるよう設定します。
  • 分散学習に役立つ Shared Memoryを volumesに設定します。

Infinibandの使用のために、次のように使用できます。

...
spec:
    ...
    pytorchReplicaSpecs:
        Worker:
            template:
                containers:
                - name: pytorch
                   securityContext:  # Infinibandの使用のために securityContextが必要です。
                        capabilities:
                            add: ["IPC_LOCK"]
                   resources:
                        limits:
                            ...
                            rdma/hca_shared_devices_a: 1
                            ...
                        requests:
                            ...
                            rdma/hca_shared_devices_a: 1
                            ...
                    # shared memory
                    volumeMounts:
                    - mountPath: /dev/shm
                       name: shared-memory
                volumes:
                - emptyDir:
                    medium: Memory
                  name: shared-memory
...

PytorchJobデバッグ

PytorchJob 使用時に問題が発生してデバッグが必要な場合、次のように環境変数値を設定して必要な情報をロギングするようにできます。

  • NCCL_DEBUG: NCCLと関連するデバッグ
  • TORCH_DISTRIBUTED_DEBUGTORCH_CPP_LOG_LEVEL: 分散学習に関するデバッグ; 詳細は PyTorch公式ドキュメントをご参照ください。

デバッグのために、次のように使用できます。

...
spec:
    ...
    pytorchReplicaSpecs:
        Worker:
            template:
                containers:
                - name: pytorch
                  ...
                  env:
                  - name: NCCL_DEBUG
                    value: "INFO"
                  - name: TORCH_DISTRIBUTED_DEBUG
                    value: "DETAIL"
                  - name: TORCH_CPP_LOG_LEVEL
                    value: "INFO"
                  ...

外部コンテナレジストリの使用

コンテナレジストリに Secret情報が必要な場合、 Container Secretを作成するを参照して作成できます。
作成された Secretは、次のように使用できます。

...
spec:
    ...
    pytorchReplicaSpecs:
        Worker:
            template:
                containers:
                - name: pytorch
                  imagePullSecrets:
                  - name: my-harbor-secret  # 事前に作成した Docker Credential Secretの名前
...

既存 Volumeの使用

Volumesを通じて作成された Volumeを使用するには、次のように使用できます。

...
spec:
    ...
    pytorchReplicaSpecs:
        Worker:
            template:
                containers:
                - name: pytorch
                    volumeMounts:
                    - mountPath: /data
                       name: mnist-data # 下部の spec.volumesに記載した名前
                volumes:
                - name: mnist-data
                  persistentVolumeClaim:
                      claimName: mnist-data # Volumesを通じて作成された PVC名
...

PytorchJobのステータスを確認

kubectl getkubectl describe を利用して PyTorchJob のステータスを確認できます。

kubectl get pytorchjob pytorch-elastic-mnist-nccl
NAME                         STATE     AGE
pytorch-elastic-mnist-nccl   Running   12s
kubectl describe pytorchjob pytorch-elastic-mnist-nccl

Status:
  Completion Time:  2024-11-22T09:16:58Z
  Conditions:
    Last Transition Time:  2024-11-22T09:15:43Z
    Last Update Time:      2024-11-22T09:15:43Z
    Message:               PyTorchJob pytorch-elastic-mnist-nccl is created.
    Reason:                PyTorchJobCreated
    Status:                True
    Type:                  Created
    Last Transition Time:  2024-11-22T09:15:48Z
    Last Update Time:      2024-11-22T09:15:48Z
    Message:               PyTorchJob nb12706/pytorch-elastic-mnist-nccl is running.
    Reason:                PyTorchJobRunning
    Status:                False
    Type:                  Running
    Last Transition Time:  2024-11-22T09:16:58Z
    Last Update Time:      2024-11-22T09:16:58Z
    Message:               PyTorchJob nb12706/pytorch-elastic-mnist-nccl successfully completed.
    Reason:                PyTorchJobSucceeded
    Status:                True
    Type:                  Succeeded
  Last Reconcile Time:     2024-11-22T09:15:43Z
  Replica Statuses:
    Worker:
      Selector:   training.kubeflow.org/job-name=pytorch-elastic-mnist-nccl,training.kubeflow.org/operator-name=pytorchjob-controller,training.kubeflow.org/replica-type=worker
      Succeeded:  2
  Start Time:     2024-11-22T09:15:44Z
Events:
  Type    Reason                    Age                  From                   Message
  ----    ------                    ----                 ----                   -------
  Normal  SuccessfulCreatePod       4m21s                pytorchjob-controller  Created pod: pytorch-elastic-mnist-nccl-worker-0
  Normal  SuccessfulCreatePod       4m21s                pytorchjob-controller  Created pod: pytorch-elastic-mnist-nccl-worker-1
  Normal  SuccessfulCreateService   4m21s                pytorchjob-controller  Created service: pytorch-elastic-mnist-nccl-worker-0
  Normal  SuccessfulCreateService   4m21s                pytorchjob-controller  Created service: pytorch-elastic-mnist-nccl-worker-1
  Normal  ExitedWithCode            3m7s (x3 over 3m8s)  pytorchjob-controller  Pod: nb12706.pytorch-elastic-mnist-nccl-worker-1 exited with code 0
  Normal  ExitedWithCode            3m7s (x2 over 3m8s)  pytorchjob-controller  Pod: nb12706.pytorch-elastic-mnist-nccl-worker-0 exited with code 0
  Normal  PyTorchJobSucceeded       3m7s                 pytorchjob-controller  PyTorchJob nb12706/pytorch-elastic-mnist-nccl successfully completed.
  Normal  JobTerminated             3m6s (x4 over 3m7s)  pytorchjob-controller  Job has been terminated. Deleting PodGroup
  Normal  SuccessfulDeletePodGroup  3m6s (x4 over 3m7s)  pytorchjob-controller  Deleted PodGroup: pytorch-elastic-mnist-nccl

学習 Podが正常に作成されない場合、以下のように Eventsを通じて原因を把握できます。

kubectl describe pytorchjob pytorch-elastic-mnist-nccl

...
Events:
  Type     Reason           Age                 From                   Message
  ----     ------           ----                ----                   -------
  Warning  FailedCreatePod  47m (x3 over 103m)  pytorchjob-controller  Error creating: Pods "job-worker-1" is forbidden: exceeded quota: normal-quota, requested: requests.nvidia.com/gpu=1, used: requests.nvidia.com/gpu=2, limited: requests.nvidia.com/gpu=2