EMRでHiveメタストアにRDSを利用する

hadoop-logo

こんにちは、小澤です。

今回はEMRとHiveのメタストアとRDSに関するお話です。

EMRとHadoop

EMRを利用するときには、必要になったらクラスタを起動して、使い終わったら終了させるという使い方をされる方が多いかと思います。 その際、HDFSのデータは消えてしまいますが、S3などに保存しておけば失われることはありません。 これによって、データを保存するストレージとジョブの実行を行うコンピューティングリソースの分離が実現できます。

必要な時に必要なだけのリソースを必要な人が確保して使える、まさにクラウドを活用している感じに溢れています。

ところで、Hadoopでよく利用されるエコシステムの1つにHiveがあります。 Hiveではテーブル定義などをHadoop本体とは別にRDB(最近ではHBaseも選択可)に保持するメタストアがあります。 EMRではデフォルトでマスタノードにこのメタストアが設置されることになります。

EMRはクラスタを終了させるとマスタノードも含めて全てのインスタンスが削除されるため、この時にメタストアにあるテーブル定義情報も一緒に失われてしまうことになります。 クラスタを起動するたびに毎回テーブルやパーティションの作成を行っていると非常に効率が悪いですね。 そこで、EMRとは別にRDSを立てておき、メタストアはそちらを使うということができます。

metastore

外部RDSとの繋ぎこみ

RDSの起動

この設定を行うのは非常に簡単です。 まず、従来通りRDSを立ち上げてください。メタストアで利用するのは普通のRDBなので、MySQLなどでOKです。

データベースの設定での「データベース名」は指定しなくても問題ありません。 EMR起動時にデータベースがなければ作成する指定ができます。

EMRの起動

次にEMRを起動します。ここでは管理コンソール上で詳細オプションを利用している前提とします。 クイックオプションの場合項目が異なっている可能性があるので注意してください。

「ソフトウェア設定の編集(省略可能)」にメタストアとして利用するRDSに関する情報を記載します。 以下はJSON形式での指定です

[
    {
      "Classification": "hive-site",
      "Properties": {
        "javax.jdo.option.ConnectionURL": "jdbc:mysql://<RDSのエンドポイント>:3306/<データベース名>?createDatabaseIfNotExist=true",
        "javax.jdo.option.ConnectionUserName": "<RDSのユーザ>",
        "javax.jdo.option.ConnectionPassword": "<RDSユーザのパスワード>"
      }
    }
  ]

「createDatabaseIfNotExist=true」でデータベースが存在していない場合作成する指定をしています。 データベース名は「hive」や「metastore」などとしておくと、何で利用しているかがわかりやすいでしょう。

これで指定したRDSをメタストアに利用してEMRを立ち上げることができます。

RDSのユーザについて

さて、RDSのユーザについてですがマスタユーザを利用したくない場合にちょっとしたハマリどころがあります。 メタストアは通常、どのようなテーブル定義がされているかなどはHiveユーザが気にすることは無いのですが、上記の設定で初回起動した際には内部ではテーブルが作成されています。

Hadoopの環境構築を行ったことがある場合ご存知の方もいるかと思いますが、 環境によっては

  • RDBのユーザ作成
  • データベース作成
  • スキーマ作成が記載されたSQLファイルの実行
  • ユーザに権限を与える

といった作業を先に行っておく必要があります。 EMRでRDSのマスタユーザを接続に利用する場合は全てやってくれるのですが、別なユーザを作成する場合はテーブル作成などの権限が無いことによってクラスタの起動が失敗します。

手軽な方法としては、

  • とりあえずマスタユーザで接続するEMRクラスタを起動することでメタストアの構築まで完了させる
  • RDSでユーザ作成や作成されたデータベース、テーブルへの権限を追加
  • クラスタを終了させ、次回起動時からは作成したユーザで接続

とするのが楽かと思います。 「既存のRDSに同居させる予定だけど、そんな権限持ってない!」という場合でも、「スキーマ作成が記載されたSQLファイルの実行」で利用するSQLファイルをマスタノードにSSHで接続して、

/usr/lib/hive/scripts/metastore/upgrade/mysql/hive-schema-<hiveのバージョン>.mysql.sql

から取得することになるかと思いますで、まずは確実に立ち上がる方法で一度クラスタを立ち上げるのがオススメです。

MySQLを利用しているものとして、実際にRDSの設定を行うコマンドは以下のようになります。 ここではマスタユーザは「root」、作成するメタストアのデータベース名は「hive」、接続するユーザは「hive」とします。

$ mysql -h <エンドポイント> -P 3306 -u root -p 
mysql> create database hive;
mysql> use hive;
mysql> source <スキーマ作成ファイル>.sql
mysql> create user hive@localhost identified by '<password>';
mysql> create user hive@'%' identified by '<password>';
mysql> grant all privileges on hive.* to hive@localhost;
mysql> grant all privileges on hive.* to hive@'%';
mysql> flush privileges;

「localhost」と「%」は両方必要ない場合の方が多いですが、 構築するHadoop環境によって繋がったり繋がらなかったりがあったので私の場合常にどちらもつけて対応しています。

メタストア自体の作成をEMRに任せる場合は、データベースとテーブルは作成されているので、 create user以降の処理のみとなります。

あとは実際にクラスタを立ち上げたり終了したりして遊んでみながら本当にメタストアの情報が残っていることを確認するだけです。

終わりに

今回はEMRのメタストアにRDSを利用する方法を紹介しました。 クラスタの起動・終了を頻繁に繰り返すだけでなく、複数のクラスタでメタストアを共有するような時にも便利な仕組みとなります。