Kubernetes で Spark を実行
- セキュリティ
- 前提条件
- 仕組み
- Kubernetes へのアプリケーションの送信
- 設定
Spark は、Kubernetes で管理されるクラスター上で実行できます。この機能は、Spark に追加されたネイティブ Kubernetes スケジューラーを利用します。
セキュリティ
認証のようなセキュリティ機能はデフォルトでは有効になっていません。インターネットまたは信頼されていないネットワークに公開されているクラスターをデプロイする場合、不正なアプリケーションがクラスター上で実行されるのを防ぐために、クラスターへのアクセスを保護することが重要です。Spark を実行する前に、Spark セキュリティ およびこのドキュメントの特定のセキュリティセクションを参照してください。
ユーザー ID
プロジェクト提供の Dockerfile からビルドされたイメージには、デフォルトの USER ディレクティブがあり、デフォルトの UID は 185 です。これは、生成されたイメージがコンテナ内で Spark プロセスをこの UID として実行することを意味します。セキュリティを重視するデプロイメントでは、カスタムイメージに USER ディレクティブを指定して、目的の非特権 UID と GID を指定することを検討してください。生成された UID には、Spark 実行可能ファイルを実行できるように、ルートグループを補助グループに含める必要があります。提供された docker-image-tool.sh スクリプトを使用して独自のイメージをビルドするユーザーは、-u <uid> オプションを使用して目的の UID を指定できます。
または、ポッドテンプレート機能を使用して、Spark が送信するポッドに runAsUser を持つ セキュリティコンテキストを追加できます。これは、イメージ自体の USER ディレクティブをオーバーライドするために使用できます。これはユーザーからの協力が必要であり、共有環境には適さない場合があることに注意してください。クラスター管理者は、ポッドが実行できるユーザーを制限したい場合は、ポッドセキュリティポリシーを使用する必要があります。
ボリュームマウント
このドキュメントの後半の Kubernetes ボリュームの使用で説明されているように、Spark on K8S は、ドライバーおよびエグゼキューターポッドに特定のボリュームタイプをマウントできるようにする構成オプションを提供します。特に、Kubernetes ドキュメントで説明されているように、既知のセキュリティ脆弱性がある hostPath ボリュームを許可します。
クラスター管理者は、環境に合わせて hostPath ボリュームのマウント機能を制限するために、ポッドセキュリティポリシーを使用する必要があります。
前提条件
- バージョン >= 1.30 の実行中の Kubernetes クラスターと、kubectl を使用したアクセス設定。まだ動作中の Kubernetes クラスターがない場合は、minikube を使用してローカルマシンにテストクラスターを設定できます。
- DNS アドオンが有効になっている minikube の最新リリースを使用することをお勧めします。
- デフォルトの minikube 設定では、Spark アプリケーションを実行するには十分ではないことに注意してください。単一のエグゼキューターで単純な Spark アプリケーションを開始するには、3 CPU と 4GB のメモリをお勧めします。
- Spark 環境の kubernetes-client library のバージョンと、Kubernetes クラスターのバージョンとの互換性を確認してください。
- クラスター内の ポッドを一覧表示、作成、編集、削除する適切な権限を持っている必要があります。
kubectl auth can-i <list|create|edit|delete> podsを実行することで、これらのリソースを一覧表示できることを確認できます。- ドライバーポッドによって使用されるサービスアカウントの資格情報には、configmap、サービス、およびポッドを作成する権限が必要です。
- クラスターに Kubernetes DNS が構成されている必要があります。
仕組み
spark-submit を直接使用して、Spark アプリケーションを Kubernetes クラスターに送信できます。送信メカニズムは次のとおりです。
- Spark は、Kubernetes ポッド内で実行される Spark ドライバーを作成します。
- ドライバーは、Kubernetes ポッド内でも実行されるエグゼキューターを作成し、それらに接続して、アプリケーションコードを実行します。
- アプリケーションが完了すると、エグゼキューターポッドは終了してクリーンアップされますが、ドライバーポッドはログを保持し、最終的にガベージコレクションされるか手動でクリーンアップされるまで、Kubernetes API で「完了」状態のままになります。
完了状態では、ドライバーポッドは計算リソースやメモリリソースを使用しないことに注意してください。
ドライバーおよびエグゼキューターポッドのスケジューリングは Kubernetes によって処理されます。Kubernetes API への通信は fabric8 を介して行われます。設定プロパティを使用して ノードセレクター を使用して、利用可能なノードのサブセットにドライバーおよびエグゼキューターポッドをスケジュールすることが可能です。将来のリリースでは、ノード/ポッドアフィニティのようなより高度なスケジューリングヒントを使用できるようになります。
Kubernetes へのアプリケーションの送信
Docker イメージ
Kubernetes では、ユーザーはポッド内のコンテナにデプロイできるイメージを提供する必要があります。イメージは、Kubernetes がサポートするコンテナランタイム環境で実行されるようにビルドされます。Docker は、Kubernetes で頻繁に使用されるコンテナランタイム環境です。Spark (バージョン 2.3 以降) には、この目的で使用できる Dockerfile が付属していますが、個々のアプリケーションのニーズに合わせてカスタマイズすることもできます。これは、kubernetes/dockerfiles/ ディレクトリにあります。
Spark には、Kubernetes バックエンドで使用する Docker イメージをビルドして公開するために使用できる bin/docker-image-tool.sh スクリプトも付属しています。
使用例は次のとおりです。
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag build
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag push
これにより、プロジェクト提供のデフォルトの Dockerfiles を使用してビルドされます。このツールの動作をカスタマイズするための追加オプション (カスタム Dockerfiles の提供を含む) を確認するには、-h フラグを付けて実行してください。
デフォルトでは、bin/docker-image-tool.sh は JVM ジョブを実行するための Docker イメージをビルドします。追加の言語バインディング Docker イメージをビルドするには、オプトインする必要があります。
使用例は次のとおりです。
# To build additional PySpark docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -p ./kubernetes/dockerfiles/spark/bindings/python/Dockerfile build
# To build additional SparkR docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -R ./kubernetes/dockerfiles/spark/bindings/R/Dockerfile build
Apache Spark Docker イメージ (例: apache/spark:<version>) を直接使用することもできます。
クラスターモード
クラスターモードで Spark Pi を起動するには、
$ ./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=5 \
--conf spark.kubernetes.container.image=<spark-image> \
local:///path/to/examples.jar
spark-submit の --master コマンドライン引数で指定するか、アプリケーションの構成で spark.master を設定することにより、Spark マスターは k8s://<api_server_host>:<k8s-apiserver-port> の形式の URL である必要があります。HTTPS ポート 443 の場合でも、ポートは常に指定する必要があります。マスター文字列を k8s:// でプレフィックスすると、Spark アプリケーションは Kubernetes クラスターで起動し、API サーバーは api_server_url で連絡されます。URL に HTTP プロトコルが指定されていない場合、デフォルトは https になります。たとえば、マスターを k8s://example.com:443 に設定することは、k8s://https://example.com:443 に設定することと同等ですが、TLS なしで別のポートに接続するには、マスターを k8s://http://example.com:8080 に設定する必要があります。
Kubernetes モードでは、spark.app.name で指定される Spark アプリケーション名、または spark-submit の --name 引数は、ドライバーやエグゼキューターのような作成された Kubernetes リソースの名前としてデフォルトで使用されます。したがって、アプリケーション名は小文字の英数字、-、および . で構成され、英数字で始まり英数字で終わる必要があります。
Kubernetes クラスターがセットアップされている場合、API サーバー URL を見つける 1 つの方法は、kubectl cluster-info を実行することです。
$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:6443
上記の例では、特定の Kubernetes クラスターを spark-submit で使用するために、--master k8s://http://127.0.0.1:6443 を spark-submit の引数として指定できます。さらに、認証プロキシである kubectl proxy を使用して Kubernetes API と通信することも可能です。
ローカルプロキシは次のように開始できます。
$ kubectl proxy
ローカルプロキシが localhost:8001 で実行されている場合、--master k8s://http://127.0.0.1:8001 を spark-submit の引数として使用できます。最後に、上記の例では、local:// スキームを持つ特定の URI を持つ jar を指定していることに注意してください。この URI は、Docker イメージにすでに含まれている例の jar の場所です。
クライアントモード
Spark 2.4.0 以降、クライアントモードで Kubernetes 上で Spark アプリケーションを実行できるようになりました。アプリケーションがクライアントモードで実行される場合、ドライバーはポッド内または物理ホストで実行できます。クライアントモードでアプリケーションを実行する場合は、次の要因を考慮することをお勧めします。
クライアントモードのネットワーク
Spark エグゼキューターは、Spark エグゼキューターからルーティング可能なホスト名とポート経由で Spark ドライバーに接続できる必要があります。クライアントモードで Spark を動作させるために必要な特定のネットワーク構成は、セットアップごとに異なります。ドライバーを Kubernetes ポッド内で実行する場合、ヘッドレスサービスを使用して、ドライバーポッドが安定したホスト名でエグゼキューターからルーティングできるようにすることができます。ヘッドレスサービスをデプロイする際は、サービスのラベルセレクターがドライバーポッドのみに一致し、他のポッドには一致しないようにしてください。ドライバーポッドに十分にユニークなラベルを割り当て、そのラベルをヘッドレスサービスのラベルセレクターで使用することをお勧めします。ドライバーのホスト名を spark.driver.host で、Spark ドライバーのポートを spark.driver.port で指定します。
クライアントモードの実行ポッドのガベージコレクション
Spark ドライバーをポッド内で実行している場合、spark.kubernetes.driver.pod.name をそのポッドの名前に設定することを強くお勧めします。このプロパティが設定されている場合、Spark スケジューラーは OwnerReference を持つエグゼキューターポッドをデプロイします。これにより、ドライバーポッドがクラスターから削除されると、アプリケーションのエグゼキューターポッドもすべて削除されることが保証されます。ドライバーは、spark.kubernetes.namespace で指定された名前空間にある指定された名前のポッドを検索し、そのポッドへの OwnerReference が各エグゼキューターポッドの OwnerReferences リストに追加されます。ドライバーポッドではないポッドに OwnerReference を設定しないように注意してください。そうしないと、間違ったポッドが削除されたときにエグゼキューターが早期に終了する可能性があります。
アプリケーションがポッド内で実行されていない場合、またはアプリケーションが実際にポッド内で実行されているときに spark.kubernetes.driver.pod.name が設定されていない場合は、アプリケーションが終了したときにエグゼキューターポッドがクラスターから適切に削除されない可能性があることに注意してください。Spark スケジューラーはこれらのポッドの削除を試みますが、API サーバーへのネットワークリクエストが何らかの理由で失敗した場合、これらのポッドはクラスターに残ります。エグゼキュータープロセスは、ドライバーに到達できないときに終了するはずなので、アプリケーションが終了した後にエグゼキューターポッドはクラスター内の計算リソース (CPU およびメモリ) を消費しないはずです。
spark.kubernetes.executor.podNamePrefix を使用して、エグゼキューターポッド名を完全に制御できます。このプロパティが設定されている場合、同じ名前空間内のすべてのジョブで一意にすることが強く推奨されます。
認証パラメータ
クライアントモードの Kubernetes 認証パラメータには、正確なプレフィックス spark.kubernetes.authenticate を使用します。
IPv4 および IPv6
3.4.0 以降、Spark は、Pod および Service に IPv4 および IPv6 アドレスを割り当てることができる IPv4/IPv6 デュアルスタックネットワーク機能を介して、IPv6 のみ環境もサポートします。K8s クラスターの機能に応じて、spark.kubernetes.driver.service.ipFamilyPolicy および spark.kubernetes.driver.service.ipFamilies は、それぞれ SingleStack、PreferDualStack、RequireDualStack と、IPv4、IPv6、IPv4,IPv6、IPv6,IPv4 のいずれかになります。デフォルトでは、Spark は spark.kubernetes.driver.service.ipFamilyPolicy=SingleStack および spark.kubernetes.driver.service.ipFamilies=IPv4 を使用します。
IPv6 のみを SingleStack で使用するには、次のようにジョブを送信できます。
...
--conf spark.kubernetes.driver.service.ipFamilies=IPv6 \
DualStack 環境では、IPv6 を使用するために、JVM 用に java.net.preferIPv6Addresses=true、Python 用に SPARK_PREFER_IPV6=true が必要になる場合があります。
依存関係管理
アプリケーションの依存関係がすべて HDFS や HTTP サーバーのようなリモートロケーションにある場合、適切なリモート URI で参照できます。また、アプリケーションの依存関係は、カスタムビルドされた Docker イメージに事前にマウントすることもできます。これらの依存関係は、local:// URI で参照したり、Dockerfile の SPARK_EXTRA_CLASSPATH 環境変数を設定したりすることで、クラスパスに追加できます。local:// スキームは、spark-submit でカスタムビルドされた Docker イメージの依存関係を参照する場合にも必要です。送信クライアントのローカルファイルシステムからの依存関係は、file:// スキームを使用するか、スキームなし (フルパスを使用) でサポートされており、宛先は Hadoop 互換ファイルシステムである必要があります。S3 を使用する典型的な例は、次のオプションを渡すことです。
...
--packages org.apache.hadoop:hadoop-aws:3.4.1
--conf spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path
--conf spark.hadoop.fs.s3a.access.key=...
--conf spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
--conf spark.hadoop.fs.s3a.fast.upload=true
--conf spark.hadoop.fs.s3a.secret.key=....
--conf spark.driver.extraJavaOptions=-Divy.cache.dir=/tmp -Divy.home=/tmp
file:///full/path/to/app.jar
アプリの jar ファイルは S3 にアップロードされ、ドライバーが起動するときにドライバーポッドにダウンロードされてクラスパスに追加されます。Spark は、並行して実行される Spark アプリケーションとの競合を回避するために、アップロードパスの下にランダムな名前のサブディレクトリを生成します。ユーザーは必要に応じて作成されたサブディレクトリを管理できます。
クライアントモードは、アプリケーション jar、および spark.jars、spark.files、spark.archives プロパティで指定された依存関係に対してサポートされています。
重要: クライアント側のすべての依存関係は、指定されたパスにフラットなディレクトリ構造でアップロードされるため、ファイル名は一意である必要があります。そうでない場合、ファイルは上書きされます。また、派生した k8s イメージのデフォルトの ivy ディレクトリに必要なアクセス権があることを確認するか、上記のように設定を変更してください。後者は、クラスターモードで --packages を使用する場合にも重要です。
シークレット管理
Kubernetes シークレットは、Spark アプリケーションが保護されたサービスにアクセスするための認証情報を提供するために使用できます。ユーザー指定のシークレットをドライバーコンテナにマウントするには、spark.kubernetes.driver.secrets.[SecretName]=<mount path> の形式の構成プロパティを使用できます。同様に、spark.kubernetes.executor.secrets.[SecretName]=<mount path> の形式の構成プロパティを使用して、ユーザー指定のシークレットをエグゼキューターコンテナにマウントできます。マウントされるシークレットは、ドライバーおよびエグゼキューターポッドと同じ名前空間にあると想定されていることに注意してください。たとえば、spark-secret という名前のシークレットをドライバーおよびエグゼキューターコンテナの両方の /etc/secrets パスにマウントするには、spark-submit コマンドに次のオプションを追加します。
--conf spark.kubernetes.driver.secrets.spark-secret=/etc/secrets
--conf spark.kubernetes.executor.secrets.spark-secret=/etc/secrets
spark-submit コマンドの次のオプションを使用して、環境変数経由でシークレットを使用します。
--conf spark.kubernetes.driver.secretKeyRef.ENV_NAME=name:key
--conf spark.kubernetes.executor.secretKeyRef.ENV_NAME=name:key
ポッドテンプレート
Kubernetes では、テンプレートファイルからポッドを定義できます。Spark ユーザーも同様にテンプレートファイルを使用して、Spark の構成でサポートされていないドライバーまたはエグゼキューターポッドの構成を定義できます。これを行うには、spark.kubernetes.driver.podTemplateFile および spark.kubernetes.executor.podTemplateFile の Spark プロパティを指定して、spark-submit プロセスからアクセス可能なファイルを示します。
--conf spark.kubernetes.driver.podTemplateFile=s3a://bucket/driver.yml
--conf spark.kubernetes.executor.podTemplateFile=s3a://bucket/executor.yml
ドライバーポッドがエグゼキューターポッドテンプレートファイルにアクセスできるようにするために、ファイルは作成時にドライバーポッドのボリュームに自動的にマウントされます。Spark はこれらのテンプレートファイルをアンマーシャリングした後、検証を行わず、検証のために Kubernetes API サーバーに依存します。
Spark は特定のポッド構成について意見を持っているため、ポッドテンプレート内の Spark によって常に上書きされる値があることに注意することが重要です。したがって、この機能のユーザーは、ポッドテンプレートファイルを指定しても、Spark はポッド構築プロセス中に空のポッドではなくテンプレートポッドから開始できるだけであることに注意する必要があります。詳細については、Spark によって上書きされるポッドテンプレート値の完全なリストを参照してください。
ポッドテンプレートファイルは、複数のコンテナを定義することもできます。その場合、ドライバーまたはエグゼキューターのベースとして使用するコンテナを示すために、spark.kubernetes.driver.podTemplateContainerName および spark.kubernetes.executor.podTemplateContainerName の Spark プロパティを使用できます。指定しない場合、またはコンテナ名が無効な場合、Spark はリスト内の最初のコンテナがドライバーまたはエグゼキューターコンテナであると想定します。
Kubernetes ボリュームの使用
ユーザーは、ドライバーおよびエグゼキューターポッドに次の種類の Kubernetes ボリュームをマウントできます。
- hostPath: ホストノードのファイルシステムからポッドにファイルまたはディレクトリをマウントします。
- emptyDir: ポッドがノードに割り当てられたときに作成される、最初は空のボリューム。
- nfs: 既存の NFS (ネットワークファイルシステム) をポッドにマウントします。
- persistentVolumeClaim:
PersistentVolumeをポッドにマウントします。
注: ボリュームマウントに関連するセキュリティ問題については、このドキュメントのセキュリティセクションを参照してください。
上記のいずれかの種類のボリュームをドライバーポッドにマウントするには、次の構成プロパティを使用します。
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly=<true|false>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath=<mount subPath>
具体的には、VolumeType は hostPath、emptyDir、nfs、persistentVolumeClaim のいずれかの値になります。VolumeName は、ポッド仕様の volumes フィールドの下で使用したい名前です。
サポートされている各ボリュームタイプには、いくつかの特定の構成オプションがある場合があります。これらは、次の形式の構成プロパティを使用して指定できます。
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName]=<value>
たとえば、ボリューム名 images を持つ nfs のサーバーとパスは、次のプロパティを使用して指定できます。
spark.kubernetes.driver.volumes.nfs.images.options.server=example.com
spark.kubernetes.driver.volumes.nfs.images.options.path=/data
また、ボリューム名 checkpointpvc を持つ persistentVolumeClaim のクレーム名は、次のプロパティを使用して指定できます。
spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=check-point-pvc-claim
エグゼキューターポッドにボリュームをマウントするための構成プロパティは、spark.kubernetes.driver. の代わりにプレフィックス spark.kubernetes.executor. を使用します。
たとえば、OnDemand をクレーム名として、storageClass および sizeLimit オプションを使用して、エグゼキューターごとに動的に作成された永続ボリュームクレームをマウントできます。これは、動的割り当ての場合に便利です。
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.readOnly=false
サポートされている各ボリュームタイプの利用可能なオプションの完全なリストについては、以下のSpark プロパティセクションを参照してください。
PVC 中心のエグゼキューターポッド割り当て
ディスクは重要なリソースタイプの 1 つであるため、Spark ドライバーは一連の構成を通じてきめ細やかな制御を提供します。たとえば、デフォルトでは、オンデマンド PVC はエグゼキューターによって所有され、PVC のライフサイクルは所有するエグゼキューターに密接に関連付けられています。ただし、オンデマンド PVC はドライバーによって所有され、Spark ジョブの実行中に別 のエグゼキューターによって再利用できます。これは、PVC の作成と削除のオーバーヘッドを削減します。
spark.kubernetes.driver.ownPersistentVolumeClaim=true
spark.kubernetes.driver.reusePersistentVolumeClaim=true
さらに、Spark 3.4 以降、Spark ドライバーは PVC 中心のエグゼキューター割り当てを実行できるようになりました。これは、Spark がジョブが持つことができる作成済み PVC の総数をカウントし、ドライバーが最大数の PVC を所有している場合、新しいエグゼキューターの作成を保持することを意味します。これは、既存の PVC があるエグゼキューターから別 のエグゼキューターに移行するのに役立ちます。
spark.kubernetes.driver.waitToReusePersistentVolumeClaim=true
ローカルストレージ
Spark は、シャッフルやその他の操作中にデータをスピルするためにボリュームを使用できます。ボリュームをローカルストレージとして使用するには、ボリューム名を spark-local-dir- で始める必要があります。
--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.readOnly=false
具体的には、ジョブでエグゼキューターでの大規模なシャッフルおよびソート操作が必要な場合、永続ボリュームクレームを使用できます。
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.readOnly=false
組み込みの KubernetesLocalDiskShuffleDataIO プラグインを介してシャッフルデータリカバリ機能を有効にするには、次のものが必要です。spark.kubernetes.driver.waitToReusePersistentVolumeClaim を追加で有効にしたい場合があります。
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data/spark-x/executor-x
spark.shuffle.sort.io.plugin.class=org.apache.spark.shuffle.KubernetesLocalDiskShuffleDataIO
ローカルストレージとしてボリュームが設定されていない場合、Spark は一時的なスクラッチスペースを使用して、シャッフルやその他の操作中にディスクにデータをスピルします。Kubernetes をリソースマネージャーとして使用する場合、ポッドは spark.local.dir または環境変数 SPARK_LOCAL_DIRS にリストされた各ディレクトリに対して emptyDir ボリュームがマウントされた状態で作成されます。ディレクトリが明示的に指定されていない場合、デフォルトのディレクトリが作成され、適切に構成されます。
emptyDir ボリュームは、Kubernetes の一時ストレージ機能を使用し、ポッドのライフサイクルを超えて永続しません。
ローカルストレージに RAM を使用する
emptyDir ボリュームはデフォルトでノードのバックエンドストレージを一時ストレージに使用しますが、この動作は一部のコンピューティング環境には適さない場合があります。たとえば、ディスクレスノードにネットワーク経由でマウントされたリモートストレージがある場合、多くのエグゼキューターがこのリモートストレージに対して IO を行うと、パフォーマンスが低下する可能性があります。
この場合、構成で spark.kubernetes.local.dirs.tmpfs=true を設定することが望ましい場合があります。これにより、emptyDir ボリュームが tmpfs、つまり RAM バックボリュームとして構成されます。この設定で構成された場合、Spark のローカルストレージの使用量はポッドのメモリ使用量に含まれるため、spark.{driver,executor}.memoryOverheadFactor の値を適切に増やすことで、メモリリクエストを増やすことを検討してください。
イントロスペクションとデバッグ
これらは、実行中/完了した Spark アプリケーションを調査し、進捗を監視し、アクションを実行できるさまざまな方法です。
ログへのアクセス
ログは、Kubernetes API および kubectl CLI を使用してアクセスできます。Spark アプリケーションが実行されている場合、次のコマンドを使用してアプリケーションからログをストリーミングできます。
$ kubectl -n=<namespace> logs -f <driver-pod-name>
同じログは、クラスターにインストールされていれば、Kubernetes ダッシュボードからもアクセスできます。
ログ収集システムが存在する場合、Spark ドライバーの Executors タブ UI で公開できます。たとえば、
spark.ui.custom.executor.log.url='https://log-server/log?appId=&execId='
この URL テンプレートにカスタム変数を追加できます。これは、次のような既存のエグゼキューター環境変数の値で入力されます。
spark.executorEnv.SPARK_EXECUTOR_ATTRIBUTE_YOUR_VAR='$(EXISTING_EXECUTOR_ENV_VAR)'
spark.ui.custom.executor.log.url='https://log-server/log?appId=&execId=&your_var='
ドライバー UI へのアクセス
アプリケーションに関連付けられた UI は、kubectl port-forward を使用してローカルでアクセスできます。
$ kubectl port-forward <driver-pod-name> 4040:4040
次に、Spark ドライバー UI は https://:4040 でアクセスできます。
Apache Spark 4.0.0 以降、Driver UI は新しい構成を通じてドライバーログを表示する方法を提供します。
spark.driver.log.localDir=/tmp
次に、Spark ドライバー UI は https://:4040/logs/ でアクセスできます。オプションで、ログのレイアウトは次のように構成されます。
spark.driver.log.layout="%m%n%ex"
デバッグ
いくつかの種類の障害が発生する可能性があります。Spark API サーバーが spark-submit からのリクエストを拒否した場合、または別の理由で接続が拒否された場合、送信ロジックは検出されたエラーを示します。ただし、アプリケーションの実行中にエラーが発生した場合、多くの場合、調査の最良の方法は Kubernetes CLI を介して行うことです。
ドライバーポッドの周りのスケジューリング決定に関する基本的な情報を取得するには、次を実行します。
$ kubectl describe pod <spark-driver-pod>
ポッドが実行時エラーに遭遇した場合、ステータスは次を使用してさらにプローブできます。
$ kubectl logs <spark-driver-pod>
失敗したエグゼキューターポッドのステータスとログは、同様の方法で確認できます。最後に、ドライバーポッドを削除すると、すべて のエグゼキューター、関連するサービスなど、Spark アプリケーション全体がクリーンアップされます。ドライバーポッドは、Spark アプリケーションの Kubernetes 表現と見なすことができます。
Kubernetes の機能
設定ファイル
Kubernetes 設定ファイルは通常、ホームディレクトリの .kube/config または KUBECONFIG 環境変数で指定された場所にあります。Spark on Kubernetes は、このファイルを使用して Kubernetes クラスターと対話するために使用される Kubernetes クライアントの初期自動構成を試みます。さまざまな Spark 構成プロパティが提供されており、クライアント構成をさらにカスタマイズできます (例: 別の認証方法の使用)。
コンテキスト
Kubernetes 設定ファイルには、複数のコンテキストを含めることができ、これにより異なるクラスターやユーザー ID を切り替えることができます。デフォルトでは、Spark on Kubernetes は、Kubernetes クライアントの初期自動構成を行う際に、現在のコンテキスト (これは kubectl config current-context を実行して確認できます) を使用します。
別のコンテキストを使用するために、ユーザーは Spark 構成プロパティ spark.kubernetes.context を介して目的のコンテキストを指定できます。たとえば、spark.kubernetes.context=minikube です。
名前空間
Kubernetes には 名前空間の概念があります。名前空間は、クラスターリソースを複数のユーザー間で分割する方法 (リソースクォータを介して) です。Spark on Kubernetes は、名前空間を使用して Spark アプリケーションを起動できます。これは、spark.kubernetes.namespace 構成を通じて利用できます。
Kubernetes では、リソースクォータを使用して、個々の名前空間のリソース、オブジェクト数などに制限を設定できます。管理者 は、Spark アプリケーションを実行する Kubernetes クラスターでの共有とリソース割り当てを制御するために、名前空間とリソースクォータを組み合わせて使用できます。
RBAC
RBAC が有効になっている Kubernetes クラスターでは、ユーザーはさまざまな Spark on Kubernetes コンポーネントが Kubernetes API サーバーにアクセスするために使用する Kubernetes RBAC ロールとサービスアカウントを構成できます。
Spark ドライバーポッドは、Kubernetes サービスアカウントを使用して Kubernetes API サーバーにアクセスし、エグゼキューターポッドを作成および監視します。ドライバーポッドによって使用されるサービスアカウントには、ドライバーがその作業を実行できるように、適切な権限が必要です。具体的には、少なくとも、サービスアカウントには、ドライバーがポッドとサービスを作成できるようにする Role または ClusterRole を付与する必要があります。デフォルトでは、ポッドが作成されるときにサービスアカウントが指定されていない場合、ドライバーポッドには spark.kubernetes.namespace で指定された名前空間の default サービスアカウントが自動的に割り当てられます。
デプロイされた Kubernetes のバージョンとセットアップによっては、この default サービスアカウントが、デフォルトの Kubernetes RBAC ポリシーの下でドライバーポッドがポッドとサービスを作成できるようにするロールを持っている場合とそうでない場合があります。場合によっては、適切なロールが付与されたカスタムサービスアカウントを指定する必要があるユーザーがいます。Spark on Kubernetes は、構成プロパティ spark.kubernetes.authenticate.driver.serviceAccountName=<service account name> を介して、ドライバーポッドで使用されるカスタムサービスアカウントを指定することをサポートしています。たとえば、ドライバーポッドに spark サービスアカウントを使用させるには、ユーザーは spark-submit コマンドに次のオプションを追加します。
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark
カスタムサービスアカウントを作成するには、ユーザーは kubectl create serviceaccount コマンドを使用できます。たとえば、次のコマンドは spark という名前のサービスアカウントを作成します。
$ kubectl create serviceaccount spark
サービスアカウントに Role または ClusterRole を付与するには、RoleBinding または ClusterRoleBinding が必要です。RoleBinding または ClusterRoleBinding を作成するには、ユーザーは kubectl create rolebinding (または ClusterRoleBinding の場合は clusterrolebinding) コマンドを使用できます。たとえば、次のコマンドは default 名前空間に edit ClusterRole を作成し、それを上記で作成した spark サービスアカウントに付与します。
$ kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
注意: Role は、単一の名前空間内のリソース (ポッドなど) へのアクセスを許可するためにのみ使用できますが、ClusterRole は、クラスター全体のリソース (ノードなど) と名前空間リソース (ポッドなど) の両方に、すべての名前空間にわたってアクセスを許可するために使用できます。Spark on Kubernetes では、ドライバーは常に同じ名前空間にエグゼキューターポッドを作成するため、Role で十分ですが、ユーザーは代わりに ClusterRole を使用することもできます。RBAC 承認の詳細およびポッドの Kubernetes サービスアカウントの構成方法については、RBAC 承認の使用およびポッドのサービスアカウントの構成を参照してください。
Spark アプリケーション管理
Kubernetes は、クラスターモードの spark-submit CLI ツールを介して簡単なアプリケーション管理を提供します。ユーザーは、ジョブを送信したときに表示される送信 ID を指定することで、ジョブをキルできます。送信 ID は namespace:driver-pod-name の形式に従います。ユーザーが名前空間を省略した場合、現在の k8s コンテキストで設定されている名前空間が使用されます。たとえば、ユーザーが次のように特定の名前空間を設定した場合、kubectl config set-context minikube --namespace=spark、デフォルトで spark 名前空間が使用されます。一方、特定のコンテキストに名前空間が追加されていない場合、すべての名前空間がデフォルトで考慮されます。これは、操作が指定された送信 ID に一致するすべての Spark アプリケーションに影響することを意味します。さらに、アプリケーション管理用の spark-submit は、ドライバーの送信に使用されるものと同じバックエンドコードを使用するため、spark.kubernetes.context などの同じプロパティを再利用できます。
例
$ spark-submit --kill spark:spark-pi-1547948636094-driver --master k8s://https://192.168.2.8:8443
ユーザーは --status フラグを使用してアプリケーションのステータスを一覧表示することもできます。
$ spark-submit --status spark:spark-pi-1547948636094-driver --master k8s://https://192.168.2.8:8443
両方の操作はグロブパターンをサポートしています。たとえば、ユーザーは次を実行できます。
$ spark-submit --kill spark:spark-pi* --master k8s://https://192.168.2.8:8443
上記は、指定されたプレフィックスを持つすべてのアプリケーションをキルします。
ユーザーは、--conf を介して提供することで、spark.kubernetes.appKillPodDeletionGracePeriod プロパティを使用してポッド終了の猶予期間を指定できます (すべての K8s ポッドのデフォルト値は 30 秒)。
今後の作業
現在開発中または開発が計画されている Spark on Kubernetes の機能がいくつかあります。これらの機能は、将来の Spark-Kubernetes 統合バージョンに最終的に取り込まれることが期待されます。
それらの一部は次のとおりです。
- 外部シャッフルサービス
- ジョブキューおよびリソース管理
設定
Spark の構成については、構成ページを参照してください。以下の構成は Spark on Kubernetes に固有のものです。
Spark プロパティ
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.kubernetes.context |
(なし) |
Kubernetes クライアントライブラリの初期自動構成に使用される、ユーザー Kubernetes 設定ファイルからのコンテキスト。指定しない場合は、ユーザーの現在のコンテキストが使用されます。注: 自動構成された設定の多くは、他の Spark 構成プロパティ (例: spark.kubernetes.namespace) の使用によってオーバーライドできます。 |
3.0.0 |
spark.kubernetes.driver.master |
https://kubernetes.default.svc |
ドライバーがエグゼキューターを要求するために使用される内部 Kubernetes マスター (API サーバー) アドレス、またはドライバーポッドのみのモードの場合は 'local[*]'。 | 3.0.0 |
spark.kubernetes.namespace |
default |
ドライバーおよびエグゼキューターポッドの実行に使用される名前空間。 | 2.3.0 |
spark.kubernetes.container.image |
(なし) |
Spark アプリケーションに使用するコンテナイメージ。通常は example.com/repo/spark:v1.0.0 の形式です。この構成は必須であり、各異なるコンテナタイプに明示的なイメージが提供されない限り、ユーザーが提供する必要があります。 |
2.3.0 |
spark.kubernetes.driver.container.image |
(spark.kubernetes.container.image の値) |
ドライバーに使用するカスタムコンテナイメージ。 | 2.3.0 |
spark.kubernetes.executor.container.image |
(spark.kubernetes.container.image の値) |
エグゼキューターに使用するカスタムコンテナイメージ。 | 2.3.0 |
spark.kubernetes.container.image.pullPolicy |
IfNotPresent |
Kubernetes 内でイメージをプルする際に使用されるコンテナイメージプルポリシー。有効な値は Always、Never、および IfNotPresent です。 |
2.3.0 |
spark.kubernetes.container.image.pullSecrets |
|
プライベートイメージレジストリからイメージをプルするために使用される Kubernetes シークレットのカンマ区切りリスト。 | 2.4.0 |
spark.kubernetes.allocation.batch.size |
10 |
エグゼキューターポッド割り当ての各ラウンドで一度に起動するポッドの数。 | 2.3.0 |
spark.kubernetes.allocation.batch.delay |
1s |
エグゼキューターポッド割り当ての各ラウンドの間に待機する時間。1 秒未満の値を指定すると、Spark ドライバーで過剰な CPU 使用率が発生する可能性があります。 | 2.3.0 |
spark.kubernetes.jars.avoidDownloadSchemes |
(なし) |
Spark on Kubernetes デプロイメントの場合にのみ、jars がエグゼキューターに配布される前にドライバーのローカルディスクにダウンロードされないスキームのカンマ区切りリスト。jars が大きい場合やエグゼキューターの数が多い場合、同時ダウンロードがネットワークの飽和とタイムアウトを引き起こす状況で使用します。ワイルドカード '*' は、どのスキームに対しても jars をダウンロードしないことを示します。 | 4.0.0 |
spark.kubernetes.authenticate.submission.caCertFile |
(なし) | ドライバーの起動時に TLS 経由で Kubernetes API サーバーに接続するための CA 証明書ファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.caCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.submission.clientKeyFile |
(なし) | ドライバーの起動時に Kubernetes API サーバーに対する認証に使用するクライアントキーファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientKeyFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.submission.clientCertFile |
(なし) | ドライバーの起動時に Kubernetes API サーバーに対する認証に使用するクライアント証明書ファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.submission.oauthToken |
(なし) | ドライバーの起動時に Kubernetes API サーバーに対する認証に使用する OAuth トークン。他の認証オプションとは異なり、これは認証に使用するトークンの正確な文字列値であることが期待されます。クライアントモードでは、代わりに spark.kubernetes.authenticate.oauthToken を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.submission.oauthTokenFile |
(なし) | ドライバーの起動時に Kubernetes API サーバーに対する認証に使用するトークンを含む OAuth トークンファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.oauthTokenFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.caCertFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に TLS 経由で Kubernetes API サーバーに接続するための CA 証明書ファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があり、ドライバーポッドにアップロードされます。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.caCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.clientKeyFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアントキーファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があり、ドライバーポッドに Kubernetes シークレットとしてアップロードされます。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientKeyFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.clientCertFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアント証明書ファイルのパス。このファイルは、送信マシン上のディスクに配置する必要があり、ドライバーポッドに Kubernetes シークレットとしてアップロードされます。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.oauthToken |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用する OAuth トークン。他の認証オプションとは異なり、これは認証に使用するトークンの正確な文字列値である必要があります。このトークン値は、Kubernetes シークレットとしてドライバーポッドにアップロードされます。クライアントモードでは、代わりに spark.kubernetes.authenticate.oauthToken を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.oauthTokenFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するトークンを含む OAuth トークンファイルのパス。他の認証オプションとは異なり、このファイルには認証に使用するトークンの正確な文字列値が含まれている必要があります。このトークン値はシークレットとしてドライバーポッドにアップロードされます。クライアントモードでは、代わりに spark.kubernetes.authenticate.oauthTokenFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.mounted.caCertFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に TLS 経由で Kubernetes API サーバーに接続するための CA 証明書ファイルのパス。このパスはドライバーポッドからアクセス可能である必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.caCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.mounted.clientKeyFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアントキーファイルのパス。このパスはドライバーポッドからアクセス可能である必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientKeyFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.mounted.clientCertFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアント証明書ファイルのパス。このパスはドライバーポッドからアクセス可能である必要があります。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。クライアントモードでは、代わりに spark.kubernetes.authenticate.clientCertFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.mounted.oauthTokenFile |
(なし) | ドライバーポッドからエグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用する OAuth トークンを含むファイルのパス。このパスはドライバーポッドからアクセス可能である必要があります。他の認証オプションとは異なり、このファイルには認証に使用するトークンの正確な文字列値が含まれている必要があります。クライアントモードでは、代わりに spark.kubernetes.authenticate.oauthTokenFile を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.driver.serviceAccountName |
default |
ドライバーポッドの実行に使用されるサービスアカウント。ドライバーポッドは、API サーバーからエグゼキューターポッドを要求する際にこのサービスアカウントを使用します。CA 証明書ファイル、クライアントキーファイル、クライアント証明書ファイル、および/または OAuth トークンと同時に指定することはできません。クライアントモードでは、代わりに spark.kubernetes.authenticate.serviceAccountName を使用してください。 |
2.3.0 |
spark.kubernetes.authenticate.executor.serviceAccountName |
(spark.kubernetes.driver.serviceAccountName の値) |
エグゼキューターポッドの実行に使用されるサービスアカウント。このパラメータが設定されていない場合、フォールバックロジックはドライバーのサービスアカウントを使用します。 | 3.1.0 |
spark.kubernetes.authenticate.caCertFile |
(なし) | クライアントモードで、エグゼキューターを要求する際に TLS 経由で Kubernetes API サーバーに接続するための CA 証明書ファイルのパス。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。 | 2.4.0 |
spark.kubernetes.authenticate.clientKeyFile |
(なし) | クライアントモードで、エグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアントキーファイルのパス。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。 | 2.4.0 |
spark.kubernetes.authenticate.clientCertFile |
(なし) | クライアントモードで、エグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用するクライアント証明書ファイルのパス。URI ではなくパスとして指定してください (つまり、スキームを提供しないでください)。 | 2.4.0 |
spark.kubernetes.authenticate.oauthToken |
(なし) | クライアントモードで、エグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用する OAuth トークン。他の認証オプションとは異なり、これは認証に使用するトークンの正確な文字列値である必要があります。 | 2.4.0 |
spark.kubernetes.authenticate.oauthTokenFile |
(なし) | クライアントモードで、エグゼキューターを要求する際に Kubernetes API サーバーに対する認証に使用する OAuth トークンを含むファイルのパス。 | 2.4.0 |
spark.kubernetes.driver.label.[LabelName] |
(なし) | ドライバーポッドに、LabelName で指定されたラベルを追加します。たとえば、spark.kubernetes.driver.label.something=true です。Spark も、管理目的でドライバーポッドに独自のラベルを追加することに注意してください。 |
2.3.0 |
spark.kubernetes.driver.annotation.[AnnotationName] |
(なし) | AnnotationName で指定された Kubernetes アノテーションをドライバーポッドに追加します。たとえば、spark.kubernetes.driver.annotation.something=true です。 |
2.3.0 |
spark.kubernetes.driver.service.label.[LabelName] |
(なし) | LabelName で指定された Kubernetes ラベルをドライバーサービスに追加します。たとえば、spark.kubernetes.driver.service.label.something=true です。Spark も、管理目的でドライバーサービスに独自のラベルを追加することに注意してください。 |
3.4.0 |
spark.kubernetes.driver.service.annotation.[AnnotationName] |
(なし) | AnnotationName で指定された Kubernetes アノテーションをドライバーサービスに追加します。たとえば、spark.kubernetes.driver.service.annotation.something=true です。 |
3.0.0 |
spark.kubernetes.executor.label.[LabelName] |
(なし) | エグゼキューターポッドに、LabelName で指定されたラベルを追加します。たとえば、spark.kubernetes.executor.label.something=true です。Spark も、管理目的でエグゼキューターポッドに独自のラベルを追加することに注意してください。 |
2.3.0 |
spark.kubernetes.executor.annotation.[AnnotationName] |
(なし) | AnnotationName で指定された Kubernetes アノテーションをエグゼキューターポッドに追加します。たとえば、spark.kubernetes.executor.annotation.something=true です。 |
2.3.0 |
spark.kubernetes.driver.pod.name |
(なし) | ドライバーポッドの名前。クラスターモードでは、これが設定されていない場合、ドライバーポッド名は名前の競合を避けるために現在のタイムスタンプでサフィックスされた "spark.app.name" に設定されます。クライアントモードでは、アプリケーションがポッド内で実行されている場合、ドライバーが実行されているポッドの名前にこれを設定することを強くお勧めします。クライアントモードでこの値を設定すると、ドライバーはエグゼキューターポッドの所有者になり、これによりエグゼキューターポッドがクラスターによってガベージコレクションできるようになります。 | 2.3.0 |
spark.kubernetes.executor.podNamePrefix |
(なし) | エグゼキューターポッド名の前に使用するプレフィックス。Kubernetes の DNS ラベル名で定義されたルールに準拠する必要があります。プレフィックスは、$podNamePrefix-exec-$id の形式でエグゼキューターポッド名を生成するために使用されます。ここで、`id` は正の整数値なので、`podNamePrefix` の長さは 47 (= 63 - 10 - 6) 以下である必要があります。 |
2.3.0 |
spark.kubernetes.submission.waitAppCompletion |
true |
クラスターモードで、ランチャープロセスを終了する前にアプリケーションの完了を待つかどうか。false に変更すると、ランチャーは Spark ジョブの起動時に「ファイア・アンド・フォーゲット」の動作をします。 | 2.3.0 |
spark.kubernetes.report.interval |
1s |
クラスターモードでの現在の Spark ジョブステータスのレポート間の間隔。 | 2.3.0 |
spark.kubernetes.executor.apiPollingInterval |
30s |
エグゼキューターの状態を検査するために Kubernetes API サーバーをポーリングする間隔。 | 2.4.0 |
spark.kubernetes.driver.request.cores |
(なし) | ドライバーポッドの CPU リクエストを指定します。値は Kubernetes の 規約に準拠します。例として 0.1、500m、1.5、5 などがあり、CPU ユニットの定義は CPU ユニットに記載されています。これが設定されている場合、ドライバーポッドの CPU リクエストを指定するために spark.driver.cores よりも優先されます。 |
3.0.0 |
spark.kubernetes.driver.limit.cores |
(なし) | ドライバーポッドのハード CPU 制限を指定します。 | 2.3.0 |
spark.kubernetes.executor.request.cores |
(なし) | 各エグゼキューターポッドの CPU リクエストを指定します。値は Kubernetes の 規約に準拠します。例として 0.1、500m、1.5、5 などがあり、CPU ユニットの定義は CPU ユニットに記載されています。これは spark.executor.cores とは異なります。設定されている場合、エグゼキューターポッドの CPU リクエストを指定するために spark.executor.cores よりも優先されます。タスクの並列度、つまりエグゼキューターが同時に実行できるタスクの数は、これに影響されません。 |
2.4.0 |
spark.kubernetes.executor.limit.cores |
(なし) | Spark アプリケーション用に起動された各エグゼキューターポッドのハード CPU 制限を指定します。 | 2.3.0 |
spark.kubernetes.node.selector.[labelKey] |
(なし) | キー labelKey および値として構成の値を持つ、ドライバーポッドおよびエグゼキューターポッドのノードセレクターに追加します。たとえば、spark.kubernetes.node.selector.identifier を myIdentifier に設定すると、ドライバーポッドとエグゼキューターはキー identifier および値 myIdentifier を持つノードセレクターを持つことになります。複数のノードセレクターキーは、このプレフィックスを持つ複数の構成を設定することで追加できます。 |
2.3.0 |
spark.kubernetes.driver.node.selector.[labelKey] |
(なし) | キー labelKey および値として構成の値を持つ、ドライバーポッドのドライバーノードセレクターに追加します。たとえば、spark.kubernetes.driver.node.selector.identifier を myIdentifier に設定すると、ドライバーポッドはキー identifier および値 myIdentifier を持つノードセレクターを持つことになります。複数のドライバーノードセレクターキーは、このプレフィックスを持つ複数の構成を設定することで追加できます。 |
3.3.0 |
spark.kubernetes.executor.node.selector.[labelKey] |
(なし) | キー labelKey および値として構成の値を持つ、エグゼキューターポッドのエグゼキューターノードセレクターに追加します。たとえば、spark.kubernetes.executor.node.selector.identifier を myIdentifier に設定すると、エグゼキューターはキー identifier および値 myIdentifier を持つノードセレクターを持つことになります。複数のエグゼキューターノードセレクターキーは、このプレフィックスを持つ複数の構成を設定することで追加できます。 |
3.3.0 |
spark.kubernetes.driverEnv.[EnvironmentVariableName] |
(なし) | EnvironmentVariableName で指定された環境変数をドライバープロセスに追加します。ユーザーは、複数の環境変数を設定するために、これらを複数指定できます。 |
2.3.0 |
spark.kubernetes.driver.secrets.[SecretName] |
(なし) | 値で指定されたパスに、SecretName という名前の Kubernetes シークレットをドライバーポッドに追加します。たとえば、spark.kubernetes.driver.secrets.spark-secret=/etc/secrets です。 |
2.3.0 |
spark.kubernetes.executor.secrets.[SecretName] |
(なし) | 値で指定されたパスに、SecretName という名前の Kubernetes シークレットをエグゼキューターポッドに追加します。たとえば、spark.kubernetes.executor.secrets.spark-secret=/etc/secrets です。 |
2.3.0 |
spark.kubernetes.driver.secretKeyRef.[EnvName] |
(なし) | EnvName (大文字小文字を区別) という名前の環境変数として、参照されている Kubernetes シークレットのデータ内の key によって参照される値を、ドライバーコンテナに追加します。たとえば、spark.kubernetes.driver.secretKeyRef.ENV_VAR=spark-secret:key です。 |
2.4.0 |
spark.kubernetes.executor.secretKeyRef.[EnvName] |
(なし) | EnvName (大文字小文字を区別) という名前の環境変数として、参照されている Kubernetes シークレットのデータ内の key によって参照される値を、エグゼキューターコンテナに追加します。たとえば、spark.kubernetes.executor.secrets.ENV_VAR=spark-secret:key です。 |
2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path |
(なし) | 値で指定されたパスに、VolumeType タイプで VolumeName という名前の Kubernetes ボリュームをドライバーポッドに追加します。たとえば、spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint です。 |
2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath |
(なし) | ボリュームからドライバーポッドにマウントされる サブパスを指定します。spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint。 |
3.0.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly |
(なし) | マウントされたボリュームが読み取り専用かどうかを指定します。たとえば、spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false です。 |
2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName] |
(なし) | OptionName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームオプションを構成します。Kubernetes オプション形式に準拠する必要があります。たとえば、spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim です。 |
2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].label.[LabelName] |
(なし) | LabelName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームラベルを構成します。Kubernetes ラベル形式に準拠する必要があります。たとえば、spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.label.foo=bar です。 |
4.0.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].annotation.[AnnotationName] |
(なし) | AnnotationName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームアノテーションを構成します。Kubernetes アノテーション形式に準拠する必要があります。たとえば、spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.annotation.foo=bar です。 |
4.0.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.path |
(なし) | 値で指定されたパスに、VolumeType タイプで VolumeName という名前の Kubernetes ボリュームをエグゼキューターポッドに追加します。たとえば、spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint です。 |
2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.subPath |
(なし) | ボリュームからエグゼキューターポッドにマウントされる サブパスを指定します。spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint。 |
3.0.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.readOnly |
false | マウントされたボリュームが読み取り専用かどうかを指定します。たとえば、spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false です。 |
2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].options.[OptionName] |
(なし) | OptionName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームオプションを構成します。たとえば、spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim です。 |
2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].label.[LabelName] |
(なし) | LabelName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームラベルを構成します。Kubernetes ラベル形式に準拠する必要があります。たとえば、spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.label.foo=bar です。 |
4.0.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].annotation.[AnnotationName] |
(なし) | AnnotationName をキーとして指定された値を持つ Kubernetes に渡される Kubernetes ボリュームアノテーションを構成します。Kubernetes アノテーション形式に準拠する必要があります。たとえば、spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.annotation.foo=bar です。 |
4.0.0 |
spark.kubernetes.local.dirs.tmpfs |
false |
Spark ドライバーおよびエグゼキューターポッド内の SPARK_LOCAL_DIRS をバックアップするために使用される emptyDir ボリュームを tmpfs バック、つまり RAM を使用するように構成します。この項については、このページのローカルストレージでさらに説明しています。 |
3.0.0 |
spark.kubernetes.memoryOverheadFactor |
0.1 |
これは、オフヒープメモリ割り当て、非 JVM タスク、さまざまなシステムプロセス、および spark.kubernetes.local.dirs.tmpfs が true の場合の tmpfs ベースのローカルディレクトリなど、JVM 以外のメモリにメモリを割り当てるメモリオーバーヘッドファクターを設定します。JVM ベースのジョブの場合、この値はデフォルトで 0.10、非 JVM ジョブの場合は 0.40 になります。これは、非 JVM タスクはより多くの非 JVM ヒープスペースを必要とし、そのようなタスクは「メモリオーバーヘッド超過」エラーで失敗することが多いためです。これは、より高いデフォルト値でこのエラーを回避します。これは、spark.driver.memoryOverheadFactor および spark.executor.memoryOverheadFactor によって明示的に設定された値によってオーバーライドされます。 |
2.4.0 |
spark.kubernetes.pyspark.pythonVersion |
"3" |
これは、ドライバーおよびエグゼキューターコンテナの実行に使用されるDockerイメージのメジャーPythonバージョンを設定します。指定できるのは「3」のみです。この構成はSpark 3.1.0で非推奨となり、実質的に何もしません。ユーザーは、`spark.pyspark.python`および`spark.pyspark.driver.python`構成、または`PYSPARK_PYTHON`および`PYSPARK_DRIVER_PYTHON`環境変数を設定する必要があります。 | 2.4.0 |
spark.kubernetes.kerberos.krb5.path |
(なし) |
Kerberosインタラクションのためにドライバーおよびエグゼキューターにマウントされる`krb5.conf`ファイルのローカルパスを指定します。定義されたKDCがコンテナ内から可視である必要があることに注意してください。 | 3.0.0 |
spark.kubernetes.kerberos.krb5.configMapName |
(なし) |
Kerberosインタラクションのためにドライバーおよびエグゼキューターにマウントされる、`krb5.conf`ファイルを含むConfigMapの名前を指定します。定義されたKDCがコンテナ内から可視である必要があります。ConfigMapは、ドライバーおよびエグゼキューターポッドと同じ名前空間にある必要があります。 | 3.0.0 |
spark.kubernetes.hadoop.configMapName |
(なし) |
カスタムHadoop構成のためにドライバーおよびエグゼキューターにマウントされる、`HADOOP_CONF_DIR`ファイルを含むConfigMapの名前を指定します。 | 3.0.0 |
spark.kubernetes.kerberos.tokenSecret.name |
(なし) |
既存のデリゲーショントークンが格納されているSecretの名前を指定します。これにより、ジョブユーザーがジョブ起動のためにKerberos認証情報を提供する必要がなくなります。 | 3.0.0 |
spark.kubernetes.kerberos.tokenSecret.itemKey |
(なし) |
既存のデリゲーショントークンが格納されているデータのアイテムキーを指定します。これにより、ジョブユーザーがジョブ起動のためにKerberos認証情報を提供する必要がなくなります。 | 3.0.0 |
spark.kubernetes.driver.podTemplateFile |
(なし) | ドライバーのポッドテンプレートを含むローカルファイルを指定します。例:spark.kubernetes.driver.podTemplateFile=/path/to/driver-pod-template.yaml |
3.0.0 |
spark.kubernetes.driver.podTemplateContainerName |
(なし) | 指定されたポッドテンプレートでドライバーのベースとして使用されるコンテナ名を指定します。例:spark.kubernetes.driver.podTemplateContainerName=spark-driver |
3.0.0 |
spark.kubernetes.executor.podTemplateFile |
(なし) | エグゼキューターのポッドテンプレートを含むローカルファイルを指定します。例:spark.kubernetes.executor.podTemplateFile=/path/to/executor-pod-template.yaml |
3.0.0 |
spark.kubernetes.executor.podTemplateContainerName |
(なし) | 指定されたポッドテンプレートでエグゼキューターのベースとして使用されるコンテナ名を指定します。例:spark.kubernetes.executor.podTemplateContainerName=spark-executor |
3.0.0 |
spark.kubernetes.executor.deleteOnTermination |
true | 障害または正常終了の場合にエグゼキューターポッドを削除するかどうかを指定します。 | 3.0.0 |
spark.kubernetes.executor.checkAllContainers |
true |
ポッドのステータスを判断する際に、エグゼキューターポッドがすべて(サイドカーを含む)のコンテナをチェックするか、エグゼキューターコンテナのみをチェックするかを指定します。 | 3.1.0 |
spark.kubernetes.submission.connectionTimeout |
10000 |
ドライバーの起動に使用されるKubernetesクライアントの接続タイムアウト(ミリ秒)。 | 3.0.0 |
spark.kubernetes.submission.requestTimeout |
10000 |
ドライバーの起動に使用されるKubernetesクライアントのリクエストタイムアウト(ミリ秒)。 | 3.0.0 |
spark.kubernetes.trust.certificates |
false |
trueに設定されている場合、クライアントはトークンのみでKubernetesクラスタにサブミットできます。 | 3.2.0 |
spark.kubernetes.driver.connectionTimeout |
10000 |
エグゼキューターをリクエストする際にドライバー内のKubernetesクライアントが使用する接続タイムアウト(ミリ秒)。 | 3.0.0 |
spark.kubernetes.driver.requestTimeout |
10000 |
エグゼキューターをリクエストする際にドライバー内のKubernetesクライアントが使用するリクエストタイムアウト(ミリ秒)。 | 3.0.0 |
spark.kubernetes.appKillPodDeletionGracePeriod |
(なし) | `spark-submit`を使用してSparkアプリケーションを削除する際の猶予期間(秒)。 | 3.0.0 |
spark.kubernetes.dynamicAllocation.deleteGracePeriod |
5s |
強制終了する前に、エグゼキューターが正常にシャットダウンするのを待つ時間。 | 3.0.0 |
spark.kubernetes.file.upload.path |
(なし) | クラスタモードでSparkサブミット側でファイルを保存するパス。例:spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path ファイルは `file://path/to/file` または絶対パスとして指定する必要があります。 |
3.0.0 |
spark.kubernetes.executor.decommissionLabel |
(なし) | 終了中または非アクティブ化中のポッドに適用されるラベル。ポッドの中断予算、削除コストなどに使用することを意図しています。 | 3.3.0 |
spark.kubernetes.executor.decommissionLabelValue |
(なし) | `spark.kubernetes.executor.decommissionLabel`が有効な場合にラベルに適用される値。 | 3.3.0 |
spark.kubernetes.executor.scheduler.name |
(なし) | 各エグゼキューターポッドのスケジューラー名を指定します。 | 3.0.0 |
spark.kubernetes.driver.scheduler.name |
(なし) | ドライバーポッドのスケジューラー名を指定します。 | 3.3.0 |
spark.kubernetes.scheduler.name |
(なし) | ドライバーポッドおよびエグゼキューターポッドのスケジューラー名を指定します。`spark.kubernetes.driver.scheduler.name`または`spark.kubernetes.executor.scheduler.name`が設定されている場合、この設定を上書きします。 | 3.3.0 |
spark.kubernetes.configMap.maxSize |
1048576 |
ConfigMapの最大サイズ制限。これは、k8sサーバー側の制限に応じて構成可能です。 | 3.1.0 |
spark.kubernetes.executor.missingPodDetectDelta |
30s |
登録済みのエグゼキューターのPODがKubernetes APIサーバーのPODリストで検出されなくなった場合、このデルタ時間は登録時刻とポーリング時刻の間の許容される時間差と見なされます。この時間を経過してもPODが見つからない場合、PODはクラスタから欠落していると見なされ、エグゼキューターは削除されます。 | 3.1.1 |
spark.kubernetes.decommission.script |
/opt/decom.sh |
正常な非アクティブ化に使用するスクリプトの場所。 | 3.2.0 |
spark.kubernetes.driver.service.deleteOnTermination |
true |
trueの場合、Sparkアプリケーション終了時にドライバーサービスは削除されます。falseの場合、ドライバーポッドの削除時にクリーンアップされます。 | 3.2.0 |
spark.kubernetes.driver.service.ipFamilyPolicy |
SingleStack |
ドライバーサービス用のK8s IPファミリーポリシー。有効な値は `SingleStack`、`PreferDualStack`、および `RequireDualStack` です。 | 3.4.0 |
spark.kubernetes.driver.service.ipFamilies |
IPv4 |
K8sドライバーサービス用のIPファミリーのリスト。有効な値は `IPv4` および `IPv6` です。 | 3.4.0 |
spark.kubernetes.driver.ownPersistentVolumeClaim |
true |
trueの場合、ドライバーポッドは、エグゼキューターポッドの代わりにオンデマンド永続ボリュームクレームの所有者になります。 | 3.2.0 |
spark.kubernetes.driver.reusePersistentVolumeClaim |
true |
trueの場合、ドライバーポッドは、削除されたエグゼキューターポッドが所有するオンデマンド永続ボリュームクレーム(存在する場合)を再利用しようとします。これは、永続ボリュームの作成をスキップすることでエグゼキューターポッドの作成遅延を短縮するのに役立ちます。`Terminating` ステータスのポッドは定義上削除されたポッドではなく、永続ボリュームクレームを含むリソースはまだ再利用可能ではないことに注意してください。Sparkは、再利用可能なものが存在しない場合に新しい永続ボリュームクレームを作成します。つまり、永続ボリュームクレームの総数が実行中のエグゼキューターの数よりも大きくなる場合があります。この設定には `spark.kubernetes.driver.ownPersistentVolumeClaim=true` が必要です。 | 3.2.0 |
spark.kubernetes.driver.waitToReusePersistentVolumeClaim |
false |
trueの場合、ドライバーポッドは作成されたオンデマンド永続ボリュームクレームの数をカウントし、その数がSparkジョブが持つことができるボリュームの総数以上である場合、待機します。この設定には `spark.kubernetes.driver.ownPersistentVolumeClaim=true` および `spark.kubernetes.driver.reusePersistentVolumeClaim=true` の両方が必要です。 | 3.4.0 |
spark.kubernetes.executor.disableConfigMap |
false |
trueの場合、エグゼキューターのConfigMap作成を無効にします。 | 3.2.0 |
spark.kubernetes.driver.pod.featureSteps |
(なし) | `KubernetesFeatureConfigStep`を実装する追加のドライバーポッド機能ステップのクラス名。これは開発者APIです。カンマ区切り。Sparkの内部機能ステップの後に実行されます。3.3.0以降、ドライバー機能ステップは`KubernetesDriverCustomFeatureConfigStep`を実装でき、ドライバー構成も利用可能になります。 | 3.2.0 |
spark.kubernetes.executor.pod.featureSteps |
(なし) | `KubernetesFeatureConfigStep`を実装する追加のエグゼキューターポッド機能ステップのクラス名。これは開発者APIです。カンマ区切り。Sparkの内部機能ステップの後に実行されます。3.3.0以降、エグゼキューター機能ステップは`KubernetesExecutorCustomFeatureConfigStep`を実装でき、エグゼキューター構成も利用可能になります。 | 3.2.0 |
spark.kubernetes.allocation.maxPendingPods |
Int.MaxValue |
このアプリケーションのエグゼキューター割り当て中に許可される保留中のPODの最大数。Kubernetesによってまだ認識されていない新しく要求されたエグゼキューターも、時間とともに保留中のPODに変わるため、この制限に含まれます。この制限はリソースプロファイルとは独立しており、使用されているすべてリソースプロファイルの合計を制限します。 | 3.2.0 |
spark.kubernetes.allocation.pods.allocator |
direct |
PODに使用されるアロケーター。可能な値は `direct`(デフォルト)、`statefulset`、または `AbstractPodsAllocator` を実装するクラスの完全なクラス名です。将来のバージョンでJobまたはreplicasetが追加される可能性があります。これは開発者APIであり、いつでも変更または削除される可能性があります。 | 3.3.0 |
spark.kubernetes.allocation.executor.timeout |
600s |
新しく作成されたエグゼキューターPODリクエストが、POD保留状態に到達する前にタイムアウトと見なされ削除されるまでの待機時間。 | 3.1.0 |
spark.kubernetes.allocation.driver.readinessTimeout |
1s |
エグゼキューターポッドを作成する前に、ドライバーポッドが準備完了になるまでの待機時間。この待機はアプリケーション開始時にのみ発生します。タイムアウトが発生しても、エグゼキューターポッドは作成されます。 | 3.1.3 |
spark.kubernetes.executor.enablePollingWithResourceVersion |
false |
trueの場合、`resourceVersion`は`0`とともに設定され、ポッドリストAPIの呼び出しを許可し、APIサーバー側キャッシュを有効にします。これは慎重に使用する必要があります。 | 3.3.0 |
spark.kubernetes.executor.eventProcessingInterval |
1s |
Kubernetes APIから送信されたエグゼキューターイベントの逐次検査間の間隔。 | 2.4.0 |
spark.kubernetes.executor.rollInterval |
0s |
エグゼキューターのロール操作間の間隔。デフォルトでは `0s` で無効になっています。 | 3.3.0 |
spark.kubernetes.executor.minTasksPerExecutorBeforeRolling |
0 |
ロール前にエグゼキューターあたりの最小タスク数。Sparkは、タスクの合計数がこの設定より少ないエグゼキューターをロールしません。デフォルト値はゼロです。 | 3.3.0 |
spark.kubernetes.executor.rollPolicy |
OUTLIER |
エグゼキューターのロールポリシー:有効な値は ID、ADD_TIME、TOTAL_GC_TIME、TOTAL_DURATION、FAILED_TASKS、および OUTLIER(デフォルト)です。エグゼキューターのロールが発生すると、Sparkはこのポリシーを使用してエグゼキューターを選択し、非アクティブ化します。組み込みポリシーはエグゼキューターの概要に基づいており、新しく開始されたエグゼキューターは`spark.kubernetes.executor.minTasksPerExecutorBeforeRolling`によって保護されます。IDポリシーは、最も小さいエグゼキューターIDを持つエグゼキューターを選択します。ADD_TIMEポリシーは、最も小さい追加時間を持つエグゼキューターを選択します。TOTAL_GC_TIMEポリシーは、最も大きいタスクGC合計時間を持つエグゼキューターを選択します。TOTAL_DURATIONポリシーは、最も大きいタスク合計時間を持つエグゼキューターを選択します。AVERAGE_DURATIONポリシーは、最も大きい平均タスク時間を持つエグゼキューターを選択します。FAILED_TASKSポリシーは、最も多い失敗タスク数を持つエグゼキューターを選択します。OUTLIERポリシーは、平均タスク時間、タスク合計時間、GC合計時間、および失敗タスク数の少なくとも2つの標準偏差を超える顕著な統計を持つエグゼキューターを選択します。外れ値がない場合、TOTAL_DURATIONポリシーのように動作します。 | 3.3.0 |
ポッドテンプレートのプロパティ
Sparkによって上書きされるポッド仕様の完全なリストについては、以下の表を参照してください。
ポッドメタデータ
| ポッドメタデータキー | 変更された値 | 説明 |
|---|---|---|
| name | spark.kubernetes.driver.pod.nameの値 |
ドライバーポッド名は、`spark.kubernetes.driver.pod.name`の設定済みまたはデフォルトの値に上書きされます。エグゼキューターポッド名は影響を受けません。 |
| namespace | spark.kubernetes.namespaceの値 |
Sparkはドライバーおよびエグゼキューターの名前空間について強い仮定をします。ドライバーとエグゼキューターの両方の名前空間は、設定済みのまたはデフォルトのSpark設定値に置き換えられます。 |
| labels | spark.kubernetes.{driver,executor}.label.*からのラベルを追加します。 |
Sparkは、Spark構成で指定された追加のラベルを追加します。 |
| annotations | spark.kubernetes.{driver,executor}.annotation.*からのアノテーションを追加します。 |
Sparkは、Spark構成で指定された追加のアノテーションを追加します。 |
ポッド仕様
| ポッドスペックキー | 変更された値 | 説明 |
|---|---|---|
| imagePullSecrets | spark.kubernetes.container.image.pullSecretsからのイメージプルシークレットを追加します。 |
追加のプルシークレットがSpark構成から両方のエグゼキューターポッドに追加されます。 |
| nodeSelector | spark.kubernetes.node.selector.*からのノードセレクターを追加します。 |
追加のノードセレクターがSpark構成から両方のエグゼキューターポッドに追加されます。 |
| restartPolicy | "never" |
Sparkは、ドライバーとエグゼキューターの両方が決して再起動しないと仮定します。 |
| serviceAccount | spark.kubernetes.authenticate.driver.serviceAccountNameの値 |
Sparkは、Spark構成が指定されている場合のみ、ドライバーポッドの`serviceAccount`をSpark構成の値で上書きします。エグゼキューターポッドは影響を受けません。 |
| serviceAccountName | spark.kubernetes.authenticate.driver.serviceAccountNameの値 |
Sparkは、Spark構成が指定されている場合のみ、ドライバーポッドの`serviceAccountName`をSpark構成の値で上書きします。エグゼキューターポッドは影響を受けません。 |
| volumes | spark.kubernetes.{driver,executor}.volumes.[VolumeType].[VolumeName].mount.pathからのボリュームを追加します。 |
Sparkは、Spark設定で指定されたボリューム、およびSpark設定およびポッドテンプレートファイルを渡すために必要な追加のボリュームを追加します。 |
コンテナ仕様
以下は、ドライバーおよびエグゼキューターコンテナに影響します。ポッドスペック内の他のすべてのコンテナは影響を受けません。
| コンテナスペックキー | 変更された値 | 説明 |
|---|---|---|
| env | spark.kubernetes.driverEnv.[EnvironmentVariableName]からの環境変数を追加します。 |
Sparkは、`spark.kubernetes.driverEnv.[EnvironmentVariableName]`からドライバー環境変数を、`spark.executorEnv.[EnvironmentVariableName]`からエグゼキューター環境変数を追加します。 |
| image | spark.kubernetes.{driver,executor}.container.imageの値 |
イメージはSpark構成で定義されます。 |
| imagePullPolicy | spark.kubernetes.container.image.pullPolicyの値 |
Sparkは、ドライバーとエグゼキューターの両方のプルポリシーを上書きします。 |
| name | 説明を参照 | ポッドテンプレートによって定義されていない場合、コンテナ名はSparkによって割り当てられます(ドライバーコンテナは "spark-kubernetes-driver"、各エグゼキューターコンテナは "spark-kubernetes-executor")。テンプレートによってコンテナが定義されている場合、テンプレートの名前が使用されます。 |
| resources | 説明を参照 | CPU制限は`spark.kubernetes.{driver,executor}.limit.cores`によって設定されます。CPUは`spark.{driver,executor}.cores`によって設定されます。メモリリクエストと制限は、`spark.{driver,executor}.memory`と`spark.{driver,executor}.memoryOverhead`の値の合計によって設定されます。その他のリソース制限は`spark.{driver,executor}.resources.{resourceName}.*`設定によって設定されます。 |
| volumeMounts | spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.{path,readOnly}からのボリュームを追加します。 |
Sparkは、Spark設定で指定されたボリューム、およびSpark設定およびポッドテンプレートファイルを渡すために必要な追加のボリュームを追加します。 |
リソース割り当てと設定の概要
構成ページのカスタムリソーススケジューリングと構成の概要セクションを必ずお読みください。このセクションでは、リソーススケジューリングのKubernetes固有の側面のみについて説明します。
ユーザーは、リソースが利用可能であることを確認し、理想的には各コンテナごとにリソースを分離して、リソースが複数のコンテナ間で共有されないように、Kubernetesクラスタを適切に構成する責任があります。リソースが分離されていない場合、リソースがコンテナ間で共有されないように発見スクリプトを作成する責任はユーザーにあります。カスタムリソースを使用したKubernetesの構成に関する詳細は、Kubernetesドキュメントを参照してください。
Sparkは、KubernetesリソースタイプがKubernetesデバイスプラグイン形式の`vendor-domain/resourcetype`に従っている限り、Spark設定`spark.{driver/executor}.resource.{resourceType}`をKubernetes設定に自動的に変換します。ユーザーは`spark.{driver/executor}.resource.{resourceType}.vendor`設定を使用してベンダーを指定する必要があります。Podテンプレートを使用している場合、ユーザーは明示的に何も追加する必要はありません。参考および例として、GPUのスケジューリングに関するKubernetesドキュメントを参照してください。Sparkはリソース制限の設定のみをサポートします。
Kubernetesは、各コンテナに割り当てられたリソースのアドレスをSparkに通知しません。そのため、ユーザーは、エグゼキューターが起動時に実行して、そのエグゼキューターが利用可能なリソースを発見するための発見スクリプトを指定する必要があります。例のスクリプトは`examples/src/main/scripts/getGpusResources.sh`で見つけることができます。スクリプトには実行権限を設定する必要があり、ユーザーは悪意のあるユーザーがそれを変更できないように権限を設定する必要があります。スクリプトは、ResourceInformationクラスの形式のJSON文字列をSTDOUTに書き込む必要があります。これには、リソース名と、そのエグゼキューターのみが利用可能なリソースアドレスの配列が含まれます。
リソースレベルのスケジューリングの概要
Spark on Kubernetesでサポートされているリソースレベルのスケジューリング機能がいくつかあります。
優先度スケジューリング
KubernetesはデフォルトでPod優先度をサポートしています。
Spark on Kubernetesでは、ポッドテンプレートによってジョブの優先度を定義できます。ユーザーは、ドライバーまたはエグゼキューターのポッドテンプレートの`spec`セクションで`priorityClassName`を指定できます。以下は、それを指定する方法を示す例です。
apiVersion: v1
Kind: Pod
metadata:
labels:
template-label-key: driver-template-label-value
spec:
# Specify the priority in here
priorityClassName: system-node-critical
containers:
- name: test-driver-container
image: will-be-overwritten
Spark on Kubernetes 用のカスタム Kubernetes スケジューラー
Sparkは、ユーザーがカスタムKubernetesスケジューラを指定できるようにします。
-
スケジューラ名を指定します。
ユーザーは、`spark.kubernetes.scheduler.name`または`spark.kubernetes.{driver/executor}.scheduler.name`設定を使用してカスタムスケジューラを指定できます。
-
スケジューラ関連の設定を構成します。
カスタムスケジューラを構成するために、ユーザーはポッドテンプレートを使用したり、ラベル(`spark.kubernetes.{driver,executor}.label.*`)、アノテーション(`spark.kubernetes.{driver/executor}.annotation.*`)、またはスケジューラ固有の設定(例:`spark.kubernetes.scheduler.volcano.podGroupTemplateFile`)を追加したりできます。
-
スケジューラ機能ステップを指定します。
ユーザーは、`spark.kubernetes.{driver/executor}.pod.featureSteps`を使用して、以下を含むがこれらに限定されない、より複雑な要件をサポートすることも検討できます。
- ドライバー/エグゼキュータースケジューリングのための追加のKubernetesカスタムリソースを作成します。
- 設定または既存のポッド情報に基づいて、動的にスケジューラヒントを設定します。
Volcano を Spark on Kubernetes 用のカスタムスケジューラーとして使用する
前提条件
-
Spark on KubernetesとVolcanoは、Spark v3.3.0およびVolcano v1.7.0以降、カスタムスケジューラとしてサポートされています。以下はVolcano 1.7.0をインストールする例です。
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.7.0/installer/volcano-development.yaml
ビルド
Sparkのダウンロードページで配布されているようなVolcanoサポート付きのSparkディストリビューションを作成するには、「Sparkのビルド」も参照してください。
./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Psparkr -Phive -Phive-thriftserver -Pkubernetes -Pvolcano
使用法
Spark on Kubernetesは、Volcanoをカスタムスケジューラとして使用できます。ユーザーはVolcanoを使用して、キューイング、リソース予約、優先度スケジューリングなど、より高度なリソーススケジューリングをサポートできます。
Volcanoをカスタムスケジューラとして使用するために、ユーザーは以下の構成オプションを指定する必要があります。
# Specify volcano scheduler and PodGroup template
--conf spark.kubernetes.scheduler.name=volcano
--conf spark.kubernetes.scheduler.volcano.podGroupTemplateFile=/path/to/podgroup-template.yaml
# Specify driver/executor VolcanoFeatureStep
--conf spark.kubernetes.driver.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
--conf spark.kubernetes.executor.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
Volcano 機能ステップ
Volcano機能ステップは、ユーザーがVolcano PodGroupを作成し、ドライバー/エグゼキューターポッドアノテーションを設定して、このPodGroupにリンクするのに役立ちます。
現在、Volcano Feature Stepではドライバー/ジョブレベルのPodGroupのみがサポートされていることに注意してください。
Volcano PodGroup テンプレート
Volcanoは、CRD yamlを使用してPodGroupスペックを定義します。
ポッドテンプレートと同様に、SparkユーザーはVolcano PodGroupテンプレートを使用してPodGroupスペック構成を定義できます。これを行うには、`spark-submit`プロセスからアクセス可能なファイルにポイントするようにSparkプロパティ`spark.kubernetes.scheduler.volcano.podGroupTemplateFile`を指定します。以下はPodGroupテンプレートの例です。
apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
spec:
# Specify minMember to 1 to make a driver pod
minMember: 1
# Specify minResources to support resource reservation (the driver pod resource and executors pod resource should be considered)
# It is useful for ensource the available resources meet the minimum requirements of the Spark job and avoiding the
# situation where drivers are scheduled, and then they are unable to schedule sufficient executors to progress.
minResources:
cpu: "2"
memory: "3Gi"
# Specify the priority, help users to specify job priority in the queue during scheduling.
priorityClassName: system-node-critical
# Specify the queue, indicates the resource queue which the job should be submitted to
queue: default
Apache YuniKorn を Spark on Kubernetes 用のカスタムスケジューラーとして使用する
Apache YuniKornは、ジョブキューイング、リソース公平性、最小/最大キュー容量、柔軟なジョブ順序付けポリシーなどの高度なバッチスケジューリング機能を提供するKubernetesのリソーススケジューラです。利用可能なApache YuniKorn機能については、コア機能を参照してください。
前提条件
Apache YuniKornのインストール
helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn --version 1.6.3 --create-namespace --set embedAdmissionController=false
上記の手順は、既存のKubernetesクラスタにYuniKorn v1.6.3をインストールします。
はじめに
以下の追加オプションでSparkジョブをサブミットします。
--conf spark.kubernetes.scheduler.name=yunikorn
--conf spark.kubernetes.driver.label.queue=root.default
--conf spark.kubernetes.executor.label.queue=root.default
--conf spark.kubernetes.driver.annotation.yunikorn.apache.org/app-id={{APP_ID}}
--conf spark.kubernetes.executor.annotation.yunikorn.apache.org/app-id={{APP_ID}}
{{APP_ID}}はSparkジョブIDに自動的に置換される組み込み変数です。上記の設定で、ジョブはデフォルトのKubernetesスケジューラではなくYuniKornスケジューラによってスケジュールされます。
ステージレベルのスケジューリング概要
ステージレベルのスケジューリングはKubernetesでサポートされています。
- 動的割り当てが無効な場合: ユーザーはステージレベルで異なるタスクリソース要件を指定でき、起動時に要求されたのと同じ Executor を使用します。
- 動的割り当てが有効な場合:ユーザーはステージレベルでタスクとエグゼキューターのリソース要件を指定でき、追加のエグゼキューターを要求します。これは、Kubernetesが現時点では外部シャッフルサービスをサポートしていないため、`spark.dynamicAllocation.shuffleTracking.enabled`が有効になっていることも必要とします。異なるプロファイルのリソースのコンテナをKubernetesに要求する順序は保証されません。Kubernetesでの動的割り当てにはシャッフル追跡機能が必要であるため、以前のステージのエグゼキューターが異なるResourceProfileを使用した場合は、シャッフルデータが原因でアイドルタイムアウトしない可能性があることに注意してください。これにより、より多くのクラスタリソースが使用される可能性があり、最悪の場合、Kubernetesクラスタにリソースが残っていない場合、Sparkがハングする可能性があります。`spark.dynamicAllocation.shuffleTracking.timeout`設定をタイムアウトに設定することを検討できますが、シャッフルデータが本当に必要な場合は、データの再計算が必要になる可能性があります。ポッドテンプレートリソースの処理方法には、ベースのデフォルトプロファイルとカスタムResourceProfilesの間で違いがあることに注意してください。ポッドテンプレートファイルで指定されたリソースは、ベースのデフォルトプロファイルでのみ使用されます。カスタムResourceProfilesを作成する場合は、テンプレートファイルのリソースはカスタムResourceProfilesに伝播されないため、すべての必要なリソースを含めるようにしてください。