Spark セキュリティ

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ストアを設定する最も基本的なステップは以下の通りです:

YARN モード

クラスタモードで実行中のドライバにローカルクラスタストアあるいはキーストアを提供するために、--files コマンドライン引数 (あるいは 同等のspark.files 設定)を使ってアプリケーションと共に配布できます。ファイルはドライバの作業ディレクトリに配置されるため、TLS設定は絶対パスではなくファイル名のみを参照する必要があります。

この方法でローカルキーストアを配布するには、ファイルをHDFS (あるいはクラスタで使用される他の似た分散ファイルシステム)に置く必要があるかもしれません。そのため基礎となるファイルシステムはセキュリティを考慮して設定することをお勧めします (例えば、認証とwire暗号化を有効にする)。

スタンドアローンモード

ユーザがマスターとワーカーのためにキーストアと設定オプションを提供する必要があります。それらはSPARK_MASTER_OPTSSPARK_WORKER_OPTS 環境変数内、あるいは単にSPARK_DAEMON_JAVA_OPTSの中で、適切なJavaシステムプロパティを加えることで設定されなければなりません。

ユーザはexecutorにワーカープロセスから継承したSSL設定を使えるようにするかも知れません。これはspark.ssl.useNodeLocalConftrue に設定することで実現できます。この場合、クライアント側でユーザによって提供された設定は使われません。

Mesos モード

Mesos 1.3.0 以上はファイルベースおよび環境ベースの両方の秘密鍵としてSecrets プリミティブをサポートします。Sparkはそれぞれspark.mesos.driver.secret.filenamesspark.mesos.driver.secret.envkeys を使ってファイルベースと環境変数ベースの秘密鍵の使用を許可します。

秘密ストアに応じて、バックエンドの秘密鍵はそれぞれspark.mesos.driver.secret.namesspark.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 応答ヘッダのための値。以下から適切な値を選択することができます:
  • 0 (XSSフィルタリングを無効にします)
  • 1 (XSS フィルタリングを有効にします。もし cross-site scripting アタックが検知されると、ブラウザはページをサニタイズするでしょう。)
  • 1; mode=block (XSS フィルタリングを有効にします。もし攻撃が検知されるとブラウザはページのレンダリングを避けるでしょう。)
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 が有効な場合のみ使用されます。
  • max-age=<expire-time>
  • max-age=<expire-time>; includeSubDomains
  • max-age=<expire-time>; preload
2.3.0

ネットワークセキュリティのためのポートの設定

一般的に言って、Spark クラスタとそのサービスは公的なインターネットに配備されません。それらは一般的にプライベートなサービスで、Sparkを配備する組織のネットワーク内でのみアクセス可能な筈です。Sparkサービスによって使われるホストとポートへのアクセスはサービスへアクセスする必要があるオリジンのホストに制限されるべきです。

以下はSparkが通信のために使用する主なポートと、それらのポートの設定方法です。

スタンドアローンモードのみ

FromToデフォルトのポート目的設定備考
ブラウザ スタンドアローンマスター 8080 Web UI spark.master.ui.port /
SPARK_MASTER_WEBUI_PORT
Jetty-based. スタンドアローンモードのみ。
ブラウザ スタンドアローン ワーカー 8081 Web UI spark.worker.ui.port /
SPARK_WORKER_WEBUI_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"を設定します。スタンドアローンモードのみ。

全てのクラスタマネージャー

FromToデフォルトのポート目的設定備考
ブラウザ アプリケーション 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.credentialsccache に設定することで、ローカル 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 に設定することで、これを実現できます。

  1. 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>
    
  2. ローカルキータブとプリンシパルを送信
    /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>
    
  3. 名前空間にすでに存在する移譲トークンを含む、事前に設定された秘密鍵を使って送信する
    /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によってユーザおよびグループのみが読み書きアクセスを持つパーミッションで生成されるでしょう。

TOP
inserted by FC2 system