HDP2.1からHDP2.5.3へアップグレードした
約1年前に別のHadoopクラスタをHDP2.1からHDP2.4にアップグレードした話はHadoopソースコードリーディング 第20回で発表しました。
Hadoopソースコードリーディング 第20回で発表してきました - wyukawa’s blog
このクラスタはデータソースがFluentdからのほぼ書き込みのみでバッチの数もazkabanのflowでいったら実質2個だったのでアップグレードは容易でした。
アップグレード方法はクラスタを新規に用意してFluentdから両方に書き込んでバッチも両方動かして、過去データはdistcpでコピーというやり方です。
今回はこれとは別のクラスタをアップグレードしました。
このクラスタの特徴は下記の通りです。
- 各サービスのDBからsqoop importでデータを取ってくる。DBの数は50個以上
- バッチの数が多い。azkabanでスケジューリングしているflowの数は100以上
- 複数人でバッチ開発が行なわれている
- Hiveで集計した結果を別DB(例:InfiniDB, Netezza)に書き込んでいる
- Prestogres経由でBIツールで参照している
- Fluentdは使っているがバックアップ用途なので事実上無視して良い。
今回もクラスタを新規に用意しています。
しかしデータを同時に両方に書き込んで、バッチを両方で動かすことはやりませんでした。
理由は、同時にバッチを動かすとサービス側のDBの負荷が2倍になることや、InfiniDB, Netezzaをさらに別途用意する必要があったからです。まあその辺はモックで騙す手はあったかもしれません。
新規クラスタを用意せずに休日に上書きアップグレードすることも考えましたが、マシンの保守切れが近いこともあってそれはやめました。
アップグレードしたかったもう一つの理由はHDP2.1付属のAmbariで構築するとresource managerがSPOFになるからというのもありました。
そんなわけでアップグレードをしたわけですが、下記のようにやりました。
- HDFS SnapshotsとDistCpを利用したHDFSデータの差分更新を参考にしてsnapshotを使ってdistcpで差分コピー
- 上記でコピーしている間もバッチは動いているのでデータは追加され続ける。その分はさらに差分コピーする
- 差分が十分に少なくなった段階でバッチを止める。
- 差分コピーして新旧クラスタでデータを同じ状態にする。
- 新環境でバッチ開始
ざっくりいうとこんな感じですが、コピーの部分をもうちょっと詳しく書きます。
今回はhiveのdb単位で移行しました。
まず移行元でdb単位にhdfs snapshotを作成します。最初はs1
for db in ... do sudo -u hdfs hdfs dfsadmin -allowSnapshot /apps/hive/warehouse/${db}.db sudo -u hdfs hdfs dfs -createSnapshot /apps/hive/warehouse/${db}.db s1 done
移行先でdistcpします。-mとか-bandwidthとかのネットワーク帯域に関してはネットワークチームの人と相談して決めました。
for db in ... do sudo -u ... hadoop distcp ... -update hdfs://oldservice/apps/hive/warehouse/${db}.db/.snapshot/s1 /apps/hive/warehouse/${db}.db done
ここでhdfs://oldserviceって書いてあるところがちょっと肝で、webhdfsを使っていません。というのも後述する差分コピーのhadoop distcp -update -diffでwebhdfsが使えないからです。
下記のように言われると思います。
The FileSystems needs to be DistributedFileSystem for using snapshot-diff-based distcp
そのため移行先のバッチサーバー(distcpを実行するマシン)の/etc/hadoop/conf/hdfs-site.xmlをいじって下記のようにして、hdfs://oldserviceとして移行元のHDFSを以降先から参照できるようにします。
なおoldserviceは適当につけた名前です。わかりやすければなんでもいいと思います。namenodeのホストやポートは環境に合わせて設定してください。
<property> <name>dfs.nameservices</name> <value>..., oldservice</value> </property> <property> <name>dfs.client.failover.proxy.provider.oldservice</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <property> <name>dfs.ha.namenodes.oldservice</name> <value>nn3,nn4</value> </property> <property> <name>dfs.namenode.http-address.oldservice.nn3</name> <value>active-namenode:port</value> </property> <property> <name>dfs.namenode.http-address.oldservice.nn4</name> <value>stanby-namenode:port</value> </property> <property> <name>dfs.namenode.rpc-address.oldservice.nn3</name> <value>active-namenode:another-port</value> </property> <property> <name>dfs.namenode.rpc-address.oldservice.nn4</name> <value>stanby-namenode:another-port</value> </property>
最初のコピーは当然ですが、時間がかかります。僕の環境では3,4日かかりました。
時間を計算する際にはhadoop fs -du -hで出した容量を3倍するのはお忘れなく。
1回目コピーが終わったら差分コピーします。
移行元でsnapshot s2を作ります。
sudo -u hdfs hdfs dfs -createSnapshot /apps/hive/warehouse/${db}.db s2
移行先でsnapshot s1を作成してから差分コピーします。
sudo -u hdfs hdfs dfsadmin -allowSnapshot /apps/hive/warehouse/${db}.db sudo -u hdfs hdfs dfs -createSnapshot /apps/hive/warehouse/${db}.db s1 sudo -u ... hadoop distcp ... -update -diff s1 s2 hdfs://oldservice/apps/hive/warehouse/${db}.db /apps/hive/warehouse/${db}.db
あとはこれを繰り返します。hiveのパーティション作成はmsck repair tableで一気に作れますが、パーティションの数が4000とかになってくると返ってこなかったです。
DDLはshow create tableで作りました。
ほかにやっかいなのは外部テーブルでhdfs://を使っているとselectできないことです。
https://issues.apache.org/jira/browse/HIVE-11116
っぽいですが、回避策がわからなかったのでwebhdfs://にしています。
そうすると今度はprestoでselectできないという問題があるのですが、jersey-bundle-1.19.3.jarを入れれば見れるというワークアラウンドはあります。
Google グループ
hive, sqoop周りでいじったのは下記です。
hive.auto.convert.join=false
sqoop import時にエラーになるのでambariでsqoop-site.xmlをorg.apache.sqoop.splitter.allow_text_splitter=trueに変更
Sqoop Import: "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" - Hortonworks
カラム名にdateを使えなくなったのでambariでhive.support.sql11.reserved.keywords=falseに変更
hadoop - Using reserved words in Hive - Stack Overflow
アップグレード前がmapreduceだったのでそのままにしていたが以下のエラーに遭遇したバッチに関してはtezに変更
Solution for "Hive Runtime Error while processing row" (only on MR) - Hortonworks
ORA-00904がでたものは--split-byをやめて--queryや--boundary-queryを使うように変更
hivemallのsha1をコメントアウト
question about hivemall install · Issue #331 · myui/hivemall · GitHub
あとはUNIONしてるクエリの間で型が違うエラーになるのでcastして合わせる。
他にもあった気がしますが、こんな感じです。
大事なことはアップグレードは週の初めにやることと翌日のバッチエラー対応は2人以上やることです。
間違っても金曜日にアップグレードをするのはお勧めしませんし、木曜日もやめたほうがいいです。バッファが1日しかないから。
今回は火曜日にアップグレードしました。
そんな感じです。ではでは。