Azure k8sを使ったSpark-submitを実行するのにハマったので同じ人が出ないよう共有です
実行環境
- kubernetes: Azure K8s Service(AKS) version 1.10.3
- dockerイメージレジストリ: Azure Container Registry
- spark: spakr2.3をgithubからDLし、-Pkubernetesオプションをつけて、jar化
実行手順
AKS での Apache Spark ジョブの実行というAzureのマニュアルに沿って実行
やりたかったこと
Spark-Pi example Jarをコンテナ内にADDした状態でspark-submitしたかった
↓のコマンドのようにlocal://をつけてspark-submitしたかったということ
./bin/spark-submit
--master k8s://http://0.0.0.1:8001
--deploy-mode cluster
--name spark-pi
--class org.apache.spark.examples.SparkPi
--conf spark.executor.instances=1
--conf spark.kubernetes.container.image=hoge
local:///opt/spark/work-dir/SparkPi.jar
起きた現象
↓のようにSparkPiをAzure Blob Storageに置いて実行する場合は正常終了する
jarUrl=$(az storage blob url --container-name $CONTAINER_NAME --name $BLOB_NAME | tr -d '"')
./bin/spark-submit \
--master k8s://http://127.0.0.1:8001 \
--deploy-mode cluster \
--name spark-pi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=3 \
--conf spark.kubernetes.container.image=$REGISTRY_NAME/spark:$REGISTRY_TAG \
$jarUrl
しかしJarをContainerにいれ、local Jarを見るようにすると失敗する.
なおコンテナ内にJarが格納されていることはdocker runした上で確認済み.
# マニュアル内[コンテナー イメージを使用して jar をパッケージ化する]箇所
./bin/spark-submit \
--master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \
--deploy-mode cluster \
--name spark-pi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=3 \
--conf spark.kubernetes.container.image=<spark-image> \
local:///opt/spark/work-dir/<your-jar-name>.jar
Error: Could not find or load main class org.apache.spark.examples.SparkPi
原因
k8s経由のspark-submit時にはimageをPullするPolicyが設定されている
Property Name | Default | Meaning |
---|---|---|
spark.kubernetes.container.image.pullPolicy | IfNotPresent | Container image pull policy used when pulling images within Kubernetes. |
(Spark 2.3.0マニュアルより抜粋)
DefaultはIfNotPresent、つまり変更があればImageをPullするPolicyであると思っていた.
にもかかわらずDocker Imageを更新してもPullされず、古いものが使われ続けていた.
そのためJarをADDしたイメージでRegistryを更新したにも関わらず、 k8s内ではADDしていない時に登録したイメージがずっと使われため、Jarが存在せずエラーで落ちていた.
またAzure Container Registryから該当イメージをPullしてdocker runした場合には、最新イメージが使われていたためJarが存在しており、トラブルシュートをややこやしくしていた.
解決策
- Regsitryのtagを毎回変えた上でPushする
- latestタグを使う
- 以下のオプションをspark-submitに加えてk8sでも毎回強制Pullさせる
--conf spark.kubernetes.container.image.pullPolicy=Always
詳しくは↓の[Updating Images]項を参考
https://kubernetes.io/docs/concepts/containers/images/