Cloudera Manager/CDH のローカルリポジトリ構築

Spark, SQL on Hadoop etc. Advent Calendar 2014 19日目です。

## はじめに

[前回](http://qiita.com/azurecube/items/c45168c13b456c58340d)Cloudera Manager APIを使ってCDHのインストールをするサンプルを紹介しました。

前回の内容をアレンジすることでインストール作業の自動化を図れるようになると思いますが、それでも処理には時間がかかると思います。その一因としてはデータのダウンロード処理が考えられます。これは検証などで繰り返し環境をセットアップする場合に特に問題になると思います。そこで、今回はローカルネットワークにリポジトリを作成してインストールを高速化する方法を紹介していきます。

リポジトリ作成後のインストール方法としては下記になります。
1. Cloudera Manager ServerをRPMでインストールする
2. Cloudera Manager Agentをクラスタの各ノードでRPMでインストールする
3. Cloudera Manager APIを使ってParcelからクラスタを構成する

なお、CM/CDH 5.2.1 をインストールするためだけのものなので、複数のバージョンを提供する場合には適宜アレンジしてください。

## 前提
CentOS6.5 がインストールされている環境を想定しています。
それぞれの環境はDNSか/etc/hostsでそれぞれに名前解決できることを想定しています。
また、リポジトリサーバではhttpdを新しくインストール/起動するので既存のサーバがある場合は注意が必要です。

パッケージ処理などが多いためrootで実行することを想定している点も注意してください。

## リポジトリサーバ
今回二つのリポジトリを作成します。
- Cloudera Manager (rpm)
- CDH (Parcel)

それぞれ変数にしている箇所は下記の内容になります。
バージョンを適宜変更してください。
- repo_origin   : パッケージを取得してくる元のリポジトリ
- doc_root      : httpdのDocumentRoot、ダウンロードしてきたパッケージはこの配下に展開します
- cm_ver        : Clouera Managerのバージョン
- cdh_ver       : CDHのバージョン

```bash
#!/bin/sh

#Setting Variables
repo_origin=http://archive.cloudera.com/
doc_root=/var/www/html

cm_ver=5.2.1
cm_major=cm`echo $cm_ver | cut -d'.' -f1`

cdh_ver=5.2.1
cdh_major=cdh`echo $cdh_ver | cut -d'.' -f1`


#get CM
wget -r -nd -np -np -P $doc_root/archive/$cm_major/ $repo_origin/$cm_major/repo-as-tarball/$cm_ver/cm${cm_ver}-centos6.tar.gz
(cd $doc_root/archive/$cm_major; tar xvf cm*-centos6.tar.gz)

#get Parcel
wget -r -nd -np -np -P $doc_root/archive/$cdh_major/$cdh_ver -A CDH-${cdh_ver}-*-el6.parcel $repo_origin/$cdh_major/parcels/$cdh_ver/
wget -r -nd -np -np -P $doc_root/archive/$cdh_major/$cdh_ver $repo_origin/$cdh_major/parcels/$cdh_ver/manifest.json

#Start Http Server
yum -y install httpd
service httpd start
```

上記を実行したノードでパッケージが提供されるようになります。
以下ではCloudera Managerのサーバとクラスタに参加するノードからこのリポジトリを使う例を紹介します。

## Cloudera Manager Server Node
下記を実行することでOSのリポジトリとして上記のリポジトリサーバとして構成し、それを使ってパッケージをインストールします。設定が必要な変数は下記になります。
- repository: 上述のリポジトリを構成したサーバ名
- cm_ver    : Cloudera Managerのバージョン

```bash
#!bin/sh

# Repository Setting
repository=myrepo.cloudera.com
cm_ver=5.2.1
cm_major=cm`echo $cm_ver | cut -d'.' -f1`

# Set CM Repository for OS Package
cat <<EOF > /etc/yum.repos.d/cm.repo
[cloudera-manager]
name = Cloudera Manager
baseurl = http://$repository/archive/$cm_major/cm/$cm_ver
gpgcheck = 0
EOF

# Install Packages
yum -y install cloudera-manager-server-db-2
yum -y install cloudera-manager-server
yum -y install oracle-j2sdk1.7

# Start Services
service cloudera-scm-server-db start
service cloudera-scm-server start
```

## Cloudera Manager Agent Node
下記を実行することでOSのリポジトリとして上記のリポジトリサーバとして構成し、それを使ってパッケージをインストールします。設定が必要な変数は下記になります。
- repository: 上述のリポジトリを構成したサーバ名
- cm_ver    : Cloudera Managerのバージョン
- cm_host   : Cloudera Manager Serverの稼動しているノード
リポジトリを設定してパッケージをインストール/起動、という流れはServerと同じですが、連携のためにCloudera Manager Serverの稼動しているノードを設定する部分が変わっています。

```bash
#!/bin/sh

# Repository Setting
repository=myrepo.cloudera.com

cm_ver=5.2.1
cm_major=cm`echo $cm_ver | cut -d'.' -f1`

#Set CM host
cm_host=mycm.cloudera.com

# Set CM Repository for OS Package
cat <<EOF > /etc/yum.repos.d/cm.repo
[cloudera-manager]
name = Cloudera Manager
baseurl = http://$repository/archive/$cm_major/cm/$cm_ver
gpgcheck = 0
EOF

# Install Packages
yum -y install cloudera-manager-agent
yum -y install oracle-j2sdk1.7

# Set CM host to report status
sed -i "s/server_host=localhost/server_host=$cm_host/" /etc/cloudera-scm-agent/config.ini

# Start Agent Service
service cloudera-scm-agent start
```

## CDHのインストール
これは [前回](http://qiita.com/azurecube/items/c45168c13b456c58340d)とほぼ同様ですが、若干処理を変えたものを[こちら](https://gist.github.com/azurecube/3bb827db631e9d51c7a2)にアップロードしてあります。

主な違いはAgentがインストール済みなのでインストール処理を抜いているところとParcelのリポジトリを作成したので下記のように設定をしています。
これは一括して変更する必要があるので注意してください。また、今回の変更を反映しているのはCDH5のlatestではなくローカルネットワークのリポジトリを見るようにしている箇所だけです。
それ以外のParcelをダウンロードする場合には外部リポジトリへのアクセスが発生することになります。

```bash
### Setting Parcel Repository
curl -X PUT -u "admin:admin" -i \
  -H "content-type:application/json" \
  -d '{ "items": [ {"name" : "REMOTE_PARCEL_REPO_URLS",
                    "value": "http://'$PARCEL_REP'/archive/cdh'$CDH_MAJOR'/'$CDH_VER',http://archive.cloudera.com/cdh4/parcels/latest/,http://archive.cloudera.com/impala/parcels/latest/,http://archive.cloudera.com/search/parcels/latest/,http://archive.cloudera.com/spark/parcels/latest/,http://archive.cloudera.com/navigator-keytrustee5/parcels/latest/,http://archive.cloudera.com/sqoop-connectors/parcels/latest/,http://archive.cloudera.com/accumulo/parcels/1.4/,http://archive.cloudera.com/accumulo-c5/parcels/latest/"
  }]}' \
$BASE/cm/config
```

# まとめ
いかがでしたでしょうか。一応検証ということであれば全て1ノードで実施してしまうこともできると思いますが検証などでCMやクラスタの再作成を繰り返すのであればリポジトリを別に作成しておくと便利だと思います。

日本にあるサーバだとどうしても物理距離上公開リポジトリへのアクセスが遅くなったり、そもそもネットワークと繋っていない環境ということもあると思いますのでそういった場合にこういった方法も検討してみてもらえればと思います。


## おまけ
RHEL/CentOSのリポジトリに関連して。
Cloudera Manager勉強会の際にCentOS6.6が2014/12/19現在まだサポートされていないのにyum updateを掛けると6.6になってしまうという話があったのですが、下記のように /etc/yum/vars/releasever を設定することで、/etc/yum.repos.d 配下のファイルで使用されている$releaseverを固定してupdateをすることができます。

```bash
# cat /etc/redhat-release
CentOS release 6.4 (Final)
# echo "6.5" > /etc/yum/vars/releasever
# yum -y update
:
# cat /etc/redhat-release
CentOS release 6.5 (Final)
```