Spark セキュリティ
- Spark セキュリティ: 知っておくべきこと
- Spark RPC (Sparkプロセス間の通信プロトコル)
- ローカルストレージの暗号化
- Web UI
- ネットワークセキュリティのためのポート設定
- Kerberos
- イベントロギング
- クライアントモードでのドライバログの永続化
Spark セキュリティ: 知っておくべきこと
認証などのセキュリティ機能は、デフォルトでは有効になっていません。インターネットまたは信頼できないネットワークに公開されているクラスタをデプロイする場合、権限のないアプリケーションがクラスタ上で実行されないように、クラスタへのアクセスを保護することが重要です。
Sparkは複数のデプロイメントタイプをサポートしており、それぞれが異なるレベルのセキュリティをサポートしています。すべてのデプロイメントタイプがすべての環境で安全であるとは限らず、デフォルトでは安全ではありません。環境、Sparkがサポートしている内容を評価し、Sparkデプロイメントを保護するための適切な対策を講じてください。
セキュリティに関する懸念事項には、さまざまな種類があります。Sparkは必ずしもすべてのことから保護するわけではありません。Sparkがサポートしている機能の一部を以下に示します。また、使用しているデプロイメントの種類のデプロイメントドキュメントで、デプロイメント固有の設定を確認してください。文書化されていないものは、Sparkではサポートされていません。
Spark RPC (Sparkプロセス間の通信プロトコル)
認証
Sparkは現在、共有シークレットを使用したRPCチャネルの認証をサポートしています。認証は、`spark.authenticate`設定パラメータを設定することで有効にできます。
共有シークレットの生成と配布に使用される正確なメカニズムは、デプロイメントによって異なります。以下に指定がない限り、シークレットは`spark.authenticate.secret`設定オプションを設定することによって定義する必要があります。その場合、同じシークレットがそのSparkアプリケーションとデーモンすべてで共有されるため、特にマルチテナントクラスタでは、これらのデプロイメントのセキュリティが制限されます。
REST送信サーバーとMesosClusterDispatcherは認証をサポートしていません。REST APIとMesosClusterDispatcher(デフォルトではそれぞれポート6066と7077)へのすべてのネットワークアクセスが、ジョブを送信することが信頼されているホストに制限されていることを確認する必要があります。
YARN
YARN上のSparkの場合、Sparkは共有シークレットの生成と配布を自動的に処理します。各アプリケーションは一意の共有シークレットを使用します。YARNの場合、この機能は、シークレットの配布を安全にするためにYARN RPC暗号化が有効になっていることに依存しています。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.yarn.shuffle.server.recovery.disabled |
false | セキュリティ要件が高く、シークレットがデータベースに保存されないことを好むアプリケーションの場合は、trueに設定します。このようなアプリケーションのシャッフルデータは、External Shuffle Serviceの再起動後には回復されません。 | 3.5.0 |
Kubernetes
Kubernetesでは、Sparkは各アプリケーションに固有の認証シークレットも自動的に生成します。シークレットは、環境変数を使用してexecutorポッドに伝播されます。これは、Sparkアプリケーションが実行されている名前空間でポッドをリストできるユーザーは誰でも、認証シークレットを見ることができることを意味します。Spark認証が安全であることを保証するために、Kubernetes管理者によってアクセス制御ルールが適切に設定されている必要があります。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.authenticate |
false | Sparkが内部接続を認証するかどうか。 | 1.0.0 |
spark.authenticate.secret |
なし | 認証に使用される秘密鍵。この設定をいつ設定する必要があるかについては、上記を参照してください。 | 1.0.0 |
または、ユーザーがポッドにマウントするファイルとKubernetesシークレットを使用して、認証シークレットをマウントできます。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.authenticate.secret.file |
なし | 接続の保護に使用する秘密鍵を指すパス。ファイルの内容が安全に生成されていることを確認してください。このファイルは、他の設定でこれがオーバーライドされない限り(下記参照)、ドライバーとexecutorの両方でロードされます。 | 3.0.0 |
spark.authenticate.secret.driver.file |
`spark.authenticate.secret.file`の値 | 指定した場合、Sparkドライバーがシークレットを読み込む場所をオーバーライドします。クライアントモードで、シークレットファイルの場所がポッドとドライバーが実行されているノードで異なる場合に便利です。これを指定する場合は、`spark.authenticate.secret.executor.file`を指定して、ドライバーとexecutorの両方がファイルを使用して秘密鍵を読み込めるようにする必要があります。ドライバー上のファイルの内容がexecutor上のファイルの内容と同一であることを確認してください。 | 3.0.0 |
spark.authenticate.secret.executor.file |
`spark.authenticate.secret.file`の値 | 指定した場合、Spark executorがシークレットを読み込む場所をオーバーライドします。クライアントモードで、シークレットファイルの場所がポッドとドライバーが実行されているノードで異なる場合に便利です。これを指定する場合は、`spark.authenticate.secret.driver.file`を指定して、ドライバーとexecutorの両方がファイルを使用して秘密鍵を読み込めるようにする必要があります。ドライバー上のファイルの内容がexecutor上のファイルの内容と同一であることを確認してください。 | 3.0.0 |
ファイルを使用する場合、Sparkはこれらのファイルをコンテナにマウントしないことに注意してください。秘密ファイルがコンテナに安全にデプロイされ、ドライバーの秘密ファイルがexecutorの秘密ファイルと一致することを確認するのは、ユーザーの責任です。
暗号化
Sparkは、RPC接続にAESベースの暗号化をサポートしています。暗号化を有効にするには、RPC認証も有効にして適切に設定する必要があります。AES暗号化はApache Commons Cryptoライブラリを使用し、Sparkの設定システムでは、上級ユーザーがそのライブラリの設定にアクセスできます。
SASLベースの暗号化のサポートもありますが、非推奨と見なされるべきです。2.2.0より古いバージョンのSparkからシャッフルサービスと通信する場合には、まだ必要です。
次の表に、この機能の設定に使用できるさまざまなオプションを示します。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.network.crypto.enabled |
false | 2.2.0で追加された新しい認証プロトコルを含む、AESベースのRPC暗号化を有効にします。 | 2.2.0 |
spark.network.crypto.config.* |
なし | 使用する暗号実装など、commons-cryptoライブラリの構成値。設定名は、`commons.crypto`プレフィックスのないcommons-crypto構成の名前である必要があります。 | 2.2.0 |
spark.network.crypto.saslFallback |
true | Sparkの内部メカニズムを使用した認証が失敗した場合に、SASL認証にフォールバックするかどうか。これは、アプリケーションが内部Spark認証プロトコルをサポートしていない古いシャッフルサービスに接続している場合に便利です。シャッフルサービス側では、この機能を無効にすると、古いクライアントが認証できなくなります。 | 2.2.0 |
spark.authenticate.enableSaslEncryption |
false | SASLベースの暗号化通信を有効にします。 | 2.2.0 |
spark.network.sasl.serverAlwaysEncrypt |
false | SASL認証を使用するポートの暗号化されていない接続を無効にします。これは、認証が有効になっているが、SASLベースの暗号化を要求しないクライアントからの接続を拒否します。 | 1.4.0 |
ローカルストレージの暗号化
Sparkは、ローカルディスクに書き込まれた一時データの暗号化をサポートしています。これは、シャッフルファイル、シャッフルスピル、およびディスクに保存されたデータブロック(キャッシングとブロードキャスト変数の両方)をカバーします。`saveAsHadoopFile`や`saveAsTable`などのAPIを使用してアプリケーションによって生成された出力データの暗号化はカバーしていません。また、ユーザーが明示的に作成した一時ファイルをカバーしていない場合もあります。
次の設定は、ディスクに書き込まれたデータの暗号化を有効にすることをカバーしています
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.io.encryption.enabled |
false | ローカルディスクI/O暗号化を有効にします。現在、Mesosを除くすべてのモードでサポートされています。この機能を使用する場合は、RPC暗号化を有効にすることを強くお勧めします。 | 2.1.0 |
spark.io.encryption.keySizeBits |
128 | IO暗号化キーのサイズ(ビット単位)。サポートされている値は128、192、256です。 | 2.1.0 |
spark.io.encryption.keygen.algorithm |
HmacSHA1 | IO暗号化キーの生成時に使用するアルゴリズム。サポートされているアルゴリズムについては、Java暗号化アーキテクチャ標準アルゴリズム名ドキュメントのKeyGeneratorセクションで説明されています。 | 2.1.0 |
spark.io.encryption.commons.config.* |
なし | 使用する暗号実装など、commons-cryptoライブラリの構成値。設定名は、`commons.crypto`プレフィックスのないcommons-crypto構成の名前である必要があります。 | 2.1.0 |
Web UI
認証と承認
Web UIの認証を有効にするには、javaxサーブレットフィルターを使用します。デプロイする認証方法を実装するフィルターが必要です。Sparkは組み込みの認証フィルターを提供していません。
Sparkは、認証フィルターが存在する場合、UIへのアクセス制御もサポートしています。各アプリケーションは、独自の個別のアクセス制御リスト(ACL)で設定できます。Sparkは、「表示」権限(アプリケーションのUIを表示できるユーザー)と「変更」権限(実行中のアプリケーションでジョブを強制終了するなどの操作を実行できるユーザー)を区別します。
ACLは、ユーザーまたはグループのいずれかに対して設定できます。設定エントリは、入力としてカンマ区切りのリストを受け入れます。つまり、複数のユーザーまたはグループに必要な権限を与えることができます。これは、共有クラスタで実行していて、自分で開始していないアプリケーションを監視する必要がある管理者または開発者のセットがある場合に使用できます。特定のACLに追加されたワイルドカード(`*`)は、すべてのユーザーがそれぞれの権限を持つことを意味します。デフォルトでは、アプリケーションを送信するユーザーのみがACLに追加されます。
グループメンバーシップは、設定可能なグループマッピングプロバイダーを使用して確立されます。マッパーは、以下の表で説明されている`spark.user.groups.mapping`設定オプションを使用して設定されます。
次のオプションは、Web UIの認証を制御します
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.ui.allowFramingFrom |
SAMEORIGIN |
`X-Frame-Options`を介して、特定の名前付きURIのフレーミングを許可します。デフォルトでは、同じ起点からのみ許可します。 | 1.6.0 |
spark.ui.filters |
なし | フィルターの設定方法については、Spark UI設定を参照してください。 | 1.0.0 |
spark.acls.enable |
false | UI ACLを有効にするかどうか。有効にした場合、ユーザーがアプリケーションを表示または変更するためのアクセス許可を持っているかどうかを確認します。これにはユーザーの認証が必要になるため、認証フィルターがインストールされていない場合、このオプションは何もしません。 | 1.1.0 |
spark.admin.acls |
なし | Sparkアプリケーションへの表示および変更アクセス権を持つユーザーのカンマ区切りリスト。 | 1.1.0 |
spark.admin.acls.groups |
なし | Sparkアプリケーションへの表示および変更アクセス権を持つグループのカンマ区切りリスト。 | 2.0.0 |
spark.modify.acls |
なし | Sparkアプリケーションへの変更アクセス権を持つユーザーのカンマ区切りリスト。 | 1.1.0 |
spark.modify.acls.groups |
なし | Spark アプリケーションへの変更アクセス権を持つグループのカンマ区切りリスト。 | 2.0.0 |
spark.ui.view.acls |
なし | Spark アプリケーションへの表示アクセス権を持つユーザーのカンマ区切りリスト。 | 1.0.0 |
spark.ui.view.acls.groups |
なし | Spark アプリケーションへの表示アクセス権を持つグループのカンマ区切りリスト。 | 2.0.0 |
spark.user.groups.mapping |
org.apache.spark.security.ShellBasedGroupsMappingProvider |
ユーザーのグループリストは、このプロパティで設定可能な、`org.apache.spark.security.GroupMappingServiceProvider` トレイトで定義されたグループマッピングサービスによって決定されます。 デフォルトでは、Unix シェルベースの実装が使用され、ホスト OS からこの情報を収集します。 注: この実装は Unix/Linux ベースの環境のみをサポートしています。Windows 環境は現在サポートされていません**。ただし、上記のトレイトを実装することで、新しいプラットフォーム/プロトコルをサポートできます。 |
2.0.0 |
YARN では、アプリケーションの送信時に表示および変更 ACL が YARN サービスに提供され、YARN インターフェースを介してそれぞれの権限を持つユーザーを制御します。
Spark History Server ACL
SHS Web UI の認証は、サーブレットフィルターを使用して、通常のアプリケーションと同じ方法で有効になります。
SHS で認証を有効にするには、いくつかの追加オプションを使用します
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.history.ui.acls.enable |
false | 履歴サーバーでアプリケーションを表示するユーザーを認証するために ACL をチェックするかどうかを指定します。有効にすると、個々のアプリケーションが `spark.ui.acls.enable` に設定した内容に関係なく、アクセス制御チェックが実行されます。アプリケーションの所有者は、常に自身のアプリケーションを表示する権限を持ち、アプリケーションの実行時に `spark.ui.view.acls` で指定されたユーザーと `spark.ui.view.acls.groups` で指定されたグループもそのアプリケーションを表示する権限を持ちます。無効にすると、履歴サーバーを介して利用可能なアプリケーション UI に対してアクセス制御チェックは行われません。 | 1.0.1 |
spark.history.ui.admin.acls |
なし | 履歴サーバー内のすべての Spark アプリケーションへの表示アクセス権を持つユーザーのカンマ区切りリスト。 | 2.1.1 |
spark.history.ui.admin.acls.groups |
なし | 履歴サーバー内のすべての Spark アプリケーションへの表示アクセス権を持つグループのカンマ区切りリスト。 | 2.1.1 |
SHS は、通常のアプリケーションと同様に、グループマッピングプロバイダーを設定するために同じオプションを使用します。この場合、グループマッピングプロバイダーは SHS によってサーバーされるすべての UI に適用され、個々のアプリケーション設定は無視されます。
SSL設定
SSL の設定は階層的に構成されています。ユーザーは、プロトコル固有の設定で上書きされない限り、サポートされているすべての通信プロトコルに使用されるデフォルトの SSL 設定を構成できます。これにより、ユーザーは各プロトコルを個別に設定する機能を無効にすることなく、すべてのプロトコルの共通設定を簡単に提供できます。次の表は、SSL 設定の名前空間を示しています
設定名前空間 | コンポーネント |
---|---|
spark.ssl |
デフォルトの SSL 設定。これらの値は、名前空間レベルで明示的に上書きされない限り、以下のすべての名前空間に適用されます。 |
spark.ssl.ui |
Spark アプリケーション Web UI |
spark.ssl.standalone |
スタンドアロンマスター/ワーカー Web UI |
spark.ssl.historyServer |
履歴サーバー Web UI |
使用可能な SSL オプションの完全な内訳は以下にあります。`${ns}` プレースホルダーは、上記のいずれかの名前空間に置き換える必要があります。
プロパティ名 | デフォルト | 意味 |
---|---|---|
${ns}.enabled |
false | SSL を有効にします。有効にすると、`${ns}.ssl.protocol` が必須です。 |
${ns}.port |
なし | SSL サービスが listen するポート。 ポートは、特定の名前空間設定内で定義する必要があります。この設定を読み取るとき、デフォルトの名前空間は無視されます。 設定されていない場合、SSL ポートは同じサービスの非 SSL ポートから派生します。「0」の値は、サービスを一時ポートにバインドさせます。 |
${ns}.enabledAlgorithms |
なし | 暗号のカンマ区切りリスト。指定された暗号は JVM でサポートされている必要があります。 プロトコルの参照リストは、Java セキュリティガイドの「JSSE Cipher Suite Names」セクションにあります。Java 8 のリストは、このページにあります。 注: 設定されていない場合、JRE のデフォルトの暗号スイートが使用されます。 |
${ns}.keyPassword |
なし | キーストア内の秘密鍵のパスワード。 |
${ns}.keyStore |
なし | キーストアファイルへのパス。パスは、プロセスが開始されたディレクトリからの絶対パスまたは相対パスです。 |
${ns}.keyStorePassword |
なし | キーストアのパスワード。 |
${ns}.keyStoreType |
JKS | キーストアのタイプ。 |
${ns}.protocol |
なし | 使用する TLS プロトコル。プロトコルは JVM でサポートされている必要があります。 プロトコルの参照リストは、Java セキュリティガイドの「Additional JSSE Standard Names」セクションにあります。Java 8 のリストは、このページにあります。 |
${ns}.needClientAuth |
false | クライアント認証を必須とするかどうか。 |
${ns}.trustStore |
なし | トラストストアファイルへのパス。パスは、プロセスが開始されたディレクトリからの絶対パスまたは相対パスです。 |
${ns}.trustStorePassword |
なし | トラストストアのパスワード。 |
${ns}.trustStoreType |
JKS | トラストストアのタイプ。 |
Spark は、Hadoop Credential Providers から `${ns}.keyPassword`、`${ns}.keyStorePassword`、`${ns}.trustStorePassword` を取得することもサポートしています。ユーザーはパスワードを資格情報ファイルに保存し、次のように異なるコンポーネントからアクセスできるようにすることができます。
hadoop credential create spark.ssl.keyPassword -value password \
-provider jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks
資格情報プロバイダーの場所を設定するには、Spark で使用される Hadoop 設定で `hadoop.security.credential.provider.path` 設定オプションを設定します。次のようにします。
<property>
<name>hadoop.security.credential.provider.path</name>
<value>jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks</value>
</property>
または、SparkConf "spark.hadoop.hadoop.security.credential.provider.path=jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks" を使用します。
キーストアの準備
キーストアは `keytool` プログラムで生成できます。Java 8 用のこのツールのリファレンスドキュメントはこちらです。Spark スタンドアロンデプロイメントモードのキーストアとトラストストアを設定するための最も基本的な手順は次のとおりです。
- 各ノードのキーペアを生成する
- キーペアの公開鍵を各ノードのファイルにエクスポートする
- エクスポートされたすべての公開鍵を単一のトラストストアにインポートする
- トラストストアをクラスターノードに配布する
YARNモード
クラスタモードで実行されているドライバーにローカルのトラストストアまたはキーストアファイルを提供するには、`--files` コマンドライン引数(または同等の `spark.files` 設定)を使用してアプリケーションと一緒に配布できます。ファイルはドライバーの作業ディレクトリに配置されるため、TLS 設定は絶対パスなしでファイル名を参照する必要があります。
このようにローカルキーストアを配布するには、ファイルを HDFS(またはクラスタで使用される他の同様の分散ファイルシステム)にステージングする必要がある場合があるため、基盤となるファイルシステムをセキュリティを考慮して設定することをお勧めします(認証とワイヤ暗号化を有効にするなど)。
スタンドアロンモード
ユーザーは、マスターとワーカーのキーストアと設定オプションを提供する必要があります。これらは、`SPARK_MASTER_OPTS` および `SPARK_WORKER_OPTS` 環境変数、または単に `SPARK_DAEMON_JAVA_OPTS` に適切な Java システムプロパティを添付することで設定する必要があります。
ユーザーは、エグゼキュータがワーカープロセスから継承された SSL 設定を使用することを許可できます。これは、`spark.ssl.useNodeLocalConf` を `true` に設定することで実現できます。その場合、クライアント側でユーザーが提供した設定は使用されません。
Mesosモード
Mesos 1.3.0 以降は、ファイルベースと環境ベースの両方のシークレットとして `Secrets` プリミティブをサポートしています。Spark では、それぞれ `spark.mesos.driver.secret.filenames` と `spark.mesos.driver.secret.envkeys` を使用して、ファイルベースと環境変数ベースのシークレットを指定できます。
シークレットストアバックエンドに応じて、`spark.mesos.driver.secret.names` と `spark.mesos.driver.secret.values` 設定プロパティを使用して、それぞれ参照または値でシークレットを渡すことができます。
参照タイプのシークレットはシークレットストアによって提供され、名前(例:`/mysecret`)で参照されます。値タイプのシークレットはコマンドラインで渡され、適切なファイルまたは環境変数に変換されます。
HTTPセキュリティヘッダー
Apache Spark は、クロスサイトスクリプティング(XSS)、クロスフレームスクリプティング(XFS)、MIME スニッフィングの防止、および HTTP Strict Transport Security の適用に役立つ HTTP ヘッダーを含めるように設定できます。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.ui.xXssProtection |
1; mode=block |
HTTP X-XSS-Protection レスポンスヘッダーの値。以下から適切な値を選択できます
|
2.3.0 |
spark.ui.xContentTypeOptions.enabled |
true |
有効にすると、X-Content-Type-Options HTTP レスポンスヘッダーが "nosniff" に設定されます。 | 2.3.0 |
spark.ui.strictTransportSecurity |
なし | HTTP Strict Transport Security (HSTS) レスポンスヘッダーの値。以下から適切な値を選択し、それに応じて `expire-time` を設定できます。このオプションは、SSL/TLS が有効になっている場合にのみ使用されます。
|
2.3.0 |
ネットワークセキュリティのためのポート設定
一般的に、Spark クラスタとそのサービスはパブリックインターネットにデプロイされません。これらは一般にプライベートサービスであり、Spark をデプロイする組織のネットワーク内でのみアクセス可能である必要があります。Spark サービスが使用するホストとポートへのアクセスは、サービスにアクセスする必要があるオリジンホストに制限する必要があります。
以下は、Spark が通信に使用する主要なポートと、それらのポートを設定する方法です。
スタンドアロンモードのみ
送信元 | 送信先 | デフォルトポート | 目的 | 設定 | 備考 |
---|---|---|---|---|---|
ブラウザ | スタンドアロンマスター | 8080 | Web UI | 8080 |
spark.master.ui.port / SPARK_MASTER_WEBUI_PORT |
ブラウザ | Jetty ベース。スタンドアロンモードのみ。 | 8081 | Web UI | スタンドアロンワーカー |
spark.master.ui.port / SPARK_MASTER_WEBUI_PORT |
Web UI Jetty ベース。スタンドアロンモードのみ。 |
スタンドアロンマスター | 7077 | spark.worker.ui.port / SPARK_WORKER_WEBUI_PORT ドライバー / アプリケーション |
7077 |
クラスタにジョブを送信 / クラスタに参加 |
SPARK_MASTER_PORT | スタンドアロンマスター | 6066 | ランダムにポートを選択するには「0」に設定します。スタンドアロンモードのみ。 | 外部サービス |
6066 |
スタンドアロンマスター | Jetty ベース。スタンドアロンモードのみ。 | REST API 経由でクラスタにジョブを送信 | spark.master.rest.port | このサービスを有効/無効にするには、`spark.master.rest.enabled` を使用します。スタンドアロンモードのみ。 |
クラスタにジョブを送信 / クラスタに参加 |
すべてのクラスタマネージャー
送信元 | 送信先 | デフォルトポート | 目的 | 設定 | 備考 |
---|---|---|---|---|---|
ブラウザ | (ランダム) | 4040 | Web UI | エグゼキュータのスケジュール |
SPARK_WORKER_PORT |
ブラウザ | アプリケーション | 18080 | Web UI | 4040 |
SPARK_WORKER_PORT |
Web UI スタンドアロンマスター |
spark.ui.port | REST API 経由でクラスタにジョブを送信 | Jetty ベース 履歴サーバー |
18080 |
Web UI |
spark.history.ui.port | spark.history.ui.port | REST API 経由でクラスタにジョブを送信 | エグゼキュータ / ドライバー | (ランダム) |
アプリケーションに接続 / エグゼキュータの状態変更を通知 |
Kerberos
spark.driver.port
ランダムにポートを選択するには「0」に設定します。
エグゼキュータ / ドライバー
(ランダム)
ブロックマネージャーポート
アプリケーションが他のセキュアなHadoopファイルシステムと対話する必要がある場合、起動時にそれらのURIをSparkに明示的に提供する必要があります。これは、以下の設定セクションで説明されているspark.kerberos.access.hadoopFileSystems
プロパティに、それらをリストすることで行われます。
Sparkは、Javaサービスメカニズム(java.util.ServiceLoader
を参照)を使用したカスタム委任トークンプロバイダーもサポートしています。org.apache.spark.security.HadoopDelegationTokenProvider
の実装は、jarのMETA-INF/services
ディレクトリにある対応するファイルにそれらの名前をリストすることで、Sparkで使用できるようにすることができます。
委任トークンのサポートは、現在、YARNモードとMesosモードでのみサポートされています。詳細については、デプロイメント固有のページを参照してください。
以下のオプションは、この機能をよりきめ細かく制御できます。
プロパティ名 | デフォルト | 意味 | バージョン |
---|---|---|---|
spark.security.credentials.${service}.enabled |
true |
セキュリティが有効になっている場合に、サービスの資格情報を取得するかどうかを制御します。デフォルトでは、サポートされているすべてのサービスの資格情報は、それらのサービスが構成されているときに取得されますが、実行されているアプリケーションと何らかの形で競合する場合、その動作を無効にすることができます。 | 2.3.0 |
spark.kerberos.access.hadoopFileSystems |
(なし) | SparkアプリケーションがアクセスするセキュアなHadoopファイルシステムのカンマ区切りリスト。たとえば、spark.kerberos.access.hadoopFileSystems=hdfs://nn1.com:8032,hdfs://nn2.com:8032, webhdfs://nn3.com:50070 などです。Sparkアプリケーションは、リストされているファイルシステムにアクセスできる必要があり、Kerberosは、それらにアクセスできるように適切に構成されている必要があります(同じレルム内、または信頼できるレルム内)。Sparkは、SparkアプリケーションがそれらのリモートHadoopファイルシステムにアクセスできるように、各ファイルシステムのセキュリティトークンを取得します。 |
3.0.0 |
ユーザーは、リソーススケジューラでのKerberos委任トークンの更新を除外できます。現在、これはYARNでのみサポートされています。設定については、Spark on YARNの実行ページを参照してください。
長時間実行アプリケーション
実行時間が、アクセスする必要があるサービスで設定されている委任トークンの最大有効期間を超えると、長時間実行されるアプリケーションで問題が発生する可能性があります。
この機能は、どこでも利用できるわけではありません。特に、YARNとKubernetes(クライアントモードとクラスタモードの両方)、およびクライアントモードを使用している場合のMesosでのみ実装されています。
Sparkは、これらのアプリケーションの新しいトークンを自動的に作成することをサポートしています。この機能を有効にするには、2つの方法があります。
Keytabの使用
Sparkにプリンシパルとキータブを提供することにより(たとえば、spark-submit
で--principal
および--keytab
パラメータを使用)、アプリケーションは、委任トークンを無期限に取得するために使用できる有効なKerberosログインを維持します。
クラスタモードでキータブを使用する場合、Sparkドライバを実行しているマシンにコピーされることに注意してください。YARNの場合、これはキータブのステージングエリアとしてHDFSを使用することを意味するため、少なくともYARNとHDFSの両方を暗号化で保護することを強くお勧めします。
チケットキャッシュの使用
Sparkの設定でspark.kerberos.renewal.credentials
をccache
に設定することにより、ローカルKerberosチケットキャッシュが認証に使用されます。Sparkは、更新可能な期間中はチケットを更新された状態に保ちますが、有効期限が切れた後は、新しいチケットを取得する必要があります(たとえば、kinit
を実行することにより)。
Sparkが使用できる更新されたチケットキャッシュを維持するのは、ユーザーの責任です。
チケットキャッシュの場所は、KRB5CCNAME
環境変数を設定することでカスタマイズできます。
Kubernetesとの安全な連携
Kerberosの背後にあるHadoopベースのサービスと通信する場合、Sparkは非ローカルプロセスが認証できるように委任トークンを取得する必要があることがわかりました。Kubernetesのこれらの委任トークンは、DriverとそのExecutorによって共有されるSecretsに格納されます。そのため、Kerberosジョブを送信するには3つの方法があります。
いずれの場合も、環境変数HADOOP_CONF_DIR
またはspark.kubernetes.hadoop.configMapName
を定義する必要があります。
また、KDCはコンテナ内から見える必要があることに注意することも重要です。
ユーザーがHadoop構成ファイルを含むリモートのHADOOP_CONFディレクトリを使用する場合、spark.kubernetes.hadoop.configMapName
を既存のConfigMapに設定することで実現できます。
- ローカルチケットキャッシュにTGTを格納する$kinitを使用して送信する
/usr/bin/kinit -kt <keytab_file> <username>/<krb5 realm> /opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION>
- ローカルキータブとプリンシパルを使用して送信する
/opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kerberos.keytab=<KEYTAB_FILE> \ --conf spark.kerberos.principal=<PRINCIPAL> \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION>
- 名前空間内にすでに存在する委任トークンを含む、事前に設定されたシークレットを使用して送信する
/opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kubernetes.kerberos.tokenSecret.name=<SECRET_TOKEN_NAME> \ --conf spark.kubernetes.kerberos.tokenSecret.itemKey=<SECRET_ITEM_KEY> \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION>
3b. (3)のように送信しますが、事前に作成されたkrb5 ConfigMapと事前に作成されたHADOOP_CONF_DIR
ConfigMapを指定します
/opt/spark/bin/spark-submit \
--deploy-mode cluster \
--class org.apache.spark.examples.HdfsTest \
--master k8s://<KUBERNETES_MASTER_ENDPOINT> \
--conf spark.executor.instances=1 \
--conf spark.app.name=spark-hdfs \
--conf spark.kubernetes.container.image=spark:latest \
--conf spark.kubernetes.kerberos.tokenSecret.name=<SECRET_TOKEN_NAME> \
--conf spark.kubernetes.kerberos.tokenSecret.itemKey=<SECRET_ITEM_KEY> \
--conf spark.kubernetes.hadoop.configMapName=<HCONF_CONFIG_MAP_NAME> \
--conf spark.kubernetes.kerberos.krb5.configMapName=<KRB_CONFIG_MAP_NAME> \
local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \
<HDFS_FILE_LOCATION>
イベントロギング
アプリケーションでイベントロギングを使用している場合、イベントログが保存されるディレクトリ(spark.eventLog.dir
)は、適切な権限で手動で作成する必要があります。ログファイルを保護するには、ディレクトリの権限をdrwxrwxrwxt
に設定する必要があります。ディレクトリの所有者とグループは、Spark History Serverを実行しているスーパーユーザーに対応している必要があります。
これにより、すべてのユーザーがディレクトリに書き込むことができますが、権限のないユーザーがファイルを読み取ったり、削除したり、名前を変更したりすることを防ぎます(所有者である場合を除く)。イベントログファイルは、ユーザーとグループのみが読み取りおよび書き込みアクセス権を持つように、Sparkによって作成されます。
クライアントモードでのドライバログの永続化
アプリケーションがspark.driver.log.persistToDfs.enabled
を有効にしてクライアントモードでドライバログを永続化する場合、ドライバログが保存されるディレクトリ(spark.driver.log.dfsDir
)は、適切な権限で手動で作成する必要があります。ログファイルを保護するには、ディレクトリの権限をdrwxrwxrwxt
に設定する必要があります。ディレクトリの所有者とグループは、Spark History Serverを実行しているスーパーユーザーに対応している必要があります。
これにより、すべてのユーザーがディレクトリに書き込むことができますが、権限のないユーザーがファイルを読み取ったり、削除したり、名前を変更したりすることを防ぎます(所有者である場合を除く)。ドライバログファイルは、ユーザーとグループのみが読み取りおよび書き込みアクセス権を持つように、Sparkによって作成されます。