概要
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://qiita.com/kai_kou/items/3a4d860f8353ff1b3110
- ローカルに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が利用できるようにします。
kubernetes
GKEへジョブ登録するのに必要な情報を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で実行するソースコードです。
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://qiita.com/kai_kou/items/3a4d860f8353ff1b3110
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://qiita.com/kai_kou/items/2f65db5305ba280ad81e