稼働中のCDHクラスタからCloudera Managerに移行した話

こちらは[Spark, SQL on Hadoop etc. Advent Calendar](http://qiita.com/advent-calendar/2014/distributedcomputing)の12日目です

# はじめに

[Cloudera Manager](http://www.cloudera.co.jp/products-services/cloudera-enterprise/cloudera-manager.html)はCloudera社が提供するHadoop（CDH）クラスタをGUIで管理・監視ができるアプリケーションです。
（以下一部Cloudera Manager = CMと略します）
職場にて元々CDH4.3を利用してHadoopクラスタを運用していたのですが

- 運用が2-3名
- 障害時に停止や再起動の手順を把握している人そのくらい（ドキュメントは一部用意してあるが…）
- 日々の運用や開発に手一杯で監視が甘い
    - GangliaとCloudForecastとNagiosなど組み合わさってとっちらかる
- 時々とんでもない値を設定しててハマる

などなどありまして、「もうちょい楽して開発に集中したい」というモチベーションが高まりCloudera Managerを採用してみることにしました。
もともとClouderaが定期的に開催しているCloudera Manager勉強会にも参加してなんとなくどういうものかはわかっていたのも理由です。

# 移行前の調査

## 当時の環境について

ざっくり下記のような環境・構成でした

- CentOS 6.4 or 6.5
- rpm installのCDH 4.3.0
- JDK7 u25
- マスターノード群9台（NameNode, JobTracker, Zookeeper, hiveserver2, metastore, hue, etc）
- スレーブノード群100台ほど（DataNode, TaskTracker）

移行を検討し始めた際、CDH5がリリースされ、さらに検証中にCDH5.1がリリースされていたので、移行と一緒にCDH5.1までアップグレードすることになりました。

## 移行方法について

[CMのドキュメント](http://www.cloudera.com/content/cloudera/en/documentation.html)を見れば一通りのインストール方法及びアップグレード方法は書いてありますが、すでにrpmで運用されているCDHクラスタへの移行方法の記述はありませんでした。
そこで検証用のCDH4.3の環境（完全分散環境）を作り、その上にCloudera Managerの管理下に置く方法を検討しました。
結論からいうとおおまかに下記のような手順となりました

1. Cloudera Manager Serverをインストールしておく
2. クラスタを全停止させ、CDH4.3のrpmを全てアンインストールする
3. CM Serverを起動し、クラスタの新規追加ウィザードで既存のノードを全てCloudera Managerの管理下となるよう追加する
4. parcelのバージョンはCDH4.7（4系最新版）を選択してインストール
    - parcel : CM専用のパッケージと考えてもらえばOKです
4. 各サービスのノードを既存の役割と合わせる
5. 各サービスを起動
6. 起動を確認したらCDH5.1へアップグレード
7. 各サービス毎に既存の環境で設定していた内容を反映させる

クラスタを一度全停止する必要がある（しかも長時間）ので止められないクラスタを運用されている方には厳しいかもしれません。
自分のサービスでも規模は大きくないものの毎時のログを集計してサービスに書き戻す処理があり、長時間止められないものがありました。
そこについてはだいぶアクロバットな解決策ですが、5台程度で構成した小さなクラスタを予めCloudera Managerで構築をしておき、移行作業の期間そこで処理をして書き戻しました。

### なぜ事前にrpmの全削除が必要なのか

基本的にparcelは`/opt/cloudera`以下に展開され、既存のrpmと被らないよう設計されています。しかしながら設定やコマンドなどが`alternatives`で切り変えるように設計されており、`/etc/alternatives/`へのシンボリックリンクと競合したのが原因です。

- rpmでインストールしたCDHは`/usr/bin`以下に直接hadoopコマンドやhiveコマンドが設置されておりCMと競合
- `HADOOP_CONF_DIR`となるべき`/etc/hadoop/conf`以下に直接configを設置していて競合
    - これはうちの設計がよくなかったと思う

CMから起動される各種デーモンは`/opt/cloudera`以下で完結しているので、各Gateway用のサーバーだけ気合でシンボリックリンク貼り直す手もありましたが漏れたときが怖かったので事前に削除することにしました。

### 直接CDH5をインストールしない理由

いきなりCDH5にアップグレードすると、hadoopとhiveのバージョンが変わり、NameNodeのメタデータ及びhiveのメタデータのアップグレードが必要になります。
CDH4.3と4.7の間は幸いバージョンが変わっていないのでそのまま起動することができ、CDH5.1へアップグレードする際の一連の作業をCM任せにでき、楽できるためです（そのために採用したわけだし）。

# 移行時のポイント

## Cloudera Managerのインストール方法

お試しの場合は全自動インストールできるbinをダウンロードしてOKなのですが、Cloudera Managerの各種設定などが記録されるRDBが組み込みPostgreSQL一択となってしまい、いざというときのためのバックアップがとりづらいため自分でパッケージをインストールし、記録先のRDBを自分で変更できる[Installation Path B](http://www.cloudera.com/content/cloudera/en/documentation/core/latest/topics/cm_ig_install_path_b.html?scroll=cmig_topic_6_6)を選択することになります。
（ちなみにRDBはMySQLを選択肢、バックアップ用にレプリケーションしています）

なお、負荷の観点からCloudera Manager及びManagement Service（各Agentからのデータを受け取るサービス）用に最低でも1台（計2台）サーバーを用意した方がいいです（とくにManagement Serviceは100台規模の監視だと結構負荷が高くなります）

### NameNode, DataNodeのディレクトリとhiveのmetastoreは既存の設定を反映させる

クラスタインストール時のウィザードでNameNodeとDataNodeのディレクトリ（`dfs.name.dir`と`dfs.data.dir`）を指定する場面がありますが、確実に指定するようにしてください。（でないとまっさらなクラスタができあがる）
hiveのmetastore設定も同様です。

### agentのインストール時の注意点

各サーバーにインストールされる`cloudera-manager-agent`と`cloudera-manager-daemons`のパッケージのうち、`cloudera-manager-daemons`のrpmが約400MBと結構大きく、各ノードがインターネット経由でインストールし始めるとサービスの帯域を圧迫しかねないので、台数が多い場合、自前のyumレポジトリなどにミラーリングしておく方が賢明です。

### parcelの展開は時間がかかる

表題の通り、各ノードにparcelを行き渡らせるには時間がかかります。CMサーバーからのダウンロードになるためインターネット回線は圧迫しませんが、ラック間の帯域などには注意して同時インストール数を決めてください。
cdh5.2のparcelで1.4GB程度あります。

## NameNode HAを組んでいる場合

ここが一番ハマったのですが、NameNode HAを組んでいる場合、一度移行前の環境でHA無しの状態に戻してから停止したほうがよさそうです。
停止前に最後にActiveだったNameNodeにCMからNameNodeをインストールしてうまく起動する手筈でしたが起動に失敗し続けました。
（幸い直前にとっておいた`dfs.name.dir`のバックアップから復旧はできました）
検証環境だとすんなり起動できたんですけどね。

## クラスタインストール時にNameNodeの起動が失敗する

これは`dfs.name.dir`が空でない場合に必ず起こります。
そこまで進んだら別のタブでCMにアクセスしてログインし、各種サービスを再起動すれば動きます。

## 既存の設定をどうするか

CMは設定された内容を元に`core-site.xml`や`hive-site.xml`などをロール毎に生成し、各ノードに配布します。
既存のxmlに直接書いた設定のインポートなどの機能は残念ながらありません。
一応CMには各ロール毎に`高度な設定スニペット（安全バルブ）`というxmlなどをベタ書きできる項目があるのでとりあえずそこにコピペしてしまうのも手です。
（ただし設定項目によっては後から設定してもコピペした設定が優先されてしまうので、徐々に書き戻していく必要はあるかと思います）

### Rack Awarenessについて

Rack Awarenessの設定（ラックの割り当て）についてですが、初期設定ですべて`default`というラックになってしまいます。
既存の設定はIPアドレスとラック番号が各行タブ区切りのものを利用していたため、それをCMに対してAPIで設定するスクリプトを用意しました。
gistに置いておいたので参考にしてください https://gist.github.com/s-wool/2a05c65bb8bc3e2b8700
`$user`, `$pass`及び`$endpoint`の部分はご自身の環境に合わせてください。
なぜperlなのかはお察しください。

## Cloudera Manager自体の高可用性について

NameNodeやResourceManagerでおなじみのHAですが、ClouderaManager自体にはHA構成はありません。しかしながら設定が記録されているRDBさえ残っていればすぐに復帰できます。なのでコールドスタンバイな環境を用意しておくとよさそうです。

# その他

## Cloudera EnterpriseとExpressについて

移行直後は60日間お試しできるCloudera Enterpriseを利用していましたが、60日をすぎたので無償の現在Expressで運用しています。
設定の履歴やロールバック、ローリング再起動や監査など便利な機能が豊富なので予算に余裕があればEnterpriseのご相談をするべきかなと思います。
今のところExpress版でも採用前より効率よく運用ができています。
APIを駆使すればEnterprise版の一部の機能はカバーできるかもしれません。

# おわりに

以上、すでに別の方法でインストールしたCDH環境からCloudera Managerへ移行する時の手順とその注意点を書いてみました。
移行は気をつけなければいけないポイントがいくつもありますが、これからクラスタを構築するというパターンであればCloudera Managerを採用するとインストールがものすごい楽になるかと思います（必要なサーバーは増えますが）。
手元のメモから一気に書き起こしたため至らないところもあるかと思いますので、ご質問、ツッコミありましたらぜひコメントください。

明日は @ka4geru さんです。お楽しみに！