概要
Google Kubernetes Engine(GKE)でバッチジョブを実行することができるのですが、Cloud Functionsからジョブ実行できたらCloud Storageなどのイベントをトリガーにできて捗るなぁと思いついて実際に可能か試してみました。
GKEのジョブ実行については下記を参照ください。
GKEを使ったバッチジョブ実行
http://otiai10.hatenablog.com/entry/2017/12/19/162430
前提
下記記事の環境を流用しています。
実際に環境構築する際は、合わせてご参考ください。
Google Kubernetes EngineでUnity ML-Agentsを動かしてみる(V0.5.0対応)
https://cloudpack.media/43540
- ローカルにDockerがインストール済み
- ローカルに
gcloud
、kubectl
がインストール済み - GKEでクラスタ作成済み
- ジョブ実行するDockerイメージがGoogle Container RegistryにPUSH済み
Cloud Functions関数の実装
Cloud Functionsにデプロイするファイルを用意します。
kubernetesのジョブ登録をPythonから行うのに、公式のClient Libraryを利用しました。
kubernetes-client/python
https://github.com/kubernetes-client/python
kubernetesのClient Libraryが利用できるようにします。
requirements.txt
kubernetes
GKEへジョブ登録するのに必要な情報をYamlファイルとして用意します。
内容は先の記事のものを流用しています。
job.yaml
apiVersion: batch/v1 kind: Job metadata: name: GKEクラスタのpod名(任意) spec: template: spec: containers: - name: unity-ml-agents-on-gke image: gcr.io/[GCPのプロジェクトID]/unity_ml_agents_on_gke:latest command: ["mlagents-learn", "trainer_config.yaml", "--env", "3DBall", "--train"] restartPolicy: OnFailure
GKEのクラスタへアクセスできるようにconfigファイルを用意します。
> gcloud container clusters get-credentials [GKEのクラスタ名]
上記コマンドで、クラスタへの接続情報が~/.kube/config
ファイルに保存されます。
このファイルをCloud Functionsにデプロイする際に含めるようにします。
ローカル環境でジョブ登録などのコマンドを実行していると、ファイルにaccess-token
、expiry
が含まれている可能性があります。
Cloud Functionsで実行する場合、GKEへアクセスするのに必要なaccess-token
はCloud Functionsのデフォルトのサービス アカウントを参照してくれるので、自前でサービスアカウントを作成する必要はありませんでした。
configファイルにもaccess-token
、expiry
は不要となるので、行ごと削除して問題ありません。
サーバー間での本番環境アプリケーションの認証の設定
https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-python
configファイルにはクラスタのIPアドレスなどが含まれるため、実運用の際にはCloud KMSなどを利用してファイルを暗号化しておきましょう。
> cp ~/.kube/config .
Cloud Functionsで実行するソースコードです。
main.py
import os from kubernetes import client, config import subprocess import yaml def create_gke_job(request): subprocess.check_output(['cp', './config', '/tmp/config']) config.load_kube_config('/tmp/config') with open(os.path.join(os.path.dirname(__file__), "./job.yaml")) as f: dep = yaml.load(f) k8s = client.BatchV1Api() resp = k8s.create_namespaced_job(body=dep, namespace="default") print("Deployment created. status='%s'" % str(resp.status))
ポイントとしては、kubernetesのconfigファイルをload_kube_config
メソッドで呼び出すと、ファイルの読み込みだけでなくaccess-token
などの追記がされるので、/tmp
ファルダにコピーして書き込み可能にする必要がありました。
job.yamlに定義している、metadata.name
がpodの名称となり一意である必要があるため、今回の実装だと、関数を複数回実行すると、pod名の重複エラーとなるため、yaml.load
後に、書き換えが必要となります。
kubernetesのClient Libraryについては、APIが多くて、どのAPIを利用すればよいのか(非常に)わかりにくいですが、ドキュメントがしっかり用意されているので、探せば大抵のことはわかるっぽいです(未確認)
python/kubernetes/README.md
https://github.com/kubernetes-client/python/blob/master/kubernetes/README.md
あとはCloud Functionsにデプロイして良しなに。
今回は関数が実行できたら良いだけので、トリガを--trigger-http
にしています。
> gcloud functions deploy create_gke_job --trigger-http --runtime=python37
※いつのまにかgcloud functions
コマンドで、--runtime=python37
の指定ができるようになっていました。(Google Cloud SDK 216.0.0)
参考
GKEを使ったバッチジョブ実行
http://otiai10.hatenablog.com/entry/2017/12/19/162430
Google Kubernetes EngineでUnity ML-Agentsを動かしてみる(V0.5.0対応)
https://cloudpack.media/43540
kubernetes-client/python
https://github.com/kubernetes-client/python
python/kubernetes/README.md
https://github.com/kubernetes-client/python/blob/master/kubernetes/README.md
サーバー間での本番環境アプリケーションの認証の設定
https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-python
Cloud FunctionsでPython利用記事まとめ
https://cloudpack.media/43468
元記事はこちら
「Google Cloud Functions(Python)からGoogle Kubernetes Engine(GKE)のジョブを登録する」