Kubernetes 上での Spark 実行

Spark は、Kubernetes によって管理されるクラスタ上で実行できます。この機能は、Spark に追加されたネイティブの Kubernetes スケジューラを利用しています。

セキュリティ

認証などのセキュリティ機能は、デフォルトでは有効になっていません。インターネットまたは信頼できないネットワークに公開されているクラスタをデプロイする場合は、クラスタへのアクセスを保護して、不正なアプリケーションがクラスタで実行されないようにすることが重要です。Spark を実行する前に、Spark セキュリティ とこのドキュメントの特定のセキュリティセクションを参照してください。

ユーザーID

プロジェクト提供の Dockerfile からビルドされたイメージには、185 のデフォルト UID を持つデフォルトの USER ディレクティブが含まれています。これは、結果として得られるイメージが、コンテナ内でこの UID として Spark プロセスを実行することを意味します。セキュリティを重視したデプロイメントでは、目的の非特権 UID と GID を指定する USER ディレクティブを指定したカスタムイメージを提供することを検討する必要があります。結果の UID には、Spark 実行可能ファイルを動作させるために、ルートグループを補足グループに含める必要があります。提供されている docker-image-tool.sh スクリプトで独自のイメージをビルドするユーザーは、-u <uid> オプションを使用して目的の UID を指定できます。

あるいは、ポッドテンプレート 機能を使用して、Spark が送信するポッドに runAsUser を含む セキュリティコンテキスト を追加できます。これは、イメージ自体の USER ディレクティブをオーバーライドするために使用できます。ただし、これはユーザーの協力が必要となるため、共有環境には適さないソリューションとなる可能性があることに注意してください。クラスタ管理者は、ポッドが実行できるユーザーを制限する場合、Pod セキュリティポリシー を使用する必要があります。

ボリュームマウント

このドキュメントの後半にある Kubernetes ボリュームの使用 の項で説明されているように、K8S 上の Spark は、特定の種類のボリュームをドライバとエグゼキュータポッドにマウントできるようにする設定オプションを提供しています。特に、Kubernetes のドキュメントで説明されているように、既知のセキュリティ脆弱性を持つ hostPath ボリュームを許可しています。

クラスタ管理者は、Pod セキュリティポリシー を使用して、hostPath ボリュームのマウント機能を環境に合わせて適切に制限する必要があります。

前提条件

動作方法

Spark cluster components

spark-submit を直接使用して、Spark アプリケーションを Kubernetes クラスタに送信できます。送信メカニズムは次のとおりです。

完了状態では、ドライバポッドは *計算* リソースまたはメモリリソースを使用しないことに注意してください。

ドライバとエグゼキュータポッドのスケジューリングは、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_server_url で API サーバーに接続されます。URL に HTTP プロトコルが指定されていない場合、デフォルトで https になります。たとえば、マスターを k8s://example.com:443 に設定することは、k8s://https://example.com:443 に設定することと同じですが、異なるポートで TLS なしで接続するには、マスターを k8s://http://example.com:8080 に設定します。

Kubernetes モードでは、spark.app.name または spark-submit--name 引数で指定された Spark アプリケーション名は、デフォルトでドライバやエグゼキュータなどの作成された Kubernetes リソースの名前付けに使用されます。したがって、アプリケーション名は、小文字の英数字、-. で構成され、英数字で始まる必要があります。

Kubernetes クラスタが設定されている場合、apiserver URL を検出する1つの方法は、kubectl cluster-info を実行することです。

$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:6443

上記の例では、`spark-submit` に `--master k8s://http://127.0.0.1:6443` を引数として指定することで、特定のKubernetesクラスタを使用できます。さらに、認証プロキシである`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アプリケーションを実行できます。アプリケーションがクライアントモードで実行されると、ドライバはpod内または物理ホスト上で実行できます。クライアントモードでアプリケーションを実行する場合は、次の要素を考慮することをお勧めします。

クライアントモードのネットワーク

Sparkエグゼキュータは、Sparkエグゼキュータからルーティング可能なホスト名とポートを介してSparkドライバに接続できる必要があります。Sparkがクライアントモードで動作するために必要な特定のネットワーク構成は、設定によって異なります。Kubernetes pod内でドライバを実行する場合は、ヘッドレスサービス を使用して、ドライバpodが安定したホスト名によってエグゼキュータからルーティングできるようにします。ヘッドレスサービスをデプロイする際には、サービスのラベルセレクタがドライバpodのみに一致し、他のpodには一致しないようにしてください。ドライバpodに十分に一意のラベルを割り当て、そのラベルをヘッドレスサービスのラベルセレクタで使用することをお勧めします。ドライバのホスト名を`spark.driver.host`、Sparkドライバのポートを`spark.driver.port`で指定します。

クライアントモードのエグゼキュータポッドのガベージコレクション

Sparkドライバをpod内で実行する場合は、`spark.kubernetes.driver.pod.name`をそのpodの名前に設定することを強くお勧めします。このプロパティが設定されると、SparkスケジューラはOwnerReferenceを使用してエグゼキュータpodをデプロイします。これにより、ドライバpodがクラスタから削除されると、アプリケーションのエグゼキュータpodもすべて削除されます。ドライバは、`spark.kubernetes.namespace`で指定された名前空間にある指定された名前のpodを探し、そのpodを指すOwnerReferenceが各エグゼキュータpodのOwnerReferencesリストに追加されます。実際にはそのドライバpodではないpodにOwnerReferenceを設定しないように注意してください。そうしないと、間違ったpodが削除されたときにエグゼキュータが早期に終了される可能性があります。

アプリケーションがpod内で実行されていない場合、またはアプリケーションが実際にpod内で実行されているときに`spark.kubernetes.driver.pod.name`が設定されていない場合は、アプリケーションが終了したときにエグゼキュータpodがクラスタから適切に削除されない可能性があることに注意してください。Sparkスケジューラはこれらのpodの削除を試みますが、何らかの理由でAPIサーバへのネットワークリクエストが失敗した場合、これらのpodはクラスタに残ります。エグゼキュータプロセスは、ドライバに到達できない場合に終了するため、アプリケーションの終了後、エグゼキュータpodはクラスタで計算リソース(CPUとメモリ)を消費しません。

`spark.kubernetes.executor.podNamePrefix`を使用して、エグゼキュータpod名を完全に制御できます。このプロパティを設定する場合は、同じ名前空間内のすべてのジョブで一意にすることを強くお勧めします。

認証パラメータ

クライアントモードでのKubernetes認証パラメータには、`spark.kubernetes.authenticate`という正確なプレフィックスを使用してください。

IPv4 と IPv6

3.4.0以降、SparkはIPv4/IPv6デュアルスタックネットワーク機能を介してIPv6のみの環境もサポートしています。この機能により、PodとサービスにIPv4と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`のみを使用するには、次のコマンドでジョブを送信します。

...
    --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.2.2
--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にアップロードされ、ドライバが起動されるとドライバpodにダウンロードされ、そのクラスパスに追加されます。Sparkは、並行して実行されているSparkアプリとの競合を回避するために、ランダムな名前のアップロードパスの下にサブディレクトリを生成します。ユーザーは必要に応じて作成されたサブディレクトリを管理できます。

クライアントスキームは、アプリケーションjar、およびプロパティ`spark.jars`、`spark.files`、`spark.archives`で指定された依存関係でサポートされています。

重要:すべてのクライアント側の依存関係は、フラットなディレクトリ構造で指定されたパスにアップロードされるため、ファイル名が重複するとファイルが上書きされます。また、派生したk8sイメージのデフォルトのivyディレクトリに必要なアクセス権限があること、または上記のように設定を変更してください。後者は、クラスタモードで`--packages`を使用する場合にも重要です。

シークレット管理

Kubernetes Secrets を使用して、Sparkアプリケーションが保護されたサービスにアクセスするための資格情報を提供できます。ユーザー指定のシークレットをドライバコンテナにマウントするには、`spark.kubernetes.driver.secrets.[SecretName]=<mount path>`形式の構成プロパティを使用できます。同様に、`spark.kubernetes.executor.secrets.[SecretName]=<mount path>`形式の構成プロパティを使用して、ユーザー指定のシークレットをエグゼキュータコンテナにマウントできます。マウントするシークレットは、ドライバとエグゼキュータpodと同じ名前空間に存在すると仮定されています。たとえば、`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では、テンプレートファイルからpodを定義できます。Sparkユーザーは同様に、テンプレートファイルを使用して、Spark構成がサポートしていないドライバまたはエグゼキュータpod構成を定義できます。これを行うには、`spark-submit`プロセスからアクセス可能なファイルを参照するように、`spark.kubernetes.driver.podTemplateFile`と`spark.kubernetes.executor.podTemplateFile`のSparkプロパティを指定します。

--conf spark.kubernetes.driver.podTemplateFile=s3a://bucket/driver.yml
--conf spark.kubernetes.executor.podTemplateFile=s3a://bucket/executor.yml

ドライバpodがエグゼキュータpodテンプレートファイルにアクセスできるようにするために、ファイルは作成時にドライバpodのボリュームに自動的にマウントされます。Sparkはこれらのテンプレートファイルをアンマーシャリングした後、検証を行わず、検証にはKubernetes APIサーバに依存します。

Sparkは特定のpod構成について独自の考えを持っているため、podテンプレート内の値は常にSparkによって上書きされることに注意することが重要です。したがって、この機能のユーザーは、podテンプレートファイルを指定しても、pod構築プロセス中に空のpodではなくテンプレートpodから開始することだけをSparkに許可することに注意してください。詳細については、Sparkによって上書きされるpodテンプレート値の完全なリストを参照してください。

Podテンプレートファイルは、複数のコンテナも定義できます。このような場合、`spark.kubernetes.driver.podTemplateContainerName`と`spark.kubernetes.executor.podTemplateContainerName`のSparkプロパティを使用して、ドライバまたはエグゼキュータのベースとして使用するコンテナを示すことができます。指定されていない場合、またはコンテナ名が有効でない場合、Sparkはリスト内の最初のコンテナがドライバまたはエグゼキュータコンテナであると仮定します。

Kubernetes ボリュームの使用

ユーザーは、次のタイプのKubernetes ボリュームをドライバとエグゼキュータpodにマウントできます。

**注記:** ボリュームマウントに関連するセキュリティの問題については、このドキュメントのセキュリティセクションを参照してください。

上記のいずれかのタイプのボリュームをドライバpodにマウントするには、次の構成プロパティを使用します。

--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`は、pod仕様の`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をクレーム名として使用し、storageClasssizeLimitオプションを以下のように使用することで、エグゼキュータごとに動的に作成されたパーシステントボリュームクレームをマウントできます。これは動的割り当ての場合に役立ちます。

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指向のエグゼキュータ割り当てを実行できるようになりました。これは、ジョブが持つことができる作成済みPVCの総数をSparkがカウントし、ドライバが最大数のPVCを所有している場合、新しいエグゼキュータの作成を保留することを意味します。これは、既存のPVCを1つのエグゼキュータから別のエグゼキュータへの移行に役立ちます。

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ダッシュボードからもアクセスできます。

ドライバUIへのアクセス

任意のアプリケーションに関連付けられたUIには、kubectl port-forwardを使用してローカルでアクセスできます。

$ kubectl port-forward <driver-pod-name> 4040:4040

その後、SparkドライバUIにはhttp://localhost:4040でアクセスできます。

デバッグ

いくつかの種類の障害が発生する可能性があります。Kubernetes 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ではResourceQuotaを使用して、個々のネームスペースのリソース、オブジェクトの数などに制限を設定できます。管理者は、ネームスペースとResourceQuotaを組み合わせて使用することで、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=sparksparkネームスペースがデフォルトで使用されます。一方、特定のコンテキストにネームスペースが追加されていない場合、すべてのネームスペースがデフォルトで考慮されます。つまり、ネームスペースに関係なく、指定された送信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

どちらの操作もglobパターンをサポートしています。例えば、ユーザーは以下を実行できます。

$ spark-submit --kill spark:spark-pi* --master  k8s://https://192.168.2.8:8443

上記は、特定のプレフィックスを持つすべてのアプリケーションを強制終了します。

ユーザーは、spark.kubernetes.appKillPodDeletionGracePeriodプロパティを介して、ポッドの終了の猶予期間を指定できます。これは--confを使用して提供します(すべての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内でイメージをプルする際に使用されるコンテナイメージプルポリシー。有効な値はAlwaysNeverIfNotPresentです。 2.3.0
spark.kubernetes.container.image.pullSecrets プライベートイメージレジストリからイメージをプルするために使用されるKubernetesシークレットのカンマ区切りリスト。 2.4.0
spark.kubernetes.allocation.batch.size 5 エグゼキューターポッドの割り当ての各ラウンドで一度に起動するポッドの数。 2.3.0
spark.kubernetes.allocation.batch.delay 1s エグゼキューターポッドの割り当ての各ラウンド間の待ち時間。1秒未満の値を指定すると、Sparkドライバーで過剰なCPU使用率が発生する可能性があります。 2.3.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.authenticate.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 units に記載されています。設定されている場合は、ドライバポッドの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 units に記載されています。これは 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.identifiermyIdentifier に設定すると、ドライバポッドとエグゼキュータは、キーがidentifierで値がmyIdentifierのノードセレクタを持つことになります。このプレフィックスを使用して複数の構成を設定することで、複数のノードセレクタキーを追加できます。 2.3.0
spark.kubernetes.driver.node.selector.[labelKey] (なし) ドライバポッドのドライバノードセレクタに、キーをlabelKey、値を構成の値として追加します。例えば、spark.kubernetes.driver.node.selector.identifiermyIdentifier に設定すると、ドライバポッドは、キーがidentifierで値がmyIdentifierのノードセレクタを持つことになります。このプレフィックスを使用して複数の構成を設定することで、複数のドライバノードセレクタキーを追加できます。 3.3.0
spark.kubernetes.executor.node.selector.[labelKey] (なし) エグゼキュータポッドのエグゼキュータノードセレクタに、キーをlabelKey、値を構成の値として追加します。例えば、spark.kubernetes.executor.node.selector.identifiermyIdentifier に設定すると、エグゼキュータは、キーが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] (なし) 参照された Kubernetes シークレット のデータ内のキーkeyで参照される値を、EnvName(大文字と小文字が区別されます)という名前でドライバコンテナに環境変数として追加します。 例えば、spark.kubernetes.driver.secretKeyRef.ENV_VAR=spark-secret:key です。 2.4.0
spark.kubernetes.executor.secretKeyRef.[EnvName] (なし) 参照された Kubernetes シークレット のデータ内のキーkeyで参照される値を、EnvName(大文字と小文字が区別されます)という名前でエグゼキュータコンテナに環境変数として追加します。 例えば、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.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.local.dirs.tmpfs false Spark ドライバとエグゼキュータポッド内の SPARK_LOCAL_DIRS をバックアップするために使用される emptyDir ボリュームが tmpfs バックアップ(つまり RAM)を使用するように設定します。これについては、このページ上部の ローカルストレージ を参照してください。 3.0.0
spark.kubernetes.memoryOverheadFactor 0.1 これは、非JVMメモリにメモリを割り当てるメモリオーバーヘッド係数を設定します。これには、ヒープ外のメモリ割り当て、非JVMタスク、さまざまなシステムプロセス、およびspark.kubernetes.local.dirs.tmpfstrueの場合のtmpfsベースのローカルディレクトリが含まれます。JVMベースのジョブの場合、この値はJVM以外のジョブの場合は0.10、0.40にデフォルト設定されます。これは、JVM以外のタスクはより多くのJVM以外のヒープスペースを必要とするため、このようなタスクは一般的に「メモリオーバーヘッド超過」エラーで失敗するためです。これは、より高いデフォルト値を使用してこのエラーを回避します。これは、spark.driver.memoryOverheadFactorspark.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 (なし) 既存の委任トークンが保存されているシークレットの名前を指定します。これにより、ジョブユーザーがジョブの起動に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 false ポッドの状態を判断する際に、エグゼキュータコンテナのみをチェックするのか、すべてのコンテナ(サイドカーを含む)をチェックするのかを指定します。 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 5秒 強制終了する前に、エグゼキュータが正常にシャットダウンするのを待つ時間。 3.0.0
spark.kubernetes.file.upload.path (なし) クラスタモードでSpark submit側でファイルを保存するパス。例: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 1572864 ConfigMapの最大サイズ制限。これは、k8sサーバ側の制限に従って設定可能です。 3.1.0
spark.kubernetes.executor.missingPodDetectDelta 30s 登録済みのエグゼキュータのPODが、Kubernetes APIサーバのポーリングされた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ファミリポリシー。有効な値はSingleStackPreferDualStackRequireDualStackです。 3.4.0
spark.kubernetes.driver.service.ipFamilies IPv4 K8sドライバサービスのIPファミリのリスト。有効な値はIPv4IPv6です。 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=truespark.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 ポッドに使用するアロケータ。可能な値はdirect(デフォルト)、statefulset、または`AbstractPodsAllocator`を実装するクラスの完全なクラス名です。将来のバージョンでは、Jobまたはreplicasetが追加される可能性があります。これは開発者向けAPIであり、いつでも変更または削除される可能性があります。 3.3.0
spark.kubernetes.allocation.executor.timeout 600秒 新しく作成されたエグゼキュータPODリクエストがまだPOD保留状態に達していないとみなされる前に待つ時間。タイムアウトすると削除されます。 3.1.0
spark.kubernetes.allocation.driver.readinessTimeout 1s エグゼキュータポッドを作成する前に、ドライバポッドの準備が整うまで待つ時間。この待機はアプリケーション開始時のみ発生します。タイムアウトが発生した場合でも、エグゼキュータポッドは引き続き作成されます。 3.1.3
spark.kubernetes.executor.enablePollingWithResourceVersion false trueの場合、ポッド一覧APIの呼び出し中に`resourceVersion`が`0`に設定され、APIサーバ側のキャッシングが許可されます。これは注意して使用する必要があります。 3.3.0
spark.kubernetes.executor.eventProcessingInterval 1s Kubernetes APIから送信されたエグゼキュータイベントの連続した検査間のインターバル。 2.4.0
spark.kubernetes.executor.rollInterval 0秒 エグゼキュータロール操作間のインターバル。デフォルトでは`0秒`で無効になっています。 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}.memoryspark.{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リソースタイプがvendor-domain/resourcetypeのKubernetesデバイスプラグイン形式に従う限り、Spark設定spark.{driver/executor}.resource.{resourceType}をKubernetes設定に変換する処理を自動的に行います。ユーザーは、spark.{driver/executor}.resource.{resourceType}.vendor設定を使用してベンダーを指定する必要があります。ポッドテンプレートを使用している場合は、明示的に何も追加する必要はありません。参考として例として、GPUのスケジューリングに関するKubernetesのドキュメントを参照してください。Sparkはリソース制限の設定のみをサポートしています。

Kubernetesは、各コンテナに割り当てられたリソースのアドレスをSparkに通知しません。そのため、ユーザーは、起動時にexecutorによって実行され、そのexecutorで使用可能なリソースを検出するディスカバリスクリプトを指定する必要があります。サンプルスクリプトは、examples/src/main/scripts/getGpusResources.shにあります。このスクリプトには実行権限を設定する必要があり、ユーザーは悪意のあるユーザーがスクリプトを変更できないようにパーミッションを設定する必要があります。スクリプトは、ResourceInformationクラスの形式でJSON文字列をSTDOUTに出力する必要があります。これには、リソース名と、そのexecutorのみが使用できるリソースアドレスの配列が含まれます。

リソースレベルスケジューリングの概要

Kubernetes上のSparkでは、いくつかのリソースレベルのスケジューリング機能がサポートされています。

優先順位スケジューリング

Kubernetesは、デフォルトでPod優先度をサポートしています。

Kubernetes上のSparkでは、Podテンプレートによってジョブの優先度を定義できます。ユーザーは、driverまたはexecutorのPodテンプレートの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

Kubernetes 上の Spark 用のカスタマイズされた Kubernetes スケジューラ

Sparkでは、ユーザーはカスタムKubernetesスケジューラを指定できます。

  1. スケジューラ名を指定します。

    ユーザーは、spark.kubernetes.scheduler.nameまたはspark.kubernetes.{driver/executor}.scheduler.name設定を使用してカスタムスケジューラを指定できます。

  2. スケジューラ関連の設定を指定します。

    カスタムスケジューラを設定するには、Podテンプレートを使用し、ラベル(spark.kubernetes.{driver,executor}.label.*)、アノテーション(spark.kubernetes.{driver/executor}.annotation.*)、またはスケジューラ固有の設定(spark.kubernetes.scheduler.volcano.podGroupTemplateFileなど)を追加できます。

  3. スケジューラ機能ステップを指定します。

    ユーザーは、spark.kubernetes.{driver/executor}.pod.featureStepsを使用して、以下を含むより複雑な要件をサポートすることもできます。

    • driver/executorスケジューリングのために追加のKubernetesカスタムリソースを作成します。
    • 設定または既存のPod情報に基づいて、スケジューラヒントを動的に設定します。

Kubernetes 上の Spark 用のカスタマイズされたスケジューラとしての Volcano の使用

前提条件
ビルド

Sparkのダウンロードページで配布されているような、Volcanoサポートを含むSparkディストリビューションを作成するには、“Building Spark”も参照してください。

./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Psparkr -Phive -Phive-thriftserver -Pkubernetes -Pvolcano
使用方法

Kubernetes上のSparkでは、カスタムスケジューラとして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にリンクするdriver/executor podアノテーションを設定するのに役立ちます。

現在、Volcano機能ステップでは、driver/jobレベルのPodGroupのみがサポートされていることに注意してください。

Volcano PodGroup テンプレート

Volcanoは、CRD yamlを使用してPodGroup specを定義します。

Podテンプレートと同様に、SparkユーザーはVolcano PodGroupテンプレートを使用してPodGroup spec設定を定義できます。そのためには、Sparkプロパティspark.kubernetes.scheduler.volcano.podGroupTemplateFileを指定して、spark-submitプロセスからアクセス可能なファイルを指し示します。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

Kubernetes 上の Spark 用のカスタマイズされたスケジューラとしての Apache YuniKorn の使用

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.3.0 --create-namespace --set embedAdmissionController=false

上記の手順により、既存のKubernetesクラスタにYuniKorn v1.3.0がインストールされます。

はじめに

次の追加オプションを使用して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でサポートされています。