このシリーズ
- Apache Zeppelinでデータ分析を分散処理する - Part 1: データ分析のライフサイクル
- Apache Zeppelinでデータ分析を分散処理する - Part 2: Ambari on DockerにZeppelinをセットアップする
- Apache Zeppelinでデータ分析を分散処理する - Part 3: ZeppelinでHiveを使えるようにする
- Apache Zeppelinでデータ分析を分散処理する - Part 4: Ambari on Dockerのambari-functionsを使ってみる
Ambari on Docker
Apache AmbariでHadoopクラスタをDocker上にセットアップしてみます。AmbariはHadoop管理プラットフォームです。ブラウザの管理画面からHadoopのプロビジョニングや監視を行うことができますが、今回はAmbari ShellのCLIからHDPをクラスタをセットアップしてみます。
SequenceIQが公開しているsequenceiq/ambariのDockerイメージをpullします。リポジトリはdocker-ambariです。
$ docker pull sequenceiq/ambari
docker-ambariをダウンロードしてシェルスクリプトを読み込みます。
$ git clone https://github.com/sequenceiq/docker-ambari
$ cd docker-ambari
$ source ambari-functions
ambari-functionsにはamb-*
関数が定義されています。Ambari on Dockerのセットアップ前に環境変数を確認してみます。
$ amb-settings
NODE_PREFIX=amb
CLUSTER_SIZE=3
AMBARI_SERVER_NAME=amb-server
IMAGE=sequenceiq/ambari:2.1.2-v1
DOCKER_OPTS=
AMBARI_SERVER_IP=
CONSUL=amb-consul
CONSUL_IMAGE=sequenceiq/consul:v0.5.0-v6
DRY_RUN=false
Dockerに4ノードのクラスタを構築します。4ノードのうち1ノードはAmbari Serverになります。そのためHadoopクラスタは3ノードのコンテナで構成されます。
$ amb-start-cluster 4
コンテナが起動するとAMBARI_SERVER_IP
環境変数にAmbari ServerコンテナのIPアドレスが設定されます。
$ amb-settings
NODE_PREFIX=amb
CLUSTER_SIZE=3
AMBARI_SERVER_NAME=amb-server
IMAGE=sequenceiq/ambari:2.1.2-v1
DOCKER_OPTS=
AMBARI_SERVER_IP=172.17.0.3
CONSUL=amb-consul
CONSUL_IMAGE=sequenceiq/consul:v0.5.0-v6
DRY_RUN=false
AmbariのREST APIをcurlコマンドからAmbariが管理しているホストの情報を確認してみます。
$ curl -u admin:admin http://$AMBARI_SERVER_IP:8080/api/v1/hosts
{
"href" : "http://172.17.0.3:8080/api/v1/hosts",
"items" : [
{
"href" : "http://172.17.0.3:8080/api/v1/hosts/amb1.service.consul",
"Hosts" : {
"host_name" : "amb1.service.consul"
}
},
{
"href" : "http://172.17.0.3:8080/api/v1/hosts/amb2.service.consul",
"Hosts" : {
"host_name" : "amb2.service.consul"
}
},
{
"href" : "http://172.17.0.3:8080/api/v1/hosts/amb3.service.consul",
"Hosts" : {
"host_name" : "amb3.service.consul"
}
}
]
}
別のシェルから実行するなどAMBARI_SERVER_IP
環境変数が読み込まれていない場合は手動で設定します。
$ AMBARI_SERVER_IP=$(docker inspect --format="{{ .NetworkSettings.IPAddress }}" amb-server)
Ambari Shell
Ambari Shellにもsequenceiq/ambari-shellDockerイメージが公開されています。リポジトリはdocker-ambari-shellです。今回はsequenceiq/ambariに入っているambari-shell.shからAmbari Shellを起動します。
$ docker run -it --rm \
--link amb-server:ambariserver \
--entrypoint /bin/sh \
sequenceiq/ambari \
./ambari-shell.sh
Ambari Shellが起動しました。
AMBARI_HOST=172.17.0.3
[DEBUG] waits for ambari server: 172.17.0.3 RUNNING ...
[DEBUG] waits until 1 hosts connected to server ...
[DEBUG] connected hosts: 3
_ _ _ ____ _ _ _
/ \ _ __ ___ | |__ __ _ _ __ (_)/ ___| | |__ ___ | || |
/ _ \ | '_ ` _ \ | '_ \ / _` || '__|| |\___ \ | '_ \ / _ \| || |
/ ___ \ | | | | | || |_) || (_| || | | | ___) || | | || __/| || |
/_/ \_\|_| |_| |_||_.__/ \__,_||_| |_||____/ |_| |_| \___||_||_|
Welcome to Ambari Shell. For command and param completion press TAB, for assistance type 'hint'.
ambari-shell>
Blueprint
BlueprintはHadoopクラスタをJSON形式で定義します。Web画面のウィザードを使わなくてもREST APIやAmbari Shellからクラスタのプロビジョニングを行うことができます。
CloudbreakのBlueprint
SequenceIQのCloudbreakBlueprintsにいくつかBlueprintの例が掲載されています。CloudbreakはAmbariをベースにしたクラウド向けのHadoop管理ツールです。Azure、AWS、GCP、OpenStackのクラウドとDockerにも対応しています。ドキュメントを読むとAmbari Blueprintだけでも使えそうです。
datascientistをセットアップ
Cloudbreakのリポジトリからdatascientist.bpから、Dockerコンテナで構成したAmbariノードにHDPクラスタをプロビジョニングします。
デフォルトで登録されているsingle-node-hdfs-yarn
を適用したプロビジョニングの流れは次のようになります。
blueprint defaults
blueprint list
cluster build --blueprint single-node-hdfs-yarn
cluster autoAssign
cluster create
tasks
先ほど起動したAmbari Shellの中でdatascientist
のBlueprintのURLを登録します。
ambari-shell> blueprint add --url https://raw.githubusercontent.com/sequenceiq/cloudbreak/master/core/src/main/resources/defaults/blueprints/datascientist.bp
Blueprint: 'datascientist' has been added
登録したdatascientist
をビルドします。Ambariホストの情報とBlueprintにて疑義されたホストグループが表示されます。
ambari-shell> cluster build --blueprint datascientist
HOSTNAME STATE
------------------- -------------------
amb3.service.consul amb3.service.consul
amb1.service.consul amb1.service.consul
amb2.service.consul amb2.service.consul
HOSTGROUP COMPONENT
--------- ----------------------
client TEZ_CLIENT
client YARN_CLIENT
client HIVE_CLIENT
client HDFS_CLIENT
client PIG
client MAPREDUCE2_CLIENT
client ZOOKEEPER_CLIENT
client HCAT
client METRICS_COLLECTOR
client SPARK_CLIENT
client METRICS_MONITOR
client HBASE_CLIENT
slave_1 HBASE_REGIONSERVER
slave_1 NODEMANAGER
slave_1 DATANODE
slave_1 METRICS_MONITOR
master_1 RESOURCEMANAGER
master_1 JOURNALNODE
master_1 WEBHCAT_SERVER
master_1 MYSQL_SERVER
master_1 ZOOKEEPER_CLIENT
master_1 HISTORYSERVER
master_1 SECONDARY_NAMENODE
master_1 METRICS_MONITOR
master_1 NAMENODE
master_1 ZEPPELIN_MASTER
master_1 TEZ_CLIENT
master_1 YARN_CLIENT
master_1 MAPREDUCE2_CLIENT
master_1 HDFS_CLIENT
master_1 HIVE_SERVER
master_1 HBASE_MASTER
master_1 PIG
master_1 SPARK_JOBHISTORYSERVER
master_1 HIVE_METASTORE
master_1 ZOOKEEPER_SERVER
master_1 APP_TIMELINE_SERVER
cluster autoAssign
を実行するとホストグループの定義に応じて自動的にAmbariホストがアサインされます。今回は3つのホストグループに1つずつ手動でホストをアサインしていきます。
CLUSTER_BUILD:datascientist> cluster assign --hostGroup master_1 --host amb1.service.consul
amb1.service.consul has been added to master_1
CLUSTER_BUILD:datascientist> cluster assign --hostGroup slave_1 --host amb2.service.consul
amb2.service.consul has been added to slave_1
CLUSTER_BUILD:datascientist> cluster assign --hostGroup client --host amb3.service.consul
amb3.service.consul has been added to client
最後にcluster create
コマンドを実行してHDPクラスタのプロビジョニングを開始します。
CLUSTER_BUILD:datascientist> cluster create --exitOnFinish true
tasks
コマンドを実行すると各コンポーネントのインストール状況がわかります。またシェルの右上に完了までの全体のパーセントが表示されます。IDCFクラウドのstandard.L16
(4 CPU x 2.4 GHz 16 GB RAM)の仮想マシンでは13分ほどかかりました。
ConsulとNginxのリバースプロキシ
HadoopクラスタのサービスディスカバリにはConsulを使っています。Dockerイメージはsequenceiq/consul、リポジトリはgliderlabs/docker-consulからforkしたsequenceiq/docker-consulです。
psコマンドでコンテナのポートを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce146ebf73f1 sequenceiq/ambari:2.1.2-v1 "/start-agent" 12 minutes ago Up 12 minutes 8080/tcp amb3
9c23d449cb83 sequenceiq/ambari:2.1.2-v1 "/start-agent" 12 minutes ago Up 12 minutes 8080/tcp amb2
162662822eb1 sequenceiq/ambari:2.1.2-v1 "/start-agent" 12 minutes ago Up 12 minutes 8080/tcp amb1
6729936f59f8 sequenceiq/ambari:2.1.2-v1 "/start-server" 12 minutes ago Up 12 minutes 8080/tcp amb-server
02ee7f29a74e sequenceiq/consul:v0.5.0-v6 "/bin/start -server -" 12 minutes ago Up 12 minutes 53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8500/tcp, 8301-8302/udp amb-consul
上記のようにDockerコンテナのポートはDockerホストにマップしていません。そのためDockerホストからしかDockerコンテナのIPアドレスへアクセスができません。今回の環境はIDCFクラウド上の仮想マシンなので、パブリックIPアドレスからAmbariとZeppelinの管理画面にアクセスできるようにNignxコンテナでリバースプロキシを作ります。
Consul
Ambari ServerのREST APIのJSONを見やすくするためにjqをDockerホストにインストールします。
$ wget -P /usr/local/bin jq http://stedolan.github.io/jq/download/linux64/jq
$ chmod u+x /usr/local/bin/jq
$ which jq
/usr/local/bin/jq
Consulクラスタのノードを表示してみます。
$ AMB_CONSUL=$(docker inspect --format="{{ .NetworkSettings.IPAddress }}" amb-consul)
$ echo $AMB_CONSUL
172.17.0.2
$ curl -s $AMB_CONSUL:8500/v1/catalog/nodes | jq .
[
{
"Node": "amb-consul.service.consul",
"Address": "172.17.0.2"
},
{
"Node": "amb-server",
"Address": "172.17.0.3"
},
{
"Node": "amb1",
"Address": "172.17.0.4"
},
{
"Node": "amb2",
"Address": "172.17.0.5"
},
{
"Node": "amb3",
"Address": "172.17.0.6"
},
{
"Node": "ambari-8080",
"Address": "172.17.0.3"
}
]
Consulに登録されたサービスを表示します。
$ curl -s $AMB_CONSUL:8500/v1/catalog/services | jq .
{
"amb-server": [],
"amb1": [],
"amb2": [],
"amb3": [],
"ambari-8080": [],
"consul": []
}
amb-consulサービスの詳細を表示します。
$ curl -s $AMB_CONSUL:8500/v1/catalog/service/consul | jq .
[
{
"Node": "amb-consul.service.consul",
"Address": "172.17.0.2",
"ServiceID": "consul",
"ServiceName": "consul",
"ServiceTags": [],
"ServiceAddress": "",
"ServicePort": 8300
}
]
digコマンドでConsulのDNSサービスを見ることもできます
$ dig @$AMB_CONSUL -p 53 amb-consul.service.consul
; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> @172.17.0.2 -p 53 amb-consul.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 65241
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;amb-consul.service.consul. IN A
;; Query time: 1 msec
;; SERVER: 172.17.0.2#53(172.17.0.2)
;; WHEN: Sat Dec 05 21:47:03 JST 2015
;; MSG SIZE rcvd: 43
Consul TempateとNginx
Consul Templateを使いDockerコンテナの情報からNginxの設定ファイルを生成します。jlordiales/nginx-consulのDockerイメージが公開されています。今回はAmbari用にリポジトリをforkしました。
以下のようなDockerfileからDockerイメージをビルドします。
FROM nginx:latest
ENV CONSUL_TEMPLATE_VERSION 0.11.0
ENV CONSUL_URL consul:8500
ADD start.sh /bin/start.sh
RUN rm -v /etc/nginx/conf.d/*.conf
ADD https://github.com/hashicorp/consul-template/releases/download/v${CONSUL_TEMPLATE_VERSION}/consul_template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip /tmp/consul-template.zip
RUN apt-get update && apt-get install unzip -y && \
unzip -j -d /usr/local/bin /tmp/consul-template.zip
EXPOSE 8080 9995 9996
VOLUME /templates
CMD ["/bin/start.sh"]
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Consul Templateのテンプレートはservice.ctmplです。9995と9996はZeppelinサーバーが起動しているamb1
ノードにプロキシーします。9996ポートはWebSocket用にヘッダーも追加します。8080ポートはAmb Serverコンテナが起動しているamb-server
ノードにプロキシーします。
server {
listen 9995;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://{{with node "amb1"}}{{.Node.Address}}{{end}}:9995;
}
}
server {
listen 9996;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://{{with node "amb1"}}{{.Node.Address}}{{end}}:9996;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
server {
listen 8080;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://{{with node "amb-server"}}{{.Node.Address}}{{end}}:8080;
}
}
forkしたリポジトリをcloneしてDockerイメージをビルドします。
$ git clone https://github.com/masato/docker-nginx-consul.git
$ cd docker-nginx-consul
$ docker build -t nginx-consul .
--dns
と--dns-search
フラグをつけてNginxのコンテナを起動します。--dns
フラグの順番はDockerホスト、Google DNSの前にConsulコンテナのIPアドレスを指定するとNginxコンテナの/etc/resolv.conf
は以下のようになります。
search service.consul
nameserver 172.17.0.2
nameserver 172.17.0.1
nameserver 8.8.8.8
Ambari Serverの管理画面で使う8080、ZeppelinのNotebookに使う9995と9996ポートをDockerホストにマップして外部から接続できるようにします。
$ AMB_CONSUL=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" amb-consul)
$ echo $AMB_CONSUL
172.17.0.2
$ docker run \
--name nginx \
-d \
-p 8080:8080 -p 9995:9995 -p 9996:9996 \
--volume $PWD/service.ctmpl:/templates/service.ctmpl \
--dns $AMB_CONSUL \
--dns 172.17.0.1 \
--dns 8.8.8.8 \
--dns-search service.consul \
nginx-consul
Nginxコンテナに入り名前解決ができるようになったか確認します。
$ docker exec -it nginx bash
$ echo $CONSUL_URL
consul:8500
$ ping -c 1 amb1
PING amb1.service.consul (172.17.0.4): 56 data bytes
64 bytes from 172.17.0.4: icmp_seq=0 ttl=64 time=0.049 ms
--- amb1.service.consul ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.049/0.049/0.049/0.000 ms
最後にpsコマンドで今回作成したDockerコンテナを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48df8cfdd49f nginx-consul "/bin/start.sh" 29 minutes ago Up 29 minutes 80/tcp, 0.0.0.0:8080->8080/tcp, 443/tcp, 0.0.0.0:9995-9996->9995-9996/tcp nginx
ce146ebf73f1 sequenceiq/ambari:2.1.2-v1 "/start-agent" 2 hours ago Up 2 hours 8080/tcp amb3
9c23d449cb83 sequenceiq/ambari:2.1.2-v1 "/start-agent" 2 hours ago Up 2 hours 8080/tcp amb2
162662822eb1 sequenceiq/ambari:2.1.2-v1 "/start-agent" 2 hours ago Up 2 hours 8080/tcp amb1
6729936f59f8 sequenceiq/ambari:2.1.2-v1 "/start-server" 2 hours ago Up 2 hours 8080/tcp amb-server
02ee7f29a74e sequenceiq/consul:v0.5.0-v6 "/bin/start -server -" 2 hours ago Up 2 hours 53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8301-8302/udp, 8500/tcp amb-consul
HDFS
Zeppelinの実行をする前にHDFSにrootユーザーのディレクトリを作成します。hdfs
ユーザーにスイッチして/user/root
ディレクトリを作成します。
$ docker exec -it amb1 bash
$ hadoop fs -ls /user
Found 4 items
drwxrwx--- - ambari-qa hdfs 0 2015-12-05 12:08 /user/ambari-qa
drwxr-xr-x - hcat hdfs 0 2015-12-05 12:09 /user/hcat
drwx------ - hive hdfs 0 2015-12-05 12:09 /user/hive
drwxrwxr-x - spark hdfs 0 2015-12-05 12:08 /user/spark
$ su hdfs
$ hadoop fs -mkdir /user/root
$ hadoop fs -chown root /user/root
コンポーネントの再起動
理由はよくわかりませんがmaster_1
グループのコンポーネントを再起動しないとZeppelinの実行に失敗してしまうようです。
Ambariの管理画面をパブリックIPアドレスからブラウザで開きます。
Hostsメニューからamb1.service.consul
を開いてRestart All Components
を実行します。
コンポーネントの再起動が終了するとようやくZeppelinが使えるようになります。9995ポートをブラウザで開きます。