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 Submission サーバと MesosClusterDispatcher は認証をサポートしません。REST API & MesosClusterDispatcher (デフォルトではそれぞれポート 6066 および 7077) への全てのネットワークアクセスが、ジョブの送信が信頼されているホストに制限されていることを確認する必要があります。
YARN
YARN上のSparkのために、Sparkは共有秘密鍵の生成と配布を自動的に処理します。各アプリケーションはユニークな共有鍵を使うでしょう。YARNの場合、この機能は秘密鍵を安全に配布するために有効にされるYARN RJPC暗号化に依存します。
Kubernetes
Kubernetes では、Spark は各アプリケーションに固有の認証秘密鍵も自動的に生成します。秘密鍵は環境変数を使って executor pod に伝播されます。つまり、Spark アプリケーションが実行されている名前空間で pod を一覧表示できる全てのユーザは、それらの認証秘密鍵も表示することもできます。Spark 認証が安全であることを保障するために、Kubernetes 管理者はアクセス制御ルールを適切に設定する必要があります。
プロパティ名 | デフォルト | 意味 | これ以降のバージョンから |
---|---|---|---|
spark.authenticate |
false | Sparkが内部接続を認証するかどうか。 | 1.0.0 |
spark.authenticate.secret |
None | 認証に使われる秘密鍵。この設定が設定される時については、上記を見てください。 | 1.0.0 |
または、ユーザが pod にマウントするファイルと Kubernetes 秘密鍵を使って、認証秘密鍵をマウントすることができます。
プロパティ名 | デフォルト | 意味 | これ以降のバージョンから |
---|---|---|---|
spark.authenticate.secret.file |
None | 接続の保護に使用する秘密鍵を指すパス。ファイルの内容が安全に生成されるようにしてください。このファイルは、他の設定で上書き(以下を参照)されない限りドライバと executor の両方で読み込まれます。 | 3.0.0 |
spark.authenticate.secret.driver.file |
spark.authenticate.secret.file の値。 |
指定された場合、Spark ドライバが秘密鍵を読み込む場所を上書きします。クライアントモードで、秘密鍵ファイルの場所が pod とドライバーが実行されているノードで異なる場合に、便利です。これが指定された場合、spark.authenticate.secret.executor.file はドライバと executor が両方ともファイルを指定して秘密鍵を読み込むようにする必要があります。ドライバ上のファイルの内容が、executor のファイルの内容と同じであるようにしてください。
|
3.0.0 |
spark.authenticate.secret.executor.file |
spark.authenticate.secret.file の値。 |
指定された場合、Spark executor が秘密鍵をロードするために読み込む場所を上書きします。クライアントモードで、秘密鍵ファイルの場所が pod とドライバーが実行されているノードで異なる場合に、便利です。これが指定された場合、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.keyLength |
128 | 生成する暗号化キーのビット単位の長さ。有効な値は 128, 192 および 256 です。 | 2.2.0 |
spark.network.crypto.keyFactoryAlgorithm |
PBKDF2WithHmacSHA1 | 暗号化キーを生成する時に使用する キー ファクトリー アルゴリズム。使用されるJREでの javax.crypto.SecretKeyFactory クラスでサポートされるアルゴリズムのうちの一つでなければなりません。 | 2.2.0 |
spark.network.crypto.config.* |
None |
どのcipher実装を使うかなどの共通暗号化ライブラリのための設定値。設定名は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 Cryptography Architecture Standard Algorithm Name ドキュメントのKeyGeneratorの章で説明されます。 | 2.1.0 |
spark.io.encryption.commons.config.* |
None |
どのcipher実装を使うかなどの共通暗号化ライブラリのための設定値。設定名はcommons.crypto プリフィックス無しのcommons-crypto設定の名前にする必要があります。
|
2.1.0 |
Web UI
認証と権限
Web UIのための認証を有効にするには、javax servlet filtersを使用します。配備したい認証方法を実装するフィルタが必要です。Spark jは組み込みの認証フィルタを提供しません。
Spark は認証フィルタが存在する場合のUIへのアクセス制御もサポートします。各アプリケーションは独自の個別のアクセス制限リスト (ACL)を使って設定することができます。 Sparkは “view” 権限 (誰がアプリケーションのUIを見ることができるか) と “modify” 権限 (誰が実行中のアプリケーションでジョブを強制終了できるか) を区別します。
ACL はユーザあるいはグループのいずれかに設定できます。設定エントリは入力としてカンマ区切りのリストを受け付けます。つまり複数のユーザあるいはグループに必要な権限を付与できます。 これは、共有クラスタ上で実行し、自分で起動していないアプリケーションを監視する必要がある管理者あるいは開発者のセットがある場合に使うことができます。特定のACLに追加されたワイルドカード (*
) は、全てのユーザがそれぞれの権限を持つことを意味します。デフォルトでは、アプリケーションを送信するユーザだけがACLに追加されます。
グループメンバーシップは設定可能なグループマッピング プロバイダを使って確立されます。マッパーは以下の表で説明されるspark.user.groups.mapping
設定オプションを使って設定されます。
以下のオプションはWeb UIの認証を制御します:
プロパティ名 | デフォルト | 意味 | これ以降のバージョンから |
---|---|---|---|
spark.ui.filters |
None | フィルターをどのように設定するかについては、Spark UI 設定を見てください。 | 1.0.0 |
spark.acls.enable |
false | UIのACLを有効にするかどうか。有効な場合、これはユーザがアプリケーションを表示あるいは変更するためのアクセス権限を持っているかどうかを確認します。これにはユーザが認証される必要があるため、もし認証フィルターがインストールされていない場合、このオプションは何もしません。 | 1.1.0 |
spark.admin.acls |
None | Sparkアプリケーションへの表示と変更のアクセスを持つユーザのカンマ区切りのリスト。 | 1.1.0 |
spark.admin.acls.groups |
None | Sparkアプリケーションへの表示と変更のアクセスを持つグループのカンマ区切りのリスト。 | 2.0.0 |
spark.modify.acls |
None | Sparkアプリケーションへの変更のアクセスを持つユーザのカンマ区切りのリスト。 | 1.1.0 |
spark.modify.acls.groups |
None | Sparkアプリケーションへの変更のアクセスを持つグループのカンマ区切りのリスト。 | 2.0.0 |
spark.ui.view.acls |
None | Sparkアプリケーションへの表示のアクセスを持つユーザのカンマ区切りのリスト。 | 1.0.0 |
spark.ui.view.acls.groups |
None | Sparkアプリケーションへの表示のアクセスを持つグループのカンマ区切りのリスト。 | 2.0.0 |
spark.user.groups.mapping |
org.apache.spark.security.ShellBasedGroupsMappingProvider |
ユーザのためのグループのリストは、プロパティによって設定することができる org.apache.spark.security.GroupMappingServiceProvider によって定義されるグループマッピングサービスによって決定されます。デフォルトで、ホストOSからこの情報を集めるUnixシェルベースの実装が使われます。 注意: この実装は Unix/Linuxベースの環境のみサポートします。Windows環境は現在のところサポートされません。ただし、上記の特性を実装することにより、新しいプラットフォームをサポートできます。 |
2.0.0 |
YARN上では、表示と変更ACLはアプリケーションを送信した時にYARNサービスに提供され、YARNインタフェースを介してそれぞれの権限を持つユーザを制御します。
Spark履歴サーバのACLs
SHS Web UIのための認証は、servletフィルタを使って通常のアプリケーションと同じ方法で有効にされます。
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 |
None | 履歴サーバ内で全てのSparkアプリケーションへのviewアクセスを持つユーザのカンマ区切りのリスト。 | 2.1.1 |
spark.history.ui.admin.acls.groups |
None | 履歴サーバ内で全てのSparkアプリケーションへのviewアクセスを持つグループのカンマ区切りのリスト。 | 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}
のプレースホルダーは上記の名前空間のうちの1つで置き換えられなければなりません。
プロパティ名 | デフォルト | 意味 |
---|---|---|
${ns}.enabled |
false | SSLを有効にします。有効にする場合、${ns}.ssl.protocol が必要です。 |
${ns}.port |
None |
SSLサービスがlistenするポート。 ポートは特定の名前空間設定内で定義されなければなりません。デフォルトの名前空間はこの設定を読む時に無視されます。 設定しない場合は、SSLポートは同じサービスの非SSLポートから取得されるでしょう。"0" の値はサービスを短命ポートに結びつけるでしょう。 |
${ns}.enabledAlgorithms |
None |
cipherのカンマ区切りのリスト。指定されたcipherはJVMによってサポートされなければなりません。 プロトコルのリファレンスのリストはJavaセキュリティガイドの "JSSE Cipher Suite Names" の章で見つけることができます。Java 8 のリストはこのページで見つけることができます。 注意: 設定しない場合、JREのためのデフォルトのcipherスイートが使われます。 |
${ns}.keyPassword |
None | キーストア内の秘密鍵へのパスワード。 |
${ns}.keyStore |
None | キーストア ファイルへのパス。パスはプロセスが開始されたディレクトリへの絶対あるいは相対パスです。 |
${ns}.keyStorePassword |
None | Password to the key store. |
${ns}.keyStoreType |
JKS | キーストアの種類。 |
${ns}.protocol |
None |
使用するプロトコル。プロトコルはJVMによってサポートされなければなりません。 プロトコルのリファレンスのリストはJavaセキュリティガイドの "Additional JSSE Standard Names" の章で見つけることができます。Java 8 については、リストをこのページで見つけることができます。 |
${ns}.needClientAuth |
false | クライアント認証を必要とするかどうか。 |
${ns}.trustStore |
None | 信頼ストア ファイルへのパス。パスはプロセスが開始されたディレクトリへの絶対あるいは相対パスです。 |
${ns}.trustStorePassword |
None | 信頼ストアのためのパスワード。 |
${ns}.trustStoreType |
JKS | 信頼ストアの種類。 |
Spark はHadoop 資格プロバイダから${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 スタンドアローン配備モードのためのキーストアとtrustストアを設定する最も基本的なステップは以下の通りです:
- 各ノードのためにキーを生成します
- キーのペアの公開鍵を各ノード上のファイルにエクスポートします
- 全てのエクスポートされた公開鍵を1つのtrustストアにインポートします
- trustストアをクラスタノードに分配します
YARN モード
クラスタモードで実行中のドライバにローカルクラスタストアあるいはキーストアを提供するために、--files
コマンドライン引数 (あるいは 同等のspark.files
設定)を使ってアプリケーションと共に配布できます。ファイルはドライバの作業ディレクトリに配置されるため、TLS設定は絶対パスではなくファイル名のみを参照する必要があります。
この方法でローカルキーストアを配布するには、ファイルをHDFS (あるいはクラスタで使用される他の似た分散ファイルシステム)に置く必要があるかもしれません。そのため基礎となるファイルシステムはセキュリティを考慮して設定することをお勧めします (例えば、認証とwire暗号化を有効にする)。
スタンドアローンモード
ユーザがマスターとワーカーのためにキーストアと設定オプションを提供する必要があります。それらはSPARK_MASTER_OPTS
と SPARK_WORKER_OPTS
環境変数内、あるいは単にSPARK_DAEMON_JAVA_OPTS
の中で、適切なJavaシステムプロパティを加えることで設定されなければなりません。
ユーザはexecutorにワーカープロセスから継承した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は Cross Site Scripting (XSS), Cross-Frame Scripting (XFS), MIME-Sniffing を避けるのに役立ち、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 |
None |
HTTP Strict Transport Security (HSTS) 応答ヘッダのための値。以下から適切な値を選択し、それに応じてexpire-time を設定することができます。このオプションは SSL/TLS が有効な場合のみ使用されます。
|
2.3.0 |
ネットワークセキュリティのためのポートの設定
一般的に言って、Spark クラスタとそのサービスは公的なインターネットに配備されません。それらは一般的にプライベートなサービスで、Sparkを配備する組織のネットワーク内でのみアクセス可能な筈です。Sparkサービスによって使われるホストとポートへのアクセスはサービスへアクセスする必要があるオリジンのホストに制限されるべきです。
以下はSparkが通信のために使用する主なポートと、それらのポートの設定方法です。
スタンドアローンモードのみ
From | To | デフォルトのポート | 目的 | 設定 | 備考 |
---|---|---|---|---|---|
ブラウザ | スタンドアローンマスター | 8080 | Web UI | spark.master.ui.port / |
Jetty-based. スタンドアローンモードのみ。 |
ブラウザ | スタンドアローン ワーカー | 8081 | Web UI | spark.worker.ui.port / |
Jetty-based. スタンドアローンモードのみ。 |
Driver / スタンドアローン ワーカー |
スタンドアローンマスター | 7077 | クラスタへのジョブのサブミット / Join cluster |
SPARK_MASTER_PORT |
ポートをランダムに選択するには"0"を設定します。スタンドアローンモードのみ。 |
External Service | スタンドアローンマスター | 6066 | REST APIを使ってジョブをクラスタに提出します | spark.master.rest.port |
このサービスを有効/無効にするには、spark.master.rest.enabled を使います。スタンドアローンモードのみ。 |
スタンドアローンマスター | スタンドアローン ワーカー | (random) | スケジュール executor | SPARK_WORKER_PORT |
ポートをランダムに選択するには"0"を設定します。スタンドアローンモードのみ。 |
全てのクラスタマネージャー
From | To | デフォルトのポート | 目的 | 設定 | 備考 |
---|---|---|---|---|---|
ブラウザ | アプリケーション | 4040 | Web UI | spark.ui.port |
Jetty-based |
ブラウザ | ヒストリーサーバ | 18080 | Web UI | spark.history.ui.port |
Jetty-based |
Executor / スタンドアローンマスター |
Driver | (random) | アプリケーションへの接続 / executor の状態の変更を通知 |
spark.driver.port |
ポートをランダムに選択するには"0"を設定します。 |
Executor / Driver | Executor / Driver | (random) | ブロックマネージャー ポート | spark.blockManager.port |
ServerSocketChannelを使ったrawソケット |
Kerberos
Sparkは認証のためにKerberosを使う環境でのアプリケーションの提出をサポートします。ほとんどの場合、Sparkは、Kerberos対応サービスの認証時に現在ログインしているユーザの資格情報に依存します。そのような資格情報は設定されたKDCにkinit
のようなツールを使ってログインすることで取得できます。
Hadoopベースのサービスと通信する場合、Sparkは非ローカルプロセスが認証できるように移譲トークンを取得する必要があります。SparkにはHDFSと他のHadoopシステム、HiveとHBaseのためのサポートが付属しています。
(DFS あるいは WebHDFSのような)Hadoopファイルシステムを使う場合、Sparkはユーザのホームディレクトリをホストするサービスのための関連トークンを取得します。
HBaseがアプリケーションのクラスパスにあり、HBase構成でKerberos認証が有効になっている場合 (hbase.security.authentication=kerberos
)、HBaseトークンが取得されます。
同様に、Hive がクラスタパスにあり、構成にリモートのメタストア サービスのURIが含まれる場合 (hive.metastore.uris
が空では無い)、Hiveトークンが取得されます。
もしアプリケーションが他の安全なHadoopファイルシステムとやり取りをする必要がある場合、それらのURIは起動時に明示的にSparkに提供される必要があります。spark.kerberos.access.hadoopFileSystems
プロパティの中でそれらをリスト化することで行われます。以下の設定の章で説明されます。
Spark はJavaサービスの仕組みを使った独自の移譲トークン プロバイダもサポートします (java.util.ServiceLoader
を見てください)。jarのMETA-INF/services
ディレクトリ内の対応するファイルの中でそれらの名前をリスト化することで、Sparkでorg.apache.spark.security.HadoopDelegationTokenProvider
の実装を利用可能にすることができます。
移譲トークンのサポートは現在のところYARNとMesosモードでのみサポートされます。詳細は配備固有のページを参照してください。
以下のオプションはこの機能のきめ細やかな制御を提供します:
プロパティ名 | デフォルト | 意味 | これ以降のバージョンから |
---|---|---|---|
spark.security.credentials.${service}.enabled |
true |
セキュリティが有効な場合に、サービスのための証明書を取得するかどうかを制御します。デフォルトではサービスが設定されている場合に全てのサポートされるサービスのための証明書が取り出されるようにしますが、アプリケーションが実行されるのに何かしらの衝突がある場合はその挙動を無効にすることができます。 | 2.3.0 |
spark.kerberos.access.hadoopFileSystems |
(none) |
Sparkアプリケーションがアクセスしようとするカンマ区切りのsecureなHadoopファイルファイルシステムのリスト。例えば、spark.kerberos.access.hadoopFileSystems=hdfs://nn1.com:8032,hdfs://nn2.com:8032, webhdfs://nn3.com:50070 。Sparkアプリケーションはリストされているファイルシステムへアクセスできなければならず、Kerberosはそれらにアクセスできるように適切に設定されていなければなりません(同じrealmあるいは信頼されたrealmのどちらか)。SparkアプリケーションがそれらのリモートのHadoopファイルシステムにアクセスできるように、Sparkは各ファイルシステムのためのセキュリティトークンを取得します。
|
3.0.0 |
ユーザは、リソーススケジューラでKerberos委任トークンの更新を除外できます。現在のところ、YARNでのみサポートされます。設定については、YARN上でSparkの実行ページで説明されます。
長時間実行中のアプリケーション
長時間実行中のアプリケーションは、実行時間がアクセスする必要のあるサービスで設定された移譲トークンの最大生存時間を超えた場合、問題が発生するかもしれません。
この機能はどこでも利用できるわけではありません。特に、YARN と Kubernetes (クライアントモードとクラスタモードの両方)、およびクライアントモードを使う場合は Mesos にのみ、実装されます。
Spark はこれらのアプリケーションのための新しいトークンの自動作成をサポートします。この機能を有効にする方法は2つあります。
キータブの使用
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 のこれらの移譲トークンは、ドライバとその executor によって共有される秘密鍵に格納されます。そのため、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履歴サーバを実行するスーパーユーザに対応する必要があります。
これにより、全てのユーザはディレクトリに書き込むことができますが、権限のないユーザはファイルを所有していない限り、ファイルの読み込み、削除あるいは名前の変更をできません。イベントログファイルはSparkによってユーザおよびグループのみが読み書きアクセスを持つパーミッションで生成されるでしょう。
クライアントモードでの永続化ドライバログ
spark.driver.log.persistToDfs.enabled
を有効にすることでアプリケーションがクライアントモードでドライバログを永続化する場合は、ドライバログが保存されるディレクトリ (spark.driver.log.dfsDir
) は適切な権限で手動で作成する必要があります。ログファイルを保護するために、ディレクトリのパーミッションは drwxrwxrwxt
に設定されなければなりません。ディレクトリの所有者とグループはSpark履歴サーバを実行するスーパーユーザに対応する必要があります。
これにより、全てのユーザはディレクトリに書き込むことができますが、権限のないユーザはファイルを所有していない限り、ファイルの読み込み、削除あるいは名前の変更をできません。ドライバログファイルはSparkによってユーザおよびグループのみが読み書きアクセスを持つパーミッションで生成されるでしょう。