Kubeflow 1.0 : コンポーネント : TensorFlow 訓練 (TFJob) (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/10/2020 (1.0)
* 本ページは、Kubeflow の以下のページを翻訳した上で適宜、補足説明したものです:
- Components of Kubeflow : TensorFlow Training (TFJob)
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
コンポーネント : TensorFlow 訓練 (TFJob)
このページは TensorFlow で機械学習モデルを訓練するための TFJob を記述します。
TFJob とは何でしょう?
TFJob は Kubernetes 上で TensorFlow 訓練ジョブを実行するために利用できる Kubernetes カスタム・リソース です。TFJob の Kubeflow 実装は tf-operator にあります。
TFJob は下の一つのような YAML 表現を持つリソースです (貴方自身の訓練コードのためのコンテナ・イメージとコマンドを使用するために編集します) :
apiVersion: kubeflow.org/v1 kind: TFJob metadata: generateName: tfjob namespace: your-user-namespace spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: OnFailure template: spec: containers: - name: tensorflow image: gcr.io/your-project/your-image command: - python - -m - trainer.task - --batch_size=32 - --training_steps=1000 Worker: replicas: 3 restartPolicy: OnFailure template: spec: containers: - name: tensorflow image: gcr.io/your-project/your-image command: - python - -m - trainer.task - --batch_size=32 - --training_steps=1000
GKE ベースで Kubeflow インストールを行なったときに自動的に作成される GCP クレデンシャルのような、クレデンシャル secret への TFJob ポッド・アクセスを与えることを望む場合、このように secret をマウントして使用できます :
apiVersion: kubeflow.org/v1 kind: TFJob metadata: generateName: tfjob namespace: your-user-namespace spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: OnFailure template: spec: containers: - name: tensorflow image: gcr.io/your-project/your-image command: - python - -m - trainer.task - --batch_size=32 - --training_steps=1000 env: - name: GOOGLE_APPLICATION_CREDENTIALS value: "/etc/secrets/user-gcp-sa.json" volumeMounts: - name: sa mountPath: "/etc/secrets" readOnly: true volumes: - name: sa secret: secretName: user-gcp-sa Worker: replicas: 1 restartPolicy: OnFailure template: spec: containers: - name: tensorflow image: gcr.io/your-project/your-image command: - python - -m - trainer.task - --batch_size=32 - --training_steps=1000 env: - name: GOOGLE_APPLICATION_CREDENTIALS value: "/etc/secrets/user-gcp-sa.json" volumeMounts: - name: sa mountPath: "/etc/secrets" readOnly: true volumes: - name: sa secret: secretName: user-gcp-sa
Kubernetes リソースに馴染みがないのであれば、ページ Understanding Kubernetes オブジェクト を参照してください。
TFJob を 組込みコントローラ と違わせるものは TFJob spec は 分散 TensorFlow 訓練ジョブ を管理するために設計されていることです。
分散 TensorFlow ジョブは典型的には以下のプロセスの 0 またそれ以上を含みます :
- Chief : chief はモデルをチェックポイントするように訓練の編成とタスクの遂行の責任を負います。
- Ps : ps はパラメータ・サーバです ; これらのサーバはモデルパラメータのための分散データストアを提供します。
- Worker : ワーカーはモデルを訓練する実際の作業を行ないます。ある場合には、ワーカー 0 はまた chief として動作するかもしれません。
- Evaluator : 評価器はモデルが訓練されるとき評価メトリクスを計算するために使用できます。
TFJob spec のフィールド tfReplicaSpecs は (上でリストされた) レプリカのタイプからそのレプリカのための TFReplicaSpec へのマップを含みます。TFReplicaSpec は 3 フィールドから成ります :
- replicas この TFJob のために起動するこのタイプのレプリカ数。
- template 各レプリカのために作成するポッドを記述する PodTemplateSpec。
- ポッドは tensorflow という名前のコンテナを含まなければなりません。
- restartPolicy ポッドがそれらが exit するとき再開始されるか否かを決定します。許可される値は次のようなものです :
- Always はポッドが常に再開始されることを意味します。このポリシーはパラメータサーバのために良いです、何故ならばそれらは決して exit せずに failure イベントでは常に再開始されるべきであるためです。
- OnFailure はポッドが failure により exit する場合に再開始されることを意味します。
- 非ゼロは failure を示すコードです。
- 0 の exit コードは成功を示しそしてポッドは再開始されません。
- このポリシーは chief と worker のために良いです。
- ExitCode は再開始動作は次のように tensorflow コンテナの exit コードに依拠していることを意味します。
- Exit コード 0 はプロセスは成功的に完了し再開始されません。
- 以下の exit コードはパーマネントエラーを示しそしてコンテナは再開始されません :
- 1: 一般エラー
- 2: misuse of shell builtins
- 126: command invoked cannot execute
- 127: command not found
- 128: invalid argument to exit
- 139: container terminated by SIGSEGV (invalid memory reference)
- 以下の exit コードは再試行可能なエラーを示しそしてコンテナは再開始されます :
- 130: container terminated by SIGINT (keyboard Control-C)
- 137: container received a SIGKILL
- 143: container received a SIGTERM
- Exit コード 138 は SIGUSR1 に対応してユーザ指定再試行可能なエラーのために予約されています。
- 他の exit コードは未定義で動作について保証はありません。
exit コードのバックグラウンド情報については、termination シグナルへの GNU ガイド と Linux ドキュメント・プロジェクト を見てください。
- Never は停止するポッドは決して再開始されないことを意味します。このポリシーは滅多に使用されないはずです、何故ならば Kubernetes はどのような数の理由 (e.g. ノードが不安定になる) でもポッドを停止しそしてこれはジョブがリカバーされることを回避するからです。
クイックスタート
TensorFlow 訓練ジョブを投入する
Note: 訓練ジョブを投入する前に、kubeflow を貴方のクラスタに配備する べきでした。それを行なうことで訓練ジョブを投入するとき TFJob カスタム・リソース が利用可能であることを確かなものにします。
MNist サンプルを実行する
Kubeflow は単純な MNist モデル を実行するために適した サンプル とともに配布されています。
git clone https://github.com/kubeflow/tf-operator cd tf-operator/examples/v1/mnist_with_summaries # Deploy the event volume kubectl apply -f tfevent-volume # Submit the TFJob kubectl apply -f tf_job_mnist.yaml
ジョブを監視する (下の詳細ガイド を見てください) :
kubectl -n kubeflow get tfjob mnist -o yaml
それを削除する :
kubectl -n kubeflow delete tfjob mnist
TFJob をカスタマイズする
典型的には TFJob yaml ファイルの次の値を変更できます :
- イメージを貴方のコードを含む docker イメージを指すように変更する
- レプリカの数とタイプを変更する
- 各リソースに割り当てられたリソース (リクエストと制限) を変更する
- 任意の環境変数を設定する
- 例えば、GCS or S3 のようなデータストアと通信するために様々な環境変数を configure する必要があるかもしれません
- ストレージのために PV を使用することを望む場合 PV を装着する。
GPU を使用する
貴方のクラスタは GPU を利用するために configure されなければなりません。
- ノードは装着された GPU を持たなければなりません。
- Kubernetes クラスタは nvidia.com/gpu リソース型を認識しなければなりません。
- GPU ドライバはクラスタ上にインストールされなければなりません。
- より多くの情報のために :
GPU を装着するには GPU を含むべきレプリカのコンテナ上の GPU リソースを指定します ; 例えば :
apiVersion: "kubeflow.org/v1" kind: "TFJob" metadata: name: "tf-smoke-gpu" spec: tfReplicaSpecs: PS: replicas: 1 template: metadata: creationTimestamp: null spec: containers: - args: - python - tf_cnn_benchmarks.py - --batch_size=32 - --model=resnet50 - --variable_update=parameter_server - --flush_stdout=true - --num_gpus=1 - --local_parameter_device=cpu - --device=cpu - --data_format=NHWC image: gcr.io/kubeflow/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3 name: tensorflow ports: - containerPort: 2222 name: tfjob-port resources: limits: cpu: '1' workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks restartPolicy: OnFailure Worker: replicas: 1 template: metadata: creationTimestamp: null spec: containers: - args: - python - tf_cnn_benchmarks.py - --batch_size=32 - --model=resnet50 - --variable_update=parameter_server - --flush_stdout=true - --num_gpus=1 - --local_parameter_device=cpu - --device=gpu - --data_format=NHWC image: gcr.io/kubeflow/tf-benchmarks-gpu:v20171202-bdab599-dirty-284af3 name: tensorflow ports: - containerPort: 2222 name: tfjob-port resources: limits: nvidia.com/gpu: 1 workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks restartPolicy: OnFailure
GPU を利用するための TensorFlow の 手順 に従ってください。
貴方のジョブを監視する
貴方のジョブのステータスを得るには :
kubectl get -o yaml tfjobs ${JOB}
ここのサンプル・ジョブのためのサンプル出力があります :
apiVersion: kubeflow.org/v1 kind: TFJob metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"kubeflow.org/v1","kind":"TFJob","metadata":{"annotations":{},"name":"mnist","namespace":"kubeflow"},"spec":{"cleanPodPolicy":"None","tfReplicaSpecs":{"Worker":{"replicas":1,"restartPolicy":"Never","template":{"spec":{"containers":[{"command":["python","/var/tf_mnist/mnist_with_summaries.py","--log_dir=/train","--learning_rate=0.01","--batch_size=150"],"image":"gcr.io/kubeflow-ci/tf-mnist-with-summaries:1.0","name":"tensorflow","volumeMounts":[{"mountPath":"/train","name":"training"}]}],"volumes":[{"name":"training","persistentVolumeClaim":{"claimName":"tfevent-volume"}}]}}}}}} creationTimestamp: "2019-07-16T02:44:38Z" generation: 1 name: mnist namespace: your-user-namespace resourceVersion: "10429537" selfLink: /apis/kubeflow.org/v1/namespaces/kubeflow/tfjobs/mnist uid: a77b9fb4-a773-11e9-91fe-42010a960094 spec: cleanPodPolicy: None tfReplicaSpecs: Worker: replicas: 1 restartPolicy: Never template: spec: containers: - command: - python - /var/tf_mnist/mnist_with_summaries.py - --log_dir=/train - --learning_rate=0.01 - --batch_size=150 image: gcr.io/kubeflow-ci/tf-mnist-with-summaries:1.0 name: tensorflow volumeMounts: - mountPath: /train name: training volumes: - name: training persistentVolumeClaim: claimName: tfevent-volume status: completionTime: "2019-07-16T02:45:23Z" conditions: - lastTransitionTime: "2019-07-16T02:44:38Z" lastUpdateTime: "2019-07-16T02:44:38Z" message: TFJob mnist is created. reason: TFJobCreated status: "True" type: Created - lastTransitionTime: "2019-07-16T02:45:20Z" lastUpdateTime: "2019-07-16T02:45:20Z" message: TFJob mnist is running. reason: TFJobRunning status: "True" type: Running replicaStatuses: Worker: running: 1 startTime: "2019-07-16T02:44:38Z"
条件
TFJob は TFJobStatus を持ち、これは TFJobConditions の配列を持ちます、それを通して TFJob は通過または非通過しました。TFJobCondition の各要素は 6 つの可能なフィールドを持ちます :
- lastUpdateTime フィールドはこの条件が更新された最後の時間を提供します。
- lastTransitionTime フィールドは条件が一つのステータスから他に遷移した最後の時間を提供します。
- message フィールドは遷移についての詳細を示す可読なメッセージです。
- reason フィールドは条件の最後の遷移のための一意、1 単語、CamelCase な理由です。
- status フィールドは可能な値 “True”, “False” と “Unknown” を持つ文字列です。
- type フィールドは以下の可能な値を持つ文字列です :
- TFJobCreated は tfjob がシステムにより受け取られたことを意味しますが、ポッド/サービスの一つまたはそれ以上がまだ開始されていません。
- TFJobRunning はこの TFJob の総てのサブリソース (e.g. サービス/ポッド) が成功的にスケジュールされて起動されてジョブが実行されていることを意味します。
- TFJobRestarting はこの TFJob の一つまたはそれ以上のサブリソース (e.g. サービス/ポッド) が問題を持ち再開始されていることを意味します。
- TFJobSucceeded はジョブが成功的に完了したことを意味します。
- TFJobFailed はジョブが失敗したことを意味します。
ジョブの成功と失敗は次のように決定されます :
- ジョブが chief 成功か失敗を持つかは chief のステータスにより決定されます。
- ジョブが chief でない成功か失敗を持つかはワーカーにより決定されます。
- 両者の場合、TFJob は監視されているプロセスが exit コード 0 で抜ける場合に成功します。
- 非ゼロ exit コードの場合動作はレプリカのための restartPolicy により決定されます。
- restartPolicy が再開始を許容する場合にはプロセスは単に再開始されて TFJob は実行し続けます。
- restartPolicy ExitCode については動作は exit コード依存です。
- restartPolicy が再開始を許容しない場合、非ゼロ exit コードはパーマネント失敗と考えられてジョブは失敗とマークされます。
tfReplicaStatuses
tfReplicaStatuses は与えられた状態にある各レプリカのためのポッドの数を示すマップを提供します。3 つの可能な状態があります :
- Active は現在実行中のポッドの数です。
- Succeeded は成功的に完了したポッドの数です。
- Failed はエラーで完了したポッドの数です。
イベント
実行の間、TFJob はポッドとサービスの作成/削除のような発生したことを示すためにイベントを出力します。Kubernetes はデフォルトでは 1 時間よりも古いイベントは保持しません。ジョブのための最近のイベントを見るには次を実行します :
kubectl describe tfjobs ${JOB}
これは次のような出力を生成します :
Name: mnist Namespace: kubeflow Labels:Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"kubeflow.org/v1","kind":"TFJob","metadata":{"annotations":{},"name":"mnist","namespace":"kubeflow"},"spec":{"cleanPodPolicy... API Version: kubeflow.org/v1 Kind: TFJob Metadata: Creation Timestamp: 2019-07-16T02:44:38Z Generation: 1 Resource Version: 10429537 Self Link: /apis/kubeflow.org/v1/namespaces/kubeflow/tfjobs/mnist UID: a77b9fb4-a773-11e9-91fe-42010a960094 Spec: Clean Pod Policy: None Tf Replica Specs: Worker: Replicas: 1 Restart Policy: Never Template: Spec: Containers: Command: python /var/tf_mnist/mnist_with_summaries.py --log_dir=/train --learning_rate=0.01 --batch_size=150 Image: gcr.io/kubeflow-ci/tf-mnist-with-summaries:1.0 Name: tensorflow Volume Mounts: Mount Path: /train Name: training Volumes: Name: training Persistent Volume Claim: Claim Name: tfevent-volume Status: Completion Time: 2019-07-16T02:45:23Z Conditions: Last Transition Time: 2019-07-16T02:44:38Z Last Update Time: 2019-07-16T02:44:38Z Message: TFJob mnist is created. Reason: TFJobCreated Status: True Type: Created Last Transition Time: 2019-07-16T02:45:20Z Last Update Time: 2019-07-16T02:45:20Z Message: TFJob mnist is running. Reason: TFJobRunning Status: True Type: Running Replica Statuses: Worker: Running: 1 Start Time: 2019-07-16T02:44:38Z Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreatePod 8m6s tf-operator Created pod: mnist-worker-0 Normal SuccessfulCreateService 8m6s tf-operator Created service: mnist-worker-0
ここでイベントはポッドとサービスが成功的に作成されたことを示します。
TensorFlow ログ
ロギングは標準的な K8s ロギング実践に従います。
削除 されなかった任意のポッドのための標準的な出力/エラーを得るために kubectl を使用できます。
最初に関心のあるレプリカのためのジョブ・コントローラにより作成されたポッドを見つけます。ポッドは次のように名前付けられます :
${JOBNAME}-${REPLICA-TYPE}-${INDEX}
ひとたびポッドを特定すれば、kubectl を使用してログを得ることができます。
kubectl logs ${PODNAME}
TFJob spec の CleanPodPolicy はジョブが停止したときポッドの削除を制御します。ポリシーは以下の値の一つであり得ます :
- Running はジョブが完了したとき依然として実行しているポッド (e.g. パラメータサーバ) だけが直ちに削除されます ; 完了したポッドはログが保存されるように削除されません。これはデフォルト値です。
- All ポリシーはジョブが終了したとき総てのポッド、完了したポッドさえも直ちに削除されることを意味します。
- None ポリシーはジョブが完了したときポッドは削除されないことを意味します。
貴方のクラスタが Kubernetes クラスタ・ロギング を活用するならばログも更なる解析のために適切なデータストアに送られるかもしれません。
GKE 上の Stackdriver
Stackdriver を使用してログを得る上での手順については ロギングと監視 へのガイドを見てください。
ロギングと監視 へのガイドで説明されているように、ポッドラベルに基づいて特定のレプリカのためのログを取得することができます。
Stackdriver UI を使用して次のような問い合わせを使用できます :
resource.type="k8s_container" resource.labels.cluster_name="${CLUSTER}" metadata.userLabels.tf_job_name="${JOB_NAME}" metadata.userLabels.tf-replica-type="${TYPE}" metadata.userLabels.tf-replica-index="${INDEX}"
代わりに gcloud を使用して :
QUERY="resource.type=\"k8s_container\" " QUERY="${QUERY} resource.labels.cluster_name=\"${CLUSTER}\" " QUERY="${QUERY} metadata.userLabels.tf_job_name=\"${JOB_NAME}\" " QUERY="${QUERY} metadata.userLabels.tf-replica-type=\"${TYPE}\" " QUERY="${QUERY} metadata.userLabels.tf-replica-index=\"${INDEX}\" " gcloud --project=${PROJECT} logging read \ --freshness=24h \ --order asc ${QUERY}
トラブルシューティング
ここに貴方のジョブのトラブルシュートをするために従うべき幾つかのステップがあります。
- ステータスは貴方のジョブのために存在していますか? 次のコマンドを実行してください :
kubectl -n ${USER_NAMESPACE} get tfjobs -o yaml ${JOB_NAME}
- USER_NAMESPACE は貴方のユーザプロフィールのために作成された名前空間です。
- 結果としての出力が貴方のジョブのためのステータスを含まない場合、これは典型的にはジョブ spec が不正であることを示しています。
- TFJob spec が不正であれば tf operator ログにログメッセージがあるはずです :
kubectl -n ${KUBEFLOW_NAMESPACE} logs `kubectl get pods --selector=name=tf-job-operator -o jsonpath='{.items[0].metadata.name}'`
- KUBEFLOW_NAMESPACE は TFJob 演算子を配備した名前空間です。
- ポッドが作成されたかを見るために貴方のジョブのためのイベントを確認します。
- イベントを得るために幾つかの方法があります ; ジョブが 1 時間未満であれば次を行なうことができます :
kubectl -n ${USER_NAMESPACE} describe tfjobs -o yaml ${JOB_NAME}
- 出力のボトムはジョブにより出力されたイベントのリストを含むはずです ; e.g.
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning SettedPodTemplateRestartPolicy 19s (x2 over 19s) tf-operator Restart policy in pod template will be overwritten by restart policy in replica spec Normal SuccessfulCreatePod 19s tf-operator Created pod: tfjob2-worker-0 Normal SuccessfulCreateService 19s tf-operator Created service: tfjob2-worker-0 Normal SuccessfulCreatePod 19s tf-operator Created pod: tfjob2-ps-0 Normal SuccessfulCreateService 19s tf-operator Created service: tfjob2-ps-0
- Kubernetes は 1 時間 の間イベントを保存するだけです (kubernetes/kubernetes#52521 参照)
- 貴方のクラスタ・セットアップに依拠してイベントは外部ストレージに存続してより長い期間アクセス可能かもしれません。
- GKE 上ではイベントは stackdriver で存続されて前のセクションの手順を使用してアクセスできます。
- ポッドとサービスが作成されなければこれは TFJob が処理されていないことを提示します ; 一般的な原因は :
- TFJob spec が不正である (上を見てください)
- TFJob 演算子が動作していない
- イベントを得るために幾つかの方法があります ; ジョブが 1 時間未満であれば次を行なうことができます :
- ポッドのためのイベントをそれらがスケジュールされたかを確実にするためにクリックします。
- イベントを得るために幾つかの方法があります ; ポッドが 1 時間未満であれば次を行なうことができます :
kubectl -n ${USER_NAMESPACE} describe pods ${POD_NAME}
- 出力のボトムは次のようなイベントを含むはずです :
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 18s default-scheduler Successfully assigned tfjob2-ps-0 to gke-jl-kf-v0-2-2-default-pool-347936c1-1qkt Normal SuccessfulMountVolume 17s kubelet, gke-jl-kf-v0-2-2-default-pool-347936c1-1qkt MountVolume.SetUp succeeded for volume "default-token-h8rnv" Normal Pulled 17s kubelet, gke-jl-kf-v0-2-2-default-pool-347936c1-1qkt Container image "gcr.io/kubeflow/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3" already present on machine Normal Created 17s kubelet, gke-jl-kf-v0-2-2-default-pool-347936c1-1qkt Created container Normal Started 16s kubelet, gke-jl-kf-v0-2-2-default-pool-347936c1-1qkt Started container
- コンテナを開始から妨げられる幾つかの一般的な問題は :
- ポッドをスケジュールするために不十分なリソース
- ポッドが存在しないか利用不可能なボリューム (or secret) をマウントしようとする
- docker イメージが存在しないかアクセスできない (e.g. パーミッション問題により)
- イベントを得るために幾つかの方法があります ; ポッドが 1 時間未満であれば次を行なうことができます :
- コンテナが開始される場合 ; 前のセクションの手順に従ってコンテナのログを確認してください。
以上