YARN 上での Spark の実行
- セキュリティ
- YARN 上での Spark の起動
- 準備
- 設定
- アプリケーションのデバッグ
- リソース割り当てと設定の概要
- ステージレベルのスケジューリング概要
- 重要な注意事項
- Kerberos
- 外部シャフルサービスの構成
- Apache Oozie を使用したアプリケーションの起動
- Spark Web UI の代わりとなる Spark History Server の使用
- Spark シャフルサービスの複数バージョンの実行
- Spark アプリケーション用の異なる JDK の構成
Spark 0.6.0 で YARN (Hadoop NextGen) 上での実行サポートが追加され、その後のリリースで改善されました。 YARN (Hadoop NextGen) 上での実行サポートが Spark 0.6.0 で追加され、その後のリリースで改善されました。
セキュリティ
認証のようなセキュリティ機能はデフォルトでは有効になっていません。インターネットまたは信頼されていないネットワークに公開されているクラスターをデプロイする場合、不正なアプリケーションがクラスター上で実行されるのを防ぐために、クラスターへのアクセスを保護することが重要です。Spark を実行する前に、Spark セキュリティ およびこのドキュメントの特定のセキュリティセクションを参照してください。
YARN 上での Spark の起動
Apache Hadoop 3.4.1 時点では Java 17 をサポートしておらず、Apache Spark 4.0.0 以降では最低 Java 17 が必要となるため、Spark アプリケーションには異なる JDK を構成する必要があります。詳細は Spark アプリケーション用の異なる JDK の構成 を参照してください。
HADOOP_CONF_DIR または YARN_CONF_DIR が、Hadoop クラスターの (クライアント側の) 設定ファイルが含まれるディレクトリを指していることを確認してください。これらの設定は HDFS への書き込みや YARN ResourceManager への接続に使用されます。このディレクトリに含まれる設定は YARN クラスターに配布され、アプリケーションが使用するすべてのコンテナが同じ設定を使用するようにします。設定が YARN によって管理されていない Java システムプロパティまたは環境変数を参照する場合、それらは Spark アプリケーションの設定 (ドライバー、エグゼキュータ、およびクライアントモードで実行する場合の AM) にも設定する必要があります。
YARN 上で Spark アプリケーションを起動するには、2 つのデプロイモードがあります。cluster モードでは、Spark ドライバーは YARN によってクラスター上で管理されるアプリケーションマスタープロセス内で実行され、クライアントはアプリケーションの起動後に離れることができます。client モードでは、ドライバーはクライアントプロセス内で実行され、アプリケーションマスターは YARN からリソースを要求するためのみに使用されます。
Spark がサポートする他のクラスターマネージャーとは異なり、マスターのアドレスを --master パラメーターで指定するのに対し、YARN モードでは ResourceManager のアドレスは Hadoop 設定から取得されます。したがって、--master パラメーターは yarn です。
cluster モードで Spark アプリケーションを起動するには
$ ./bin/spark-submit --class path.to.your.Class --master yarn --deploy-mode cluster [options] <app jar> [app options]
例
$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--driver-memory 4g \
--executor-memory 2g \
--executor-cores 1 \
--queue thequeue \
examples/jars/spark-examples*.jar \
10
上記は、デフォルトの Application Master を起動する YARN クライアントプログラムを開始します。次に SparkPi が Application Master の子スレッドとして実行されます。クライアントはステータス更新のために Application Master を定期的にポーリングし、コンソールに表示します。アプリケーションが実行を終了すると、クライアントは終了します。ドライバーおよびエグゼキュータのログを確認する方法については、下の アプリケーションのデバッグ セクションを参照してください。
client モードで Spark アプリケーションを起動するには、同様に行いますが、cluster を client に置き換えます。以下は、spark-shell を client モードで実行する方法を示しています。
$ ./bin/spark-shell --master yarn --deploy-mode client
その他の JAR の追加
cluster モードでは、ドライバーはクライアントとは異なるマシンで実行されるため、クライアントにローカルなファイルに対して SparkContext.addJar はそのままでは機能しません。クライアント上のファイルを SparkContext.addJar で利用可能にするには、起動コマンドの --jars オプションに含めてください。
$ ./bin/spark-submit --class my.main.Class \
--master yarn \
--deploy-mode cluster \
--jars my-other-jar.jar,my-other-other-jar.jar \
my-main-jar.jar \
app_arg1 app_arg2
準備
YARN 上での Spark の実行には、YARN サポートでビルドされた Spark のバイナリディストリビューションが必要です。バイナリディストリビューションは、プロジェクトウェブサイトの ダウンロードページ からダウンロードできます。ダウンロードできる Spark バイナリディストリビューションには 2 つのバリアントがあります。1 つは特定のバージョンの Apache Hadoop で事前にビルドされたものです。この Spark ディストリビューションには Hadoop ランタイムが組み込まれているため、with-hadoop Spark ディストリビューションと呼びます。もう 1 つはユーザー提供の Hadoop で事前にビルドされたものです。この Spark ディストリビューションには Hadoop ランタイムが組み込まれていないため、サイズは小さいですが、ユーザーは別途 Hadoop インストールを提供する必要があります。このバリアントを no-hadoop Spark ディストリビューションと呼びます。with-hadoop Spark ディストリビューションの場合、Hadoop ランタイムが既に組み込まれているため、デフォルトでは、ジョブが Hadoop Yarn クラスターにサブミットされる際に、JAR の競合を防ぐために、Yarn のクラスパスは Spark には設定されません。この動作を上書きするには、spark.yarn.populateHadoopClasspath=true を設定できます。no-hadoop Spark ディストリビューションの場合、Hadoop ランタイムを取得するために Spark はデフォルトで Yarn のクラスパスを設定します。with-hadoop Spark ディストリビューションの場合、アプリケーションがクラスターにのみ存在する特定のライブラリに依存している場合は、上記の設定を試して Yarn クラスパスを設定できます。これにより JAR 競合の問題が発生した場合は、それを無効にして、このライブラリをアプリケーション JAR に含める必要があります。
Spark を自分でビルドするには、Spark のビルド を参照してください。
YARN 側から Spark ランタイム JAR にアクセスできるようにするには、spark.yarn.archive または spark.yarn.jars を指定できます。詳細については、Spark プロパティ を参照してください。spark.yarn.archive も spark.yarn.jars も指定しない場合、Spark は $SPARK_HOME/jars のすべての JAR を含む zip ファイルを作成し、分散キャッシュにアップロードします。
設定
ほとんどの設定は、Spark on YARN の場合、他のデプロイモードと同じです。詳細については、設定ページ を参照してください。これらは Spark on YARN 固有の設定です。
アプリケーションのデバッグ
YARN 用語では、エグゼキュータとアプリケーションマスターは「コンテナ」内で実行されます。YARN には、アプリケーション完了後にコンテナログを処理するための 2 つのモードがあります。ログ集約が有効になっている場合 (yarn.log-aggregation-enable 設定)、コンテナログは HDFS にコピーされ、ローカルマシンから削除されます。これらのログは、yarn logs コマンドを使用してクラスター上のどこからでも表示できます。
yarn logs -applicationId <app ID>
指定されたアプリケーションのすべてのコンテナからのすべてのログファイルの内容を出力します。HDFS シェルまたは API を使用して、HDFS 上のコンテナログファイルを直接表示することもできます。それらが配置されているディレクトリは、YARN 設定 (yarn.nodemanager.remote-app-log-dir および yarn.nodemanager.remote-app-log-dir-suffix) を確認することで見つけることができます。ログは Spark Web UI の Executor タブでも利用できます。Spark History Server と MapReduce History Server の両方が実行されており、yarn-site.xml で yarn.log.server.url が正しく設定されている必要があります。Spark History Server UI のログ URL は、集約されたログを表示するために MapReduce History Server にリダイレクトされます。
ログ集約が有効になっていない場合、ログは各マシンの YARN_APP_LOGS_DIR の下にローカルに保持されます。これは通常、Hadoop のバージョンとインストール方法に応じて、/tmp/logs または $HADOOP_HOME/logs/userlogs に設定されます。コンテナのログを表示するには、それらが含まれるホストに移動し、このディレクトリを確認する必要があります。サブディレクトリは、アプリケーション ID とコンテナ ID によってログファイルを整理します。ログは Spark Web UI の Executor タブでも利用でき、MapReduce History Server を実行する必要はありません。
コンテナごとの起動環境を確認するには、yarn.nodemanager.delete.debug-delay-sec を大きな値 (例: 36000) に増やし、コンテナが起動されるノードの yarn.nodemanager.local-dirs を介してアプリケーションキャッシュにアクセスします。このディレクトリには、起動スクリプト、JAR、および各コンテナの起動に使用されるすべての環境変数が含まれています。このプロセスは、特にクラスパスの問題をデバッグするのに役立ちます。(これを有効にするにはクラスター設定で管理者権限が必要であり、すべてのノードマネージャーの再起動が必要であることに注意してください。したがって、ホストされているクラスターには適用できません)。
アプリケーションマスターまたはエグゼキュータ用のカスタム log4j2 設定を使用するには、以下のオプションがあります。
spark-submitでカスタムlog4j2.propertiesをアップロードします。これは、アプリケーションと一緒にアップロードされるファイルの--filesリストに追加することで行います。-Dlog4j.configurationFile=<設定ファイルの場所>をspark.driver.extraJavaOptions(ドライバーの場合) またはspark.executor.extraJavaOptions(エグゼキュータの場合) に追加します。ファイルを使用する場合、file:プロトコルを明示的に指定する必要があり、ファイルはすべてのノードでローカルに存在する必要があることに注意してください。$SPARK_CONF_DIR/log4j2.propertiesファイルを更新すると、他の設定と一緒に自動的にアップロードされます。複数のオプションが指定された場合、他の 2 つのオプションがこのオプションよりも優先されることに注意してください。
最初のオプションの場合、エグゼキュータとアプリケーションマスターは同じ log4j 設定を共有し、同じノードで実行される場合 (例: 同じログファイルに書き込もうとする場合) に問題が発生する可能性があることに注意してください。
YARN 上のログファイルに適切な場所への参照が必要で、YARN がそれらを正しく表示および集約できるようにするには、log4j2.properties で spark.yarn.app.container.log.dir を使用します。たとえば、appender.file_appender.fileName=${sys:spark.yarn.app.container.log.dir}/spark.log のようになります。ストリーミングアプリケーションの場合、RollingFileAppender を構成し、ファイル場所を YARN のログディレクトリに設定すると、大きなログファイルによるディスクオーバーフローを回避でき、YARN のログユーティリティを使用してログにアクセスできます。
アプリケーションマスターおよびエグゼキュータ用のカスタム metrics.properties を使用するには、$SPARK_CONF_DIR/metrics.properties ファイルを更新します。他の設定と一緒に自動的にアップロードされるため、--files で手動で指定する必要はありません。
Spark プロパティ
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.yarn.am.memory |
512m |
クライアントモードでの YARN Application Master に使用するメモリ量。JVM メモリ文字列と同じ形式 (例: 512m、2g)。クラスターモードでは、代わりに spark.driver.memory を使用してください。キロバイト、メガバイト、ギガバイト、テラバイト、ペビバイトには、それぞれ小文字の接尾辞 (例: |
1.3.0 |
spark.yarn.am.resource.{resource-type}.amount |
(なし) |
クライアントモードでの YARN Application Master に使用するリソース量。クラスターモードでは、代わりに spark.yarn.driver.resource.<resource-type>.amount を使用してください。この機能は YARN 3.0+ でのみ使用可能であることに注意してください。参考として、YARN リソースモデルのドキュメント を参照してください。例: YARN から GPU リソースを要求するには、以下を使用します: |
3.0.0 |
spark.yarn.applicationType |
SPARK |
より具体的なアプリケーションタイプを定義します。例: SPARK、SPARK-SQL、SPARK-STREAMING、SPARK-MLLIB、SPARK-GRAPH。20 文字を超えないように注意してください。 |
3.1.0 |
spark.yarn.driver.resource.{resource-type}.amount |
(なし) |
クラスターモードでの YARN Application Master に使用するリソース量。この機能は YARN 3.0+ でのみ使用可能であることに注意してください。参考として、YARN リソースモデルのドキュメント を参照してください。 例: YARN から GPU リソースを要求するには、以下を使用します: |
3.0.0 |
spark.yarn.executor.resource.{resource-type}.amount |
(なし) |
エグゼキュータプロセスごとに使用するリソース量。この機能は YARN 3.0+ でのみ使用可能であることに注意してください。参考として、YARN リソースモデルのドキュメント を参照してください。 例: YARN から GPU リソースを要求するには、以下を使用します: |
3.0.0 |
spark.yarn.resourceGpuDeviceName |
yarn.io/gpu |
Spark のリソースタイプ `gpu` と、GPU を表す YARN リソースのマッピングを指定します。デフォルトでは YARN は yarn.io/gpu を使用しますが、YARN がカスタムリソースタイプで構成されている場合、これにより再マッピングできます。spark.{driver/executor}.resource.gpu.* 設定を使用する場合に適用されます。 |
3.2.1 |
spark.yarn.resourceFpgaDeviceName |
yarn.io/fpga |
Spark のリソースタイプ `fpga` と、FPGA を表す YARN リソースのマッピングを指定します。デフォルトでは YARN は yarn.io/fpga を使用しますが、YARN がカスタムリソースタイプで構成されている場合、これにより再マッピングできます。spark.{driver/executor}.resource.fpga.* 設定を使用する場合に適用されます。 |
3.2.1 |
spark.yarn.am.cores |
1 |
クライアントモードでの YARN Application Master に使用するコア数。クラスターモードでは、代わりに spark.driver.cores を使用してください。 |
1.3.0 |
spark.yarn.am.waitTime |
100s |
cluster モードでのみ使用されます。YARN Application Master が SparkContext の初期化を待つ時間。 |
1.3.0 |
spark.yarn.submit.file.replication |
HDFS のデフォルトレプリケーション (通常は 3) |
アプリケーションのために HDFS にアップロードされるファイルに対する HDFS レプリケーションレベル。これには、Spark JAR、アプリケーション JAR、および分散キャッシュファイル/アーカイブなどが含まれます。 | 0.8.1 |
spark.yarn.stagingDir |
ファイルシステム上の現在のユーザーのホームディレクトリ | アプリケーションのサブミット中に使用されるステージングディレクトリ。 | 2.0.0 |
spark.yarn.preserve.staging.files |
false |
ジョブの終了時にステージングされたファイル (Spark JAR、アプリケーション JAR、分散キャッシュファイル) を削除せずに保持するには true に設定します。 |
1.1.0 |
spark.yarn.scheduler.heartbeat.interval-ms |
3000 |
Spark アプリケーションマスターが YARN ResourceManager にハートビートする間隔 (ミリ秒)。値は YARN の有効期限間隔の設定値の半分、つまり yarn.am.liveness-monitor.expiry-interval-ms の値に制限されます。 |
0.8.1 |
spark.yarn.scheduler.initial-allocation.interval |
200ms |
Spark アプリケーションマスターが保留中のコンテナ割り当て要求に対して積極的にハートビートする初期間隔。spark.yarn.scheduler.heartbeat.interval-ms より大きくてはいけません。保留中のコンテナがまだ存在する場合、積極的なハートビートは successive heartbeats で倍増し、spark.yarn.scheduler.heartbeat.interval-ms に達するまで続きます。 |
1.4.0 |
spark.yarn.historyServer.address |
(なし) | Spark History Server のアドレス。例: host.com:18080。アドレスにはスキーム (http://) を含めてはいけません。History Server はオプションのサービスであるため、デフォルトでは設定されていません。このアドレスは、Spark アプリケーションが終了したときに YARN ResourceManager に与えられ、ResourceManager UI から Spark History Server UI へのリンクが作成されます。このプロパティでは、YARN プロパティを変数として使用でき、これらは実行時に Spark によって置換されます。たとえば、Spark History Server が YARN ResourceManager と同じノードで実行されている場合、${hadoopconf-yarn.resourcemanager.hostname}:18080 に設定できます。 |
1.0.0 |
spark.yarn.dist.archives |
(なし) | 各エグゼキュータの作業ディレクトリに展開されるアーカイブのコンマ区切りリスト。 | 1.0.0 |
spark.yarn.dist.files |
(なし) | 各エグゼキュータの作業ディレクトリに配置されるファイルのコンマ区切りリスト。 | 1.0.0 |
spark.yarn.dist.jars |
(なし) | 各エグゼキュータの作業ディレクトリに配置される JAR のコンマ区切りリスト。 | 2.0.0 |
spark.yarn.dist.forceDownloadSchemes |
(なし) |
リソースが YARN の分散キャッシュに追加される前にローカルディスクにダウンロードされるスキームのコンマ区切りリスト。YARN サービスが http、https、ftp のような Spark でサポートされているスキームをサポートしていない場合、またはローカル YARN クライアントのクラスパスに必要とされる JAR の場合に使用します。ワイルドカード '*' は、すべてのスキームのリソースをダウンロードすることを表します。 | 2.3.0 |
spark.executor.instances |
2 |
静的割り当てのエグゼキュータ数。spark.dynamicAllocation.enabled が有効な場合、初期エグゼキュータセットはこのサイズ以上になります。 |
1.0.0 |
spark.yarn.am.memoryOverhead |
AM メモリ * 0.10、最小値 384 | クライアントモードでの YARN Application Master の場合と同様ですが、spark.driver.memoryOverhead と同じです。 |
1.3.0 |
spark.yarn.queue |
default |
アプリケーションがサブミットされる YARN キューの名前。 | 1.0.0 |
spark.yarn.jars |
(なし) | YARN コンテナに配布される Spark コードを含むライブラリのリスト。デフォルトでは、Spark on YARN はローカルにインストールされた Spark JAR を使用しますが、Spark JAR は HDFS 上のどこにでも読み取り可能な場所に配置することもできます。これにより、YARN はノードにキャッシュできるため、アプリケーションが実行されるたびに配布する必要がなくなります。たとえば、HDFS 上の JAR を指すには、この設定を hdfs:///some/path に設定します。Glob パターンも使用できます。 |
2.0.0 |
spark.yarn.archive |
(なし) | YARN キャッシュに配布するために必要な Spark JAR を含むアーカイブ。設定されている場合、この設定は spark.yarn.jars を置き換え、アーカイブはアプリケーションのすべてのコンテナで使用されます。アーカイブには、ルートディレクトリに JAR ファイルが含まれている必要があります。前のオプションと同様に、アーカイブを HDFS 上にホストしてファイル配布を高速化することもできます。 |
2.0.0 |
spark.yarn.appMasterEnv.[EnvironmentVariableName] |
(なし) | YARN 上で起動される Application Master プロセスに、EnvironmentVariableName で指定された環境変数を追加します。ユーザーは複数のこれらの変数を指定して、複数の環境変数を設定できます。cluster モードでは、これは Spark ドライバーの環境を制御し、client モードではエグゼキュータランチャーの環境のみを制御します。 |
1.1.0 |
spark.yarn.containerLauncherMaxThreads |
25 |
エグゼキュータコンテナを起動するための YARN Application Master で使用されるスレッドの最大数。 | 1.2.0 |
spark.yarn.am.extraJavaOptions |
(なし) | クライアントモードでの YARN Application Master に渡される追加の JVM オプションの文字列。クラスターモードでは、代わりに spark.driver.extraJavaOptions を使用してください。このオプションで最大ヒープサイズ (-Xmx) 設定を設定することは不正であることに注意してください。最大ヒープサイズ設定は spark.yarn.am.memory で設定できます。 |
1.3.0 |
spark.yarn.am.extraLibraryPath |
(なし) | クライアントモードで YARN Application Master を起動する際に使用する特別なライブラリパスを設定します。 | 1.4.0 |
spark.yarn.populateHadoopClasspath |
with-hadoop Spark ディストリビューションでは false に設定されています。no-hadoop ディストリビューションでは true に設定されています。 |
yarn.application.classpath および mapreduce.application.classpath から Hadoop クラスパスを埋め込むかどうか。false に設定されている場合、Hadoop ランタイムをバンドルした with-Hadoop Spark ディストリビューションが必要になるか、ユーザーが別途 Hadoop インストールを提供する必要があることに注意してください。 |
2.4.6 |
spark.yarn.maxAppAttempts |
YARN の yarn.resourcemanager.am.max-attempts |
アプリケーションのサブミットが試行される最大回数。YARN 設定のグローバルの最大試行回数より多くてはいけません。 | 1.3.0 |
spark.yarn.am.attemptFailuresValidityInterval |
(なし) | AM 障害追跡の有効期間を定義します。AM が少なくとも定義された間実行されている場合、AM 障害カウントはリセットされます。この機能は、設定されていない場合は有効になりません。 | 1.6.0 |
spark.yarn.am.clientModeTreatDisconnectAsFailed |
false | yarn-client の不正な切断を障害として扱います。yarn-client モードでは、アプリケーションが意図的にユーザーによって終了されたのか、または実際の障害が発生したのかを知ることができない場合があるため、アプリケーションは通常 SUCCESS の最終ステータスで終了します。この設定は、Application Master がドライバーから不正に切断された場合 (つまり、適切なシャットダウンハンドシェイクなしで) アプリケーションは FAILED の最終ステータスで終了するように、この動作を変更します。これにより、呼び出し元はそれが本当に障害であったかどうかを決定できます。この設定が有効であり、ユーザーがクライアントアプリケーションを誤って終了した場合、実際には FAILED ではなかったのに FAILED ステータスを示す可能性があることに注意してください。 | 3.3.0 |
spark.yarn.am.clientModeExitOnError |
false | yarn-client モードで、これが true の場合、ドライバーが KILLED または FAILED の最終ステータスを持つアプリケーションレポートを取得した場合、ドライバーは対応する SparkContext を停止し、コード 1 でプログラムを終了します。これが true で、別のアプリケーションから呼び出された場合、親アプリケーションも終了することに注意してください。 | 3.3.0 |
spark.yarn.am.tokenConfRegex |
(なし) | この設定の値は、ジョブの設定ファイル (例: hdfs-site.xml) から設定エントリのリストを取得するために使用される正規表現です。RM に送信され、RM はデリゲーショントークンを更新する際にそれらを使用します。この機能の典型的な使用例は、YARN クラスターが複数の下流 HDFS クラスターと通信する必要がある環境でデリゲーショントークンをサポートすることです。この場合、YARN RM はこれらのクラスターに接続するための設定 (例: dfs.nameservices、dfs.ha.namenodes.*、dfs.namenode.rpc-address.*) を持っていない可能性があります。このシナリオでは、Spark ユーザーは設定値を ^dfs.nameservices\$|^dfs.namenode.rpc-address.*\$|^dfs.ha.namenodes.*\$ に設定して、これらの HDFS 設定をジョブのローカル設定ファイルから解析できます。この設定は mapreduce.job.send-token-conf に非常に似ています。詳細については YARN-5910 を参照してください。 |
3.3.0 |
spark.yarn.submit.waitAppCompletion |
true |
YARN クラスターモードでは、クライアントがアプリケーション完了まで終了せずに待機するかどうかを制御します。true に設定されている場合、クライアントプロセスはアプリケーションのステータスを報告してアクティブなままになります。そうでない場合、クライアントプロセスはサブミット後に終了します。 |
1.4.0 |
spark.yarn.am.nodeLabelExpression |
(なし) | AM がスケジューリングされるノードのセットを制限する YARN ノードラベル式。YARN のバージョン 2.6 以上のみがノードラベル式をサポートしているため、それ以前のバージョンで実行する場合は、このプロパティは無視されます。 | 1.6.0 |
spark.yarn.executor.nodeLabelExpression |
(なし) | エグゼキュータがスケジューリングされるノードのセットを制限する YARN ノードラベル式。YARN のバージョン 2.6 以上のみがノードラベル式をサポートしているため、それ以前のバージョンで実行する場合は、このプロパティは無視されます。 | 1.4.0 |
spark.yarn.tags |
(なし) | YARN ApplicationReports として渡される文字列のコンマ区切りリスト。YARN アプリケーションをクエリする際にフィルタリングに使用できます。 | 1.5.0 |
spark.yarn.priority |
(なし) | 保留中のアプリケーションの順序付けポリシーを定義するための YARN のアプリケーション優先度。整数値が高いほど、アクティブ化される機会が増えます。現在、YARN は FIFO 順序付けポリシーを使用している場合のみアプリケーション優先度をサポートしています。 | 3.0.0 |
spark.yarn.config.gatewayPath |
(なし) | Spark アプリケーションが起動されるゲートウェイホストで有効なパスですが、クラスター内の他のノードでの同じリソースのパスとは異なる場合があります。spark.yarn.config.replacementPath と組み合わせて、Spark がリモートプロセスを正しく起動できるように、異種構成のクラスターをサポートするために使用されます。置換パスには通常、YARN によってエクスポートされ、したがって Spark コンテナから見える環境変数への参照が含まれます。 たとえば、ゲートウェイノードに Hadoop ライブラリが |
1.5.0 |
spark.yarn.config.replacementPath |
(なし) | spark.yarn.config.gatewayPath を参照してください。 |
1.5.0 |
spark.yarn.rolledLog.includePattern |
(なし) | 定義されたインクルードパターンに一致するログファイルをフィルタリングするための Java Regex。これらのログファイルはローリング方式で集約されます。これは YARN のローリングログ集約と共に使用されます。この機能を YARN 側で有効にするには、yarn-site.xml で yarn.nodemanager.log-aggregation.roll-monitoring-interval-seconds を設定する必要があります。Spark の log4j アペンダーは、実行中にファイルが削除される可能性のある FileAppender またはその他のアペンダーを使用するように変更する必要があります。log4j 設定で構成されたファイル名 (例: spark.log) に基づいて、ユーザーは集約する必要のあるすべてのログファイルをインクルードする正規表現 (spark*) を設定する必要があります。 |
2.0.0 |
spark.yarn.rolledLog.excludePattern |
(なし) | 定義されたエクルードパターンに一致するログファイルをフィルタリングするための Java Regex。これらのログファイルはローリング方式で集約されません。ログファイル名がインクルードパターンとエクルードパターンの両方に一致する場合、このファイルは最終的に除外されます。 | 2.0.0 |
spark.yarn.executor.launch.excludeOnFailure.enabled |
false | YARN リソース割り当ての問題があるノードを除外することを有効にするフラグ。除外エラーの制限は spark.excludeOnFailure.application.maxFailedExecutorsPerNode で構成できます。 |
2.4.0 |
spark.yarn.exclude.nodes |
(なし) | リソース割り当てから除外される YARN ノード名のコンマ区切りリスト。 | 3.0.0 |
spark.yarn.metrics.namespace |
(なし) | AM メトリクスレポートのルート名前空間。設定されていない場合、YARN アプリケーション ID が使用されます。 | 2.4.0 |
spark.yarn.report.interval |
1s |
クラスターモードでの現在の Spark ジョブステータスのレポート間隔。 | 0.9.0 |
spark.yarn.report.loggingFrequency |
30 |
次のアプリケーションステータスがログに記録されるまでの、処理されたアプリケーションレポートの最大数。状態の変更があった場合、処理されたアプリケーションレポートの数に関係なく、アプリケーションステータスがログに記録されます。 | 3.5.0 |
spark.yarn.clientLaunchMonitorInterval |
1s |
アプリ起動中にクライアントモード AM のステータスを要求する間隔。 | 2.3.0 |
spark.yarn.includeDriverLogsLink |
false |
クラスターモードでは、クライアントアプリケーションレポートにドライバーコンテナのログへのリンクが含まれるかどうか。これには ResourceManager の REST API をポーリングする必要があるため、RM に追加の負荷がかかります。 | 3.1.0 |
spark.yarn.unmanagedAM.enabled |
false |
クライアントモードでは、Application Master サービスをアンマネージドアムとしてクライアントの一部として起動するかどうか。 | 3.0.0 |
spark.yarn.shuffle.server.recovery.disabled |
false | セキュリティ要件が高いアプリケーションで、秘密鍵がデータベースに保存されないことを優先する場合に true に設定します。このようなアプリケーションのシャフルデータは、外部シャフルサービスが再起動しても復旧されません。 | 3.5.0 |
SHS カスタムエグゼキュータログ URL の利用可能なパターン
| パターン | 意味 |
|---|---|
| {{HTTP_SCHEME}} | YARN HTTP ポリシーに従った http:// または https://。(yarn.http.policy 経由で設定) |
| {{NM_HOST}} | コンテナが実行されたノードの「ホスト」。 |
| {{NM_PORT}} | コンテナが実行されたノードマネージャーの「ポート」。 |
| {{NM_HTTP_PORT}} | コンテナが実行されたノードマネージャーの HTTP サーバーの「ポート」。 |
| {{NM_HTTP_ADDRESS}} | コンテナが割り当てられたノードの HTTP URI。 |
| {{CLUSTER_ID}} | Resource Manager のクラスター ID。(yarn.resourcemanager.cluster-id 経由で設定) |
| {{CONTAINER_ID}} | コンテナの ID。 |
| {{USER}} | システム環境の SPARK_USER。 |
| {{FILE_NAME}} | stdout、stderr。 |
たとえば、ジョブ履歴サーバーに直接ログ URL リンクをポイントさせたい場合、ノードマネージャーの HTTP サーバーがリダイレクトするのではなく、以下のように spark.history.custom.executor.log.url を設定できます。
{{HTTP_SCHEME}}<JHS_HOST>:<JHS_PORT>/jobhistory/logs/{{NM_HOST}}:{{NM_PORT}}/{{CONTAINER_ID}}/{{CONTAINER_ID}}/{{USER}}/{{FILE_NAME}}?start=-4096
注: <JHS_HOST> および <JHS_PORT> は実際の値に置き換える必要があります。
リソース割り当てと設定の概要
カスタムリソーススケジューリングと構成の概要セクションを 設定ページ で必ずお読みください。このセクションでは、リソーススケジューリングの YARN 固有の側面のみについて説明します。
YARN は、ユーザーが Spark で使用したいリソースをサポートするように構成する必要があります。YARN でのリソーススケジューリングは YARN 3.1.0 で追加されました。リソースの構成と適切な分離設定の詳細については、YARN のドキュメントを参照してください。理想的には、リソースは分離されているため、エグゼキュータは割り当てられたリソースのみを確認できます。分離が有効になっていない場合、ユーザーはリソースがエグゼキュータ間で共有されないことを保証する検出スクリプトを作成する責任があります。
YARN はユーザー定義のリソースタイプをサポートしていますが、GPU (yarn.io/gpu) および FPGA (yarn.io/fpga) の組み込みタイプがあります。そのため、これらのリソースのいずれかを使用している場合、Spark は Spark リソースの要求を YARN リソースに変換でき、spark.{driver/executor}.resource. 設定を指定するだけで済みます。GPU または FPGA 用にカスタムリソースタイプを使用している場合、Spark マッピングは spark.yarn.resourceGpuDeviceName および spark.yarn.resourceFpgaDeviceName を使用して変更できることに注意してください。FPGA または GPU 以外のリソースを使用している場合、ユーザーは YARN (spark.yarn.{driver/executor}.resource.) および Spark (spark.{driver/executor}.resource.) の両方の設定を指定する責任があります。
たとえば、ユーザーが各エグゼキュータに 2 つの GPU を要求したいとします。ユーザーは spark.executor.resource.gpu.amount=2 を指定するだけで、Spark は YARN から yarn.io/gpu リソースタイプを要求することを処理します。
ユーザー定義の YARN リソース(ここでは acceleratorX と呼びます)がある場合、ユーザーは spark.yarn.executor.resource.acceleratorX.amount=2 と spark.executor.resource.acceleratorX.amount=2 を指定する必要があります。
YARN は Spark に各コンテナに割り当てられたリソースのアドレスを通知しません。そのため、ユーザーはエグゼキュータが起動時に実行され、そのエグゼキュータが利用可能なリソースを検出するための検出スクリプトを指定する必要があります。スクリプトの例は examples/src/main/scripts/getGpusResources.sh で見つけることができます。スクリプトには実行権限を設定する必要があり、ユーザーは悪意のあるユーザーがそれを変更できないように権限を設定する必要があります。スクリプトは、ResourceInformation クラスの形式で JSON 文字列を標準出力に書き出す必要があります。これには、リソース名と、そのエグゼキュータのみが利用可能なリソースアドレスの配列が含まれます。
ステージレベルのスケジューリング概要
ステージレベルのスケジューリングは YARN でサポートされています。
- 動的割り当てが無効な場合: ユーザーはステージレベルで異なるタスクリソース要件を指定でき、起動時に要求されたのと同じ Executor を使用します。
- 動的割り当てが有効な場合: ユーザーはステージレベルでタスクおよびエグゼキュータのリソース要件を指定でき、追加のエグゼキュータを要求します。
YARN 固有のこととして、各 ResourceProfile は YARN で異なるコンテナ優先度を必要とします。マッピングは単純に ResourceProfile ID が優先度になり、YARN では数値が小さいほど優先度が高くなります。これは、先に作成されたプロファイルが YARN でより高い優先度を持つことを意味します。通常、Spark は 1 つのステージを完了してから次のステージを開始するため、これは問題になりませんが、ジョブサーバータイプのシナリオでは影響がある可能性があり、注意が必要です。カスタムリソースの処理方法において、ベースのデフォルトプロファイルとカスタム ResourceProfiles の間に違いがあることに注意してください。ユーザーが Spark スケジューリングしない追加リソースを持つ YARN コンテナを要求できるようにするには、ユーザーは spark.yarn.executor.resource. 設定でリソースを指定できます。これらの設定はベースのデフォルトプロファイルでのみ使用され、他のカスタム ResourceProfiles には伝播されません。これは、ステージにそれらを持たたくない場合、それらを削除する方法がないためです。その結果、デフォルトプロファイルには、spark.yarn.executor.resource. で定義されたカスタムリソースと、GPU または FPGA の Spark 定義リソースが含まれます。Spark は GPU および FPGA リソースを YARN の組み込みタイプ (yarn.io/gpu) および yarn.io/fpga に変換しますが、他のリソースのマッピングは認識しません。他の Spark カスタムリソースは、デフォルトプロファイルには YARN に伝播されません。したがって、Spark がカスタムリソースに基づいてスケジューリングし、それを YARN に要求したい場合は、YARN (spark.yarn.{driver/executor}.resource.) と Spark (spark.{driver/executor}.resource.) の両方の設定で指定する必要があります。Spark がそれらを使用せずに YARN コンテナのみを要求したい場合は、Spark 設定を省略してください。カスタム ResourceProfiles の場合、Spark がスケジューリングしないリソースを YARN で要求しながら、カスタムリソースのみを指定する方法は現在ありません。これは、カスタム ResourceProfiles では、ResourceProfile で定義されたすべてのリソースが YARN に伝播されることを意味します。GPU および FPGA も YARN の組み込みタイプに変換されます。これは、指定するカスタムリソースの名前が YARN で定義されているものと一致する必要があることを意味します。
重要な注意事項
- コア要求がスケジューリング決定で尊重されるかどうかは、使用されているスケジューラとその構成方法によって異なります。
clusterモードでは、Spark エグゼキュータおよび Spark ドライバーが使用するローカルディレクトリは、YARN (Hadoop YARN 設定yarn.nodemanager.local-dirs) 用に構成されたローカルディレクトリになります。ユーザーがspark.local.dirを指定しても、無視されます。clientモードでは、Spark エグゼキュータは YARN 用に構成されたローカルディレクトリを使用しますが、Spark ドライバーはspark.local.dirで定義されたものを使用します。これは、Spark ドライバーがclientモードでは YARN クラスター上で実行されず、Spark エグゼキュータのみが実行されるためです。--filesおよび--archivesオプションは、Hadoop と同様に # を使用してファイル名を指定できます。たとえば、--files localtest.txt#appSees.txtを指定すると、ローカルでlocaltest.txtという名前のファイルが HDFS にアップロードされますが、これはappSees.txtという名前でリンクされ、アプリケーションは YARN 上で実行する際にappSees.txtという名前で参照する必要があります。--jarsオプションは、clusterモードでローカルファイルを使用してSparkContext.addJar関数を動作させることができます。HDFS、HTTP、HTTPS、または FTP ファイルを使用する場合は、使用する必要はありません。
Kerberos
Spark の標準 Kerberos サポートについては、セキュリティ ページで説明されています。
YARN モードでは、Hadoop ファイルシステムにアクセスする際に、Hadoop 設定のデフォルトファイルシステムに加えて、Spark は Spark アプリケーションのステージングディレクトリをホストするサービス用のデリゲーショントークンも自動的に取得します。
YARN 固有の Kerberos 設定
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.kerberos.keytab |
(なし) | 上記で指定されたプリンシパルのキータブが含まれるファイルのフルパス。このキータブは YARN 分散キャッシュを介して YARN Application Master を実行するノードにコピーされ、ログインチケットとデリゲーショントークンを定期的に更新するために使用されます。--keytab コマンドライン引数と同等です。(「local」マスターでも機能します。) |
3.0.0 |
spark.kerberos.principal |
(なし) | セキュアなクラスターで実行する際に KDC にログインするために使用されるプリンシパル。--principal コマンドライン引数と同等です。(「local」マスターでも機能します。) |
3.0.0 |
spark.yarn.kerberos.relogin.period |
1m | Kerberos TGT を更新する必要があるかどうかをチェックする頻度。これは、TGT 更新期間 (または TGT 更新が有効になっていない場合は TGT の有効期間) より短い値に設定する必要があります。デフォルト値はほとんどのデプロイメントで十分です。 | 2.3.0 |
spark.yarn.kerberos.renewal.excludeHadoopFileSystems |
(なし) | リソーススケジューラでのデリゲーショントークン更新から除外される Hadoop ファイルシステムのホストのコンマ区切りリスト。例: spark.yarn.kerberos.renewal.excludeHadoopFileSystems=hdfs://nn1.com:8032, hdfs://nn2.com:8032。これは現在 YARN で動作することが知られており、YARN Resource Manager はアプリケーションのトークンを更新しません。リソーススケジューラはトークンを更新しないため、元のトークン有効期限より長く実行されているアプリケーションがそのトークンを使用しようとすると失敗する可能性が高いことに注意してください。 |
3.2.0 |
Kerberos のトラブルシューティング
Hadoop/Kerberos の問題をデバッグするのは「難しい」場合があります。有用なテクニックの 1 つは、HADOOP_JAAS_DEBUG 環境変数を設定して、Hadoop で Kerberos 操作の追加ログを有効にすることです。
export HADOOP_JAAS_DEBUG=true
JDK クラスは、システムプロパティ sun.security.krb5.debug および sun.security.spnego.debug=true を介して、Kerberos および SPNEGO/REST 認証の追加ログを有効にするように構成できます。
-Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true
これらすべてのオプションは Application Master で有効にできます。
spark.yarn.appMasterEnv.HADOOP_JAAS_DEBUG true
spark.yarn.am.extraJavaOptions -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true
最後に、org.apache.spark.deploy.yarn.Client のログレベルが DEBUG に設定されている場合、ログには取得されたすべてのトークンとその有効期限の詳細のリストが含まれます。
外部シャフルサービスの構成
YARN クラスターの各 NodeManager で Spark Shuffle Service を起動するには、以下の手順に従ってください。
- YARN プロファイル で Spark をビルドします。事前パッケージ化されたディストリビューションを使用している場合は、この手順をスキップしてください。
spark-<version>-yarn-shuffle.jarを見つけます。Spark を自分でビルドしている場合は$SPARK_HOME/common/network-yarn/target/scala-<version>の下に、ディストリビューションを使用している場合はyarnの下にあります。- この JAR をクラスターのすべての
NodeManagerのクラスパスに追加します。 - 各ノードの
yarn-site.xmlで、yarn.nodemanager.aux-servicesにspark_shuffleを追加し、次にyarn.nodemanager.aux-services.spark_shuffle.classをorg.apache.spark.network.yarn.YarnShuffleServiceに設定します。 etc/hadoop/yarn-env.shでYARN_HEAPSIZE(デフォルト 1000) を設定してNodeManagerのヒープサイズを増やし、シャフルの間のガベージコレクションの問題を回避します。- クラスターのすべての
NodeManagerを再起動します。
シャフルサービスが YARN で実行されている場合、次の追加設定オプションが利用可能です。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.yarn.shuffle.stopOnFailure |
false |
Spark Shuffle Service の初期化に失敗した場合に NodeManager を停止するかどうか。これにより、Spark Shuffle Service が実行されていない NodeManager で実行中のコンテナによるアプリケーション障害を防ぎます。 | 2.1.0 |
spark.yarn.shuffle.service.metrics.namespace |
sparkShuffleService |
NodeManager の Hadoop metrics2 システムにシャフルサービスメトリクスをエミットする際に使用する名前空間。 | 3.2.0 |
spark.yarn.shuffle.service.logs.namespace |
(未設定) |
YARN シャフルサービスからのログのエミットに使用するロガー名を形成する際にクラス名に追加される名前空間。例: org.apache.spark.network.yarn.YarnShuffleService.logsNamespaceValue。一部のロギングフレームワークはロガー名がクラス名のように見えることを期待するため、一般的に Java パッケージまたはクラス名として有効であり、スペースを含まない値を提供することが推奨されます。 |
3.3.0 |
spark.shuffle.service.db.backend |
ROCKSDB | YARN でワーク保存再起動が有効になっている場合、これはシャフルサービス状態ストアで使用されるディスクベースストアを指定するために使用され、`ROCKSDB` と `LEVELDB` (非推奨) をサポートし、デフォルト値は `ROCKSDB` です。`RocksDB/LevelDB` の元のデータストアは、現在自動的に別の種類のストレージに変換されません。元のデータストアは保持され、ストレージタイプを切り替えるときに新しいタイプのデータストアが作成されます。 | 3.4.0 |
上記の指示は、デフォルトのシャフルサービス名 spark_shuffle が使用されていることを前提としていることに注意してください。ここでは任意の名前を使用できますが、YARN NodeManager 設定で使用される値は、Spark アプリケーションの spark.shuffle.service.name の値と一致する必要があります。
デフォルトでは、シャフルサービスは Hadoop 設定 (例: yarn-site.xml) からすべての設定を取得します。ただし、spark-shuffle-site.xml という名前のファイルを使用してシャフルサービスを個別に構成することも可能です。このファイルはシャフルサービスのクラスパスに配置する必要があり (デフォルトでは NodeManager のクラスパスと共有されています)。シャフルサービスは、これを標準の Hadoop 設定リソースとして扱い、NodeManager の設定の上に重ね合わせます。
Apache Oozie を使用したアプリケーションの起動
Apache Oozie は、ワークフローの一部として Spark アプリケーションを起動できます。セキュアなクラスターでは、起動されたアプリケーションはクラスターのサービスにアクセスするために関連するトークンを必要とします。Spark がキータブで起動される場合、これは自動的です。しかし、Spark がキータブなしで起動される場合、セキュリティ設定の責任は Oozie に委ねられる必要があります。
セキュアなクラスター用の Oozie の構成とジョブの認証情報の取得の詳細については、Oozie ウェブサイト の特定のリリースドキュメントの「認証」セクションを参照してください。
Spark アプリケーションの場合、Oozie ワークフローは、アプリケーションが必要とするすべてのトークンを Oozie が要求するように設定する必要があります。これには以下が含まれます。
- YARN リソースマネージャー。
- ローカル Hadoop ファイルシステム。
- I/O のソースまたは宛先として使用されるリモート Hadoop ファイルシステム。
- Hive — 使用する場合。
- HBase — 使用する場合。
- YARN タイムラインサーバー — アプリケーションがこれとやり取りする場合。
Spark が Hive、HBase、およびリモート HDFS トークンを取得しようとして失敗するのを避けるために、Spark 設定でこれらのサービスに対するトークン収集を無効にする必要があります。
Spark 設定には、以下の行を含める必要があります。
spark.security.credentials.hive.enabled false
spark.security.credentials.hbase.enabled false
設定オプション spark.kerberos.access.hadoopFileSystems は未設定である必要があります。
Spark Web UI の代わりとなる Spark History Server の使用
アプリケーション UI が無効になっている実行中のアプリケーションのトラッキング URL として Spark History Server アプリケーションページを使用することが可能です。これはセキュアなクラスターでは望ましい場合があり、Spark ドライバーのメモリ使用量を削減できます。Spark History Server を介したトラッキングを設定するには、次の手順を実行します。
- アプリケーション側で、Spark の設定で
spark.yarn.historyServer.allowTracking=trueを設定します。これにより、アプリケーション UI が無効になっている場合、Spark は History Server の URL をトラッキング URL として使用するようになります。 - Spark History Server 側で、
spark.ui.filters設定のフィルタリストにorg.apache.spark.deploy.yarn.YarnProxyRedirectFilterを追加します。
History Server の情報がアプリケーションのステータスと最新でない場合があることに注意してください。
Spark シャフルサービスの複数バージョンの実行
このセクションは YARN バージョン >= 2.9.0 で実行する場合にのみ適用されることに注意してください。
場合によっては、異なる Spark バージョンを使用する Spark Shuffle Service の複数のインスタンスを実行することが望ましい場合があります。これは、たとえば、複数の Spark バージョンを実行するアプリケーションの混合ワークロードを持つ YARN クラスターを実行する場合に役立ちます。なぜなら、特定のバージョンのシャフルサービスは、他の Spark バージョンと常に互換性があるわけではないからです。YARN 2.9.0 以降では、シャフルサービスを分離されたクラスローダー内で実行する機能がサポートされています (YARN-4577 YARN-4577 を参照)。これにより、単一の NodeManager 内で複数の Spark バージョンが共存できます。yarn.nodemanager.aux-services.<service-name>.classpath および YARN 2.10.2/3.1.1/3.2.0 以降では、yarn.nodemanager.aux-services.<service-name>.remote-classpath オプションを使用してこれを構成できます。YARN 3.3.0/3.3.1 には、回避策として yarn.nodemanager.aux-services.<service-name>.system-classes を設定する必要がある問題があることに注意してください。詳細は YARN-11053 YARN-11053 を参照してください。個別のクラスパスを設定することに加えて、2 つのサービスが異なるポートでアドバタイズされるようにする必要があります。これは、上記で説明した spark-shuffle-site.xml ファイルを使用して達成できます。たとえば、次のような構成がある場合があります。
yarn.nodemanager.aux-services = spark_shuffle_x,spark_shuffle_y
yarn.nodemanager.aux-services.spark_shuffle_x.classpath = /path/to/spark-x-path/fat.jar:/path/to/spark-x-config
yarn.nodemanager.aux-services.spark_shuffle_y.classpath = /path/to/spark-y-path/fat.jar:/path/to/spark-y-config
または
yarn.nodemanager.aux-services = spark_shuffle_x,spark_shuffle_y
yarn.nodemanager.aux-services.spark_shuffle_x.classpath = /path/to/spark-x-path/*:/path/to/spark-x-config
yarn.nodemanager.aux-services.spark_shuffle_y.classpath = /path/to/spark-y-path/*:/path/to/spark-y-config
2 つの spark-*-config ディレクトリには、それぞれ spark-shuffle-site.xml という名前のファイルが含まれています。これらは Hadoop Configuration フォーマット の XML ファイルであり、それぞれポート番号と使用されるメトリクス名プレフィックスを調整するためのいくつかの設定が含まれています。
<configuration>
<property>
<name>spark.shuffle.service.port</name>
<value>7001</value>
</property>
<property>
<name>spark.yarn.shuffle.service.metrics.namespace</name>
<value>sparkShuffleServiceX</value>
</property>
</configuration>
値は、2 つの異なるサービスでそれぞれ異なる必要があります。
次に、Spark アプリケーションの設定で、一方を次のように構成します。
spark.shuffle.service.name = spark_shuffle_x
spark.shuffle.service.port = 7001
もう一方は次のように構成します。
spark.shuffle.service.name = spark_shuffle_y
spark.shuffle.service.port = <other value>
Spark アプリケーション用の異なる JDK の構成
場合によっては、YARN ノードマネージャーとは異なる JDK を Spark アプリケーションの実行に使用することが望ましい場合があります。これは、YARN コンテナおよび spark-submit プロセスに JAVA_HOME 環境変数を設定することで実現できます。
Spark は、1 つのアプリケーションで実行されるすべての JVM プロセスが同じ JDK バージョンを使用すると想定していることに注意してください。そうでない場合、JDK シリアライゼーションの問題が発生する可能性があります。
すべてのノードに /opt/openjdk-17 に事前にインストールされている JDK を使用するように Spark アプリケーションを構成するには
$ export JAVA_HOME=/opt/openjdk-17
$ ./bin/spark-submit --class path.to.your.Class \
--master yarn \
--conf spark.yarn.appMasterEnv.JAVA_HOME=/opt/openjdk-17 \
--conf spark.executorEnv.JAVA_HOME=/opt/openjdk-17 \
<app jar> [app options]
オプションとして、ユーザーは YARN クラスターノードに別の JDK をインストールすることを避けたい場合があります。そのような場合、YARN の分散キャッシュを使用して JDK を配布することも可能です。たとえば、Java 21 を Spark アプリケーションの実行に使用するには、JDK 21 tarball openjdk-21.tar.gz を準備し、ローカルノードの /opt に解凍してから、Spark アプリケーションをサブミットします。
$ export JAVA_HOME=/opt/openjdk-21
$ ./bin/spark-submit --class path.to.your.Class \
--master yarn \
--archives path/to/openjdk-21.tar.gz \
--conf spark.yarn.appMasterEnv.JAVA_HOME=./openjdk-21.tar.gz/openjdk-21 \
--conf spark.executorEnv.JAVA_HOME=./openjdk-21.tar.gz/openjdk-21 \
<app jar> [app options]