Amazon Linux に ZooKeeper をインストールする

Jubatus を分散モードで動かすにあたって ZooKeeper のインストールで手間取ったのでそのメモ。
（もしもっと良い方法があったらコメント等で教えてください）

# yum install zookeeper-client → ×

Jubatus のリポジトリを追加した状態だと zookeeper-client-* というパッケージがいくつか見つかる。これは Jubatus のリポジトリから提供されているようだ。

```
$ yum search -q zookeeper
============================ N/S matched: zookeeper ============================
zookeeper-client.x86_64 : ZooKeeper C Client
zookeeper-client-debuginfo.x86_64 : Debug information for package
                                  : zookeeper-client
zookeeper-client-devel.x86_64 : Headers and libraries for ZooKeeper client
zookeeper-client-utils.x86_64 : Utility commands for ZooKeeper
```

ただし、パッケージ名から分かる通りこれにはサーバは含まれていない。

# CDH5 リポジトリ → ×

Cloudera が提供している CDH という Hadoop 関連のソフトウェアを簡単に導入するためのディストリビューションに ZooKeeper が含まれている。[ドキュメント] (http://www.cloudera.com/content/cloudera/en/documentation/cdh5/v5-0-0/CDH5-Installation-Guide/cdh5ig_cdh5_install.html) に従ってリポジトリを追加すると yum で zookeeper-server をインストールできるようになる。

yum install zookeeper-server を実行したところ、依存関係で入るパッケージが多すぎるのでこの方法は不採用。

# jubatus-installer (zookeeper のソースからインストール) → △

[jubatus-installer] (https://github.com/jubatus/jubatus-installer) は Jubatus をソースから簡単にインストールするためのスクリプト。試しにこれを使ってインストールしてみたけど基本的に RPM パッケージから入れた場合と変わらないようだ（ビルドにはかなり時間がかかるのでこれは時間の無駄だった）。ただ、展開されたディレクトリの中に zookeeper のソースがあったので、ここからインストールすることを考える。なお jubatus-installer を実行するために以下のパッケージはこの時点でインストール済み。

```
$ sudo yum install autoconf automake gcc gcc-c++ libtool
```

まず ant が必要なのでインストール:

```
$ sudo yum install ant
```

ant rpm を実行するとエラーが出た:

```
BUILD FAILED
/home/ec2-user/jubatus-installer/download/zookeeper-3.4.6/build.xml:272: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64/jre"
```

JAVA_HOME が jre を指していたので jdk を指すように変更:

```
$ export JAVA_HOME=/usr/lib/jvm/java
```

今度は cppunit がないと怒られた。 cppunit は CentOS 標準だがなぜか Amazon Linux のリポジトリにないので、 CentOS のリポジトリを追加する。

```
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo
$ cat /etc/yum.repos.d/CentOS-Base.repo
[centos-base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os
enabled=0
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
$ sudo yum install cppunit cppunit-devel --enablerepo=centos-base
```

make distclean しろと言われたので src/c/ に入って make distclean を実行。

rpm -ba が実行できないというエラーが出たので rpm-build パッケージをインストール。

そうしたらこんなエラーが出た。

```
/usr/lib/rpm/redhat/brp-compress: No such file or directory
```

しかしそんなコマンドはない。 RPM ビルド時にこのコマンドを呼ばないようにすればよさそう。

~/.rpmmacros というファイルを作って __os_install_post, __spec_install_post あたりを無効にする。

```
$ echo "%__os_install_post %{nil}" >> ~/.rpmmacros
$ echo "%__spec_install_post %{nil}" >> ~/.rpmmacros
```

以下のようなエラーが出たが RPM パッケージ自体はできたようだ。

```
cd: /tmp/zkpython_build_ec2-user/BUILD: No such file or directory
```

# rpm build → ○

こんな面倒くさい思いをしなくて済む方法はないかと調べたら CentOS 6 用の RPM パッケージを公開している人がいた。

https://github.com/globocom/zookeeper-centos-6/downloads

ここからパッケージをダウンロードして、依存パッケージの java-1.6.0-openjdk も入れてインストールしたら、こんなエラーが出た。

```
	ファイル /usr/bin (パッケージ zookeeper-3.4.3-2.x86_64 から) は、パッケージ filesystem-2.4.30-3.8.amzn1.x86_64 からのファイルと競合しています。
	ファイル /usr/sbin (パッケージ zookeeper-3.4.3-2.x86_64 から) は、パッケージ filesystem-2.4.30-3.8.amzn1.x86_64 からのファイルと競合しています。
```

パッケージの作りがよくないっぽいので spec ファイルを修正してみる。

まず RPM ビルド用の環境を整える。

```
$ mkdir -p ~/rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ echo "%_topdir $HOME/rpm" >> ~/.rpmmacros
```

src.rpm がないのでリポジトリを clone してファイルをコピーして

```
$ git clone https://github.com/globocom/zookeeper-centos-6.git
$ cd zookeeper-centos-6
$ cp zookeeper.spec ~/rpm/SPECS/
$ cp redhat/* ~/rpm/SOURCES/
```

http://www.apache.org/dist/zookeeper/zookeeper-3.4.6/ からソースファイルを ~/rpm/SOURCES/ にダウンロードして (jubatus-installer を実行しているなら既にダウンロード済みのファイルがあるので単にそれをコピーすれば良い)、 spec ファイルを以下のように修正する。

```diff
--- zookeeper.spec.orig	2015-04-21 07:44:00.388891361 +0000
+++ zookeeper.spec	2015-04-21 10:40:31.141715834 +0000
@@ -4,7 +4,7 @@
 
 %define _noarch_libdir /usr/lib 
 
-%define rel_ver 3.4.3
+%define rel_ver 3.4.6
 
 Summary: High-performance coordination service for distributed applications.
 Name: zookeeper
@@ -21,7 +21,7 @@
 Source5: java.env
 BuildRoot: %{_tmppath}/%{name}-%{rel_ver}-%{release}-root
 BuildRequires: python-devel,gcc,cppunit-devel
-Requires: logrotate, java-1.6.0-openjdk
+Requires: logrotate, java-1.7.0-openjdk
 Requires(post): chkconfig initscripts
 Requires(pre): chkconfig initscripts
 AutoReqProv: no
@@ -111,8 +111,8 @@
 %{_initrddir}/zookeeper
 %config(noreplace) %{_sysconfdir}/logrotate.d/zookeeper
 %config(noreplace) %{_sysconfdir}/zookeeper
-%{_sbindir}
-%{_bindir}
+%{_sbindir}/*
+%{_bindir}/*
 
 # ------------------------------ libzookeeper ------------------------------
 
```

変更したのは次の3点:

* インストールする ZooKeeper のバージョンを 3.4.3 -> 3.4.6 に変更
* Java のバージョンをデフォルトでインストールされている 1.7.0 に変更 
* 他のパッケージとコンフリクトしないように %files を調整

RPM パッケージをビルド:

```
$ rpmbuild -ba ~/rpm/SPECS/zookeeper.spec
```

これで ~/rpm/RPMS/x86_64/ 以下に rpm ファイルができた。

# まとめ

素の Amazon Linux で ZooKeeper をインストールするには以下の手順を実行すれば良い。

```
$ sudo yum update
$ sudo yum install gcc automake autoconf libtool python-devel git rpm-build
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo  ### 内容は前述
$ sudo yum install cppunit-devel --enablerepo=centos-base
$ mkdir -p ~/rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ echo "%_topdir $HOME/rpm" >> ~/.rpmmacros
$ git clone https://github.com/globocom/zookeeper-centos-6.git
$ cp zookeeper-centos-6/zookeeper.spec ~/rpm/SPECS/
$ cp zookeeper-centos-6/redhat/* ~/rpm/SOURCES/
$ cd ~/rpm/SOURCES
$ wget http://www.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz
$ cd ~/rpm/SPECS
$ vi zookeeper.spec  ### 内容は前述
$ rpmbuild -ba zookeeper.spec
$ sudo rpm -Uvh ~/rpm/RPMS/x86_64/zookeeper-3.4.6-2.x86_64.rpm
```

(Amazon Linux AMI release 2015.03 で確認)