金融データ分析基盤の構築 - Hadoop(3)

前回:


今回やること

  1. Hadoopクラスタ用プリンシパルの作成

  2. HadoopクラスタのKerberos連携

  3. 各ノードのKerberos設定

  4. Hadoopクラスタの確認

1. Hadoopクラスタ用プリンシパルの作成

まずは、Hadoopクラスタの各ノードが使うためのプリンシパルを作成する。Kerberos認証を用いる場合はクラスタのノード間でも認証が必要となるため、ユーザではなくサービスのプリンシパルをいくつか作ることになる。

基本的には以下のドキュメント通りにプリンシパルを作る。

一部引用してくると、NameNode用のプリンシパルはこんな感じ。

$ klist -e -k -t /etc/security/keytab/nn.service.keytab
Keytab name: FILE:/etc/security/keytab/nn.service.keytab
KVNO Timestamp         Principal
   4 07/18/11 21:08:09 nn/full.qualified.domain.name@REALM.TLD (AES-256 CTS mode with 96-bit SHA-1 HMAC)
   4 07/18/11 21:08:09 nn/full.qualified.domain.name@REALM.TLD (AES-128 CTS mode with 96-bit SHA-1 HMAC)
   4 07/18/11 21:08:09 nn/full.qualified.domain.name@REALM.TLD (ArcFour with HMAC/md5)
   4 07/18/11 21:08:09 host/full.qualified.domain.name@REALM.TLD (AES-256 CTS mode with 96-bit SHA-1 HMAC)
   4 07/18/11 21:08:09 host/full.qualified.domain.name@REALM.TLD (AES-128 CTS mode with 96-bit SHA-1 HMAC)
   4 07/18/11 21:08:09 host/full.qualified.domain.name@REALM.TLD (ArcFour with HMAC/md5)

手順は、以下のコマンドでKerberosの管理サーバに対してリクエストを送る。

$ kadmin.local
$ addprinc -randkey nn/<FQDN>@REALM
$ addprinc -randkey host/<FQDN>@REALM
$ ktadd -e aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96,rc4-hmac:normal -k /etc/security/keytabs/nn.keytab nn/<FQDN>@REALM

上記で生成したKeytabファイルはパスワードなしでログイン可能なように認証情報が含まれている。これらを適切な所有者・グループ・権限にして、各ノードに配置する。(上記はNameNodeのみだが、Secondary NameNode、DataNodeに対しても行う。)

2. HadoopクラスタのKerberos連携

Hadoopクラスタ用のプリンシパルは作れたので、それらのプリンシパルを使って認証するようにKerberosの設定をする。設定は、各ノードの以下のファイルを編集する。

  • core-site.xml

  • hdfs-site.xml

  • ssl-server.xml(HTTPS必須だったためとりあえず設定)

# core-site.xml

<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://hadoop-namenode1.home:9000</value>
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/hadoop/tmp</value>
  </property>
  <property>
    <name>hadoop.rpc.protection</name>
    <value>authentication</value>
  </property>
  <property>
    <name>hadoop.security.authentication</name>
    <value>kerberos</value>
  </property>
  <property>
    <name>hadoop.security.authorization</name>
    <value>true</value>
  </property>
  <property>
    <name>hadoop.security.auth_to_local</name>
    <value>
      RULE:[2:$1/$2@$0]([ndj]n/.*@HOME)s/.*/hdfs/
      RULE:[2:$1/$2@$0]([rn]m/.*@HOME)s/.*/yarn/
      RULE:[2:$1/$2@$0](jhs/.*@HOME)s/.*/mapred/
      DEFAULT
    </value>
  </property>
</configuration>
# hdfs-site.xml (NameNodeのもの)

<configuration>
  <property>
    <name>dfs.block.access.token.enable</name>
    <value>true</value>
  </property>
  <property>
    <name>dfs.namenode.kerberos.principal</name>
    <value>nn/_HOST@HOME</value>
  </property>
  <property>
    <name>dfs.namenode.keytab.file</name>
    <value>/etc/security/keytab/nn.service.keytab</value>
  </property>
  <property>
    <name>dfs.namenode.kerberos.internal.spnego.principal</name>
    <value>HTTP/_HOST@HOME</value>
  </property>
  <property>
    <name>dfs.web.authentication.kerberos.keytab</name>
    <value>/etc/security/keytab/spnego.service.keytab</value>
  </property>
  <property>
    <name>dfs.http.policy</name>
    <value>HTTPS_ONLY</value>
  </property>
  <property>
    <name>dfs.data.transfer.protection</name>
    <value>authentication</value>
  </property>
</configuration>
# ssl-server.xml

<configuration>
<property>
  <name>ssl.server.truststore.location</name>
  <value>/etc/ssl/hadoop/mykeystore.jks</value>
</property>
<property>
  <name>ssl.server.truststore.password</name>
  <value>storepassword</value>
</property>
<property>
  <name>ssl.server.truststore.type</name>
  <value>jks</value>
</property>
<property>
  <name>ssl.server.truststore.reload.interval</name>
  <value>10000</value>
</property>
<property>
  <name>ssl.server.keystore.location</name>
  <value>/etc/ssl/hadoop/mykeystore.jks</value>
</property>
<property>
  <name>ssl.server.keystore.password</name>
  <value>storepassword</value>
</property>
<property>
  <name>ssl.server.keystore.keypassword</name>
  <value>keypassword</value>
</property>
<property>
  <name>ssl.server.keystore.type</name>
  <value>jks</value>
</property>
<property>
  <name>ssl.server.exclude.cipher.list</name>
  <value>TLS_ECDHE_RSA_WITH_RC4_128_SHA,SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
  SSL_RSA_WITH_DES_CBC_SHA,SSL_DHE_RSA_WITH_DES_CBC_SHA,
  SSL_RSA_EXPORT_WITH_RC4_40_MD5,SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
  SSL_RSA_WITH_RC4_128_MD5</value>
</property>
</configuration>

設定はドキュメントのセキュリティのページに書いてあるのだが、ドキュメントだけではちょっとよくわからない部分もあった。そこで色々試行錯誤していて時間がかかってしまった。

dfs.block.access.token.enableについて

ドキュメントには、NameNodeの設定のほうにdfs.block.access.token.enableをtrueにするようにと書いてあるが、これはDataNodeの設定にも必要となっていた。

これをDataNodeで有効にしておかないと、「セキュリティの設定されてるのに、Block Access Tokenが有効になってないよ」というようなエラーが出てしまう。

HTTPS_ONLYとその他の設定

ドキュメントには、DataNodeのセキュリティについて以下のように書かれている。

As of version 2.6.0, SASL can be used to authenticate the data transfer protocol. In this configuration, it is no longer required for secured clusters to start the DataNode as root using jsvc and bind to privileged ports. To enable SASL on data transfer protocol, set dfs.data.transfer.protection in hdfs-site.xml. A SASL enabled DataNode can be started in secure mode in following two ways: 1. Set a non-privileged port for dfs.datanode.address. 1. Set dfs.http.policy to HTTPS_ONLY or set dfs.datanode.http.address to a privileged port and make sure the HDFS_DATANODE_SECURE_USER and JSVC_HOME environment variables are specified properly as environment variables on start up (in hadoop-env.sh).

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SecureMode.html

Hadoopのバージョン2.6.0以降ではSASLを利用できるらしく、その利用方法としては非特権ポートの設定をし、HTTPではなくHTTPS通信のみを利用するように設定する必要がある。

そうしないと、ソースの以下の部分で例外が投げられてしまうようになっている(Incorrect config的な感じの)

HTTPS通信のみにすると当然だがサーバ側のSSL設定をしなくてはいけなくなる。なので、とりあえず自己証明書を適当に作って設定のみしてある。

3. 各ノードのKerberos設定

あと、Hadoopクラスタの各ノードのKerberos設定が必要になってくる。KDCサーバをLAN内に立てているが、そもそも各ノードのクライアントに適切なレルムの設定(特にデフォルトレルム)をしないとうまく認証ができなかった。

各ノードには以下のような感じで、デフォルトレルムを設定しておかないと、Hadoop内でTGS要求を行ったりする際にうまくできなかったりしていたっぽい(ログを見る限り)。

[libdefaults]
        default_realm = HOME
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true
        rdns = false
        fcc-mit-ticketflags = true

[realms]
        HOME = {
                kdc = kdc.home
                admin_server = kdc.home
        }

4. Hadoopクラスタの確認

それらの設定をしてNameNodeでsbin/start-dfs.shを実行する。その後まずログを確認してサーバがエラーなどでシャットダウンしてないかをみて、特に問題なさそうだったらNameNodeの指定したポートにHTTPSでアクセスすると管理画面が見える。

Live Nodesが1となっているので、DataNodeが一つ正常に接続できていることがわかる。また、CapacityもDataNodeのストレージひとつ分の容量があることが確認できた。

ぼやき

認証周りで結構時間かかって、とりあえず動いた感じだけど、ちゃんと理解できているかは少し怪しい。次の記事でYARNなどに行く前にHadoopの認証を図解したりより詳しく理解するための内容を書こうかな。

特に、SASLやSPNEGOあたりや、認証の具体的な手順などについて知りたい。あと、それらに問題が合った時の調べたかなど。

次やること

  1. 認証のより詳しい理解

  2. YARNのセットアップ

  3. MapRecudeのセットアップ

  4. HDFS、YARN、MapRecudeの設定を詳しく理解する

この記事が気に入ったらサポートをしてみませんか?