LoginSignup
7
7

More than 5 years have passed since last update.

Apache Zeppelinでデータ分析を分散処理する - Part 4: Ambari on Dockerのambari-functionsを使ってみる

Last updated at Posted at 2015-12-11

このシリーズ

ambari-functions

 Part 2ではAmbari on Dockersequenceiq/ambariイメージからAmbariクラスターをセットアップしました。ここで利用したambari-functionsにはDockerとAmbariの管理に便利な関数がいくつか定義されています。リポジトリからcloneしてambari-functionsを読み込むとamb-*関数が利用できるようになります。

$ git clone https://github.com/sequenceiq/docker-ambari.git
$ cd !$
$ source ambari-functions

Docker操作系

docker-ps

 docker psをラップしてAmbari管理に有用な情報を1行に見やすくしてくれます。コンテナ名、IPアドレス、Dockerイメージ名が一覧できます。

$ docker-ps
/nginx 172.17.0.7 nginx-consul <nil> {[/bin/start.sh]}
/amb3 172.17.0.6 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb2 172.17.0.5 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb1 172.17.0.4 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb-server 172.17.0.3 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-server]}
/amb-consul 172.17.0.2 sequenceiq/consul:v0.5.0-v6 {[/bin/start]} {[-server -bootstrap]}

 現在のZeppelinは以下のように5台のコンテナで構成されています。

  • Ambari Server x 1
  • Ambari Worker Node x 3
  • Consul x 1
  • Nginx x 1

docker-psa

 docker ps -aと同じです。起動していないコンテナも表示します。

$ docker-psa
/nginx 172.17.0.7 nginx-consul <nil> {[/bin/start.sh]}
/amb3 172.17.0.6 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb2 172.17.0.5 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb1 172.17.0.4 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-agent]}
/amb-server 172.17.0.3 sequenceiq/ambari:2.1.2-v1 <nil> {[/start-server]}
/amb-consul 172.17.0.2 sequenceiq/consul:v0.5.0-v6 {[/bin/start]} {[-server -bootstrap]}

Ambari操作系

amb-start-cluster

 Part 2amb-start-cluster関数を使いDockerコンテナを4つ作成しました。

$ amb-start-cluster 4

 関数の内部ではamb-start-firstを実行し最初の1ノードのAmbari Serverと追加でConsulのコンテナを作成します。今回の場合残り3ノードがワーカーノードになります。

amb-start-cluster
amb-start-cluster() {
  local act_cluster_size=$1
  : ${act_cluster_size:=$CLUSTER_SIZE}
  echo starting an ambari cluster with: $act_cluster_size nodes

  amb-start-first
  [ $act_cluster_size -gt 1 ] && for i in $(seq $((act_cluster_size - 1))); do
    amb-start-node $i
  done
}

amb-start-first

最初にConsulコンテナとAmbari Serverコンテナを作成します。

amb-start-first() {
  local dns_port_command=""
  if [[ "$EXPOSE_DNS" == "true" ]]; then
     dns_port_command="-p 53:$DNS_PORT/udp"
  fi
  run-command docker run -d $dns_port_command --name $CONSUL -h $CONSUL.service.consul $CONSUL_IMAGE -server -bootstrap
  sleep 5

  run-command docker run -d -e BRIDGE_IP=$(get-consul-ip) $DOCKER_OPTS --name $AMBARI_SERVER_NAME -h $AMBARI_SERVER_NAME.service.consul $IMAGE /start-server

  get-ambari-server-ip

  _consul-register-service $AMBARI_SERVER_NAME $AMBARI_SERVER_IP
  _consul-register-service ambari-8080 $AMBARI_SERVER_IP
}

amb-start-node

 この関数ではAmbariワーカーノードのコンテナを作成して、Consulにサービスとして登録しています。

amb-start-node
amb-start-node() {
  get-ambari-server-ip
  : ${AMBARI_SERVER_IP:?"AMBARI_SERVER_IP is needed"}
  NUMBER=${1:?"please give a <NUMBER> parameter it will be used as node<NUMBER>"}
  if [[ $# -eq 1 ]]; then
    MORE_OPTIONS="-d"
  else
    shift
    MORE_OPTIONS="$@"
  fi

  run-command docker run $MORE_OPTIONS -e BRIDGE_IP=$(get-consul-ip) $DOCKER_OPTS --name ${NODE_PREFIX}$NUMBER -h ${NODE_PREFIX}${NUMBER}.service.consul $IMAGE /start-agent

  _consul-register-service ${NODE_PREFIX}${NUMBER} $(get-host-ip ${NODE_PREFIX}$NUMBER)
}

 Ambariワーカーノードのコンテナで実行されるstart-agentBRIDGE_IP環境変数としてConsulコンテナのIPアドレスを渡しています。--net="host"フラグをつけてコンテナを起動した場合/etc/resolv.confがホストのファイルが使われるため、--dnsフラグが利用できません。ワークアラウンドとしてコンテナのコマンドでConsulをnameserverに指定して/etc/resolv.confを上書きしています。

start-agent
# --dns isn't available for: docker run --net=host
# sed -i /etc/resolf.conf fails:
# sed: cannot rename /etc/sedU9oCRy: Device or resource busy
# here comes the tempfile workaround ...
local-nameserver() {
  cat>/etc/resolv.conf<<EOF
nameserver $BRIDGE_IP
search service.consul node.dc1.consul
EOF
}

 amb-start-node関数を直接使い、現在3台あるワーカーノードに1台のコンテナを追加してみます。関数の中でAmbari ServerやConsulのIPアドレスを設定してくれます。NODE_PREFIXを引数の数字を追加した名前がコンテナ名になります。docker-ps関数で確認したように現在amb3まであるので4を追加します。

$ amb-start-node 4

 出力結果は以下です。ホスト名にamb4.service.consulが指定されました。

[DEBUG] docker run -d -e BRIDGE_IP=172.17.0.2 --name amb4 -h amb4.service.consul sequenceiq/ambari:2.1.2-v1 /start-agent
78353cc44a93693a331357ba15b08d4015f88d7fc509ce06ab39295a6972de3e

 Consulのサービスカタログにもamb4が登録されています。

$ amb-members | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   308  100   308    0     0   304k      0 --:--:-- --:--:-- --:--:--  300k
[
  {
    "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": "amb4",
    "Address": "172.17.0.8"
  }
]

amb-shell

 Part 2ではsequenceiq/ambariに入っている/tmp/ambari-shell.shスクリプトを直接実行してAmbari Shellを起動しました。今回はambari-functionsに入っているamb-shell関数を経由して使ってみます。どちらも同じ/tmp/ambari-shell.shを実行します。

amb-shell
_amb_run_shell() {
  COMMAND=$1
  : ${COMMAND:? required}
  get-ambari-server-ip
  NODES=$(docker inspect --format="{{.Config.Image}} {{.Name}}" $(docker ps -q)|grep $IMAGE|grep $NODE_PREFIX|wc -l|xargs)
  run-command docker run -it --rm -e EXPECTED_HOST_COUNT=$((NODES-1)) -e BLUEPRINT=$BLUEPRINT --link ${AMBARI_SERVER_NAME}:ambariserver --entrypoint /bin/sh $IMAGE -c $COMMAND
}

amb-shell() {
  _amb_run_shell /tmp/ambari-shell.sh
}

 Ambari Shellが起動しました。

[DEBUG] docker run -it --rm -e EXPECTED_HOST_COUNT=4 -e BLUEPRINT=--link amb-server:ambariserver --entrypoint /bin/sh sequenceiq/ambari:2.1.2-v1 -c /tmp/ambari-shell.sh
AMBARI_HOST=172.17.0.3
[DEBUG] waits for ambari server: 172.17.0.3 RUNNING ...

[DEBUG] waits until 4 hosts connected to server ...
[DEBUG] connected hosts: 4
    _                _                   _  ____   _            _  _
   / \    _ __ ___  | |__    __ _  _ __ (_)/ ___| | |__    ___ | || |
  / _ \  | '_ ` _ \ | '_ \  / _` || '__|| |\___ \ | '_ \  / _ \| || |
 / ___ \ | | | | | || |_) || (_| || |   | | ___) || | | ||  __/| || |
/_/   \_\|_| |_| |_||_.__/  \__,_||_|   |_||____/ |_| |_| \___||_||_|

Welcome to Ambari Shell. For command and param completion press TAB, for assistance type 'hint'.
ambari-shell>

 Ambariが利用可能なホストの一覧を表示します。

ambari-shell>host list
amb4.service.consul [HEALTHY] 172.17.0.8 centos6:x86_64
amb1.service.consul [HEALTHY] 172.17.0.4 centos6:x86_64
amb2.service.consul [HEALTHY] 172.17.0.5 centos6:x86_64
amb3.service.consul [HEALTHY] 172.17.0.6 centos6:x86_64

 残念ながらAmbari Shellを使ってノードの追加はできませんCloudbreakなどでも使っているambari-rest-clientAmbariClientMain.groovyを直接使うと可能らしいので試してみようと思います。

AmbariClientMain.groovy
package com.sequenceiq.ambari.main

import com.sequenceiq.ambari.client.AmbariClient

class AmbariClientMain {
  public static void main(String[] args) {
    def host = 'localhost'
    def port = '8080'
    if (args.size == 2) {
      host = args[0]
      port = args[1]
    }

    AmbariClient client = new AmbariClient(host, port)
    println "\n  clusterList: \n${client.showClusterList()}"
    println "\n  hostsList: \n${client.showHostList()}"
    println "\n  tasksList: \n${client.showTaskList()}"
    println "\n  serviceList: \n${client.showServiceList()}"
    println "\n  blueprintList: \n${client.showBlueprints()}"
    println "\n  clusterBlueprint: \n${client.showClusterBlueprint()}"

  }
}

Hadoop操作系

 WebHDFS REST API経由でHDFSの操作ができます。

amb-create-hdfs-dir

 HDFSにディレクトリを作成する関数です。

amb-create-hdfs-dir() {
  get-ambari-server-ip
  DIR=$1
  curl -X PUT "http://$AMBARI_SERVER_IP:50070/webhdfs/v1$DIR?user.name=hdfs&op=MKDIRS" > /dev/null 2>&1
}

 Ambariの設定からWebHDFSのチェックを確認します。

HDFS > Configs > Advanced > General > WebHDFS enabled

webhdfs-checked.png

 2.1. Getting Correct Configuration Values for Manually-Deployed ClustersのドキュメントにWebHDFSのURIの設定場所が書いてあります。

HDFS > Configs > Advanced > Advanced hdfs-site > dfs.namenode.http-address

webhdfs-setting.png

 この環境ではamb1.service.consul:50070がWebHDFSのURIに設定されていますが、amb-create-hdfs-dir関数の中でAMBARI_SERVER_IP環境変数にAmbari ServerのIPアドレスが指定されてしまいます。WebHDFSを使う場合は直接curlから実行します。

$ WEB_HDFS_IP=$(docker inspect --format="{{ .NetworkSettings.IPAddress }}" amb1)
$ curl -X PUT "http://$WEB_HDFS_IP:50070/webhdfs/v1/user/root/test?user.name=root&op=MKDIRS"
{"boolean":true}

 amb1コンテナに入ってHDFSにディレクトリが作成されたか確認してみます。

$ docker exec -it amb1 hadoop fs -ls
Found 3 items
drwxr-xr-x   - root hdfs          0 2015-12-10 08:45 .sparkStaging
-rw-r--r--   3 root hdfs    4610348 2015-12-10 08:49 bank-full.csv
drwxr-xr-x   - root hdfs          0 2015-12-11 18:50 test

 

amb-copy-to-hdfs

 WebHDFSのAPI経由でローカルのファイルをコピーできるようです。こちらも同様にAMBARI_SERVER_IP環境変数を使っているのでこの環境では利用できません。

amb-copy-to-hdfs() {
  get-ambari-server-ip
  FILE_PATH=${1:?"usage: <FILE_PATH> <NEW_FILE_NAME_ON_HDFS> <HDFS_PATH>"}
  FILE_NAME=${2:?"usage: <FILE_PATH> <NEW_FILE_NAME_ON_HDFS> <HDFS_PATH>"}
  DIR=${3:?"usage: <FILE_PATH> <NEW_FILE_NAME_ON_HDFS> <HDFS_PATH>"}
  amb-create-hdfs-dir $DIR
  DATANODE=$(curl -si -X PUT "http://$AMBARI_SERVER_IP:50070/webhdfs/v1$DIR/$FILE_NAME?user.name=hdfs&op=CREATE" |grep Location | sed "s/\..*//; s@.*http://@@")
  DATANODE_IP=$(get-host-ip $DATANODE)
  curl -T $FILE_PATH "http://$DATANODE_IP:50075/webhdfs/v1$DIR/$FILE_NAME?op=CREATE&user.name=hdfs&overwrite=true&namenoderpcaddress=$AMBARI_SERVER_IP:8020"
}

まとめ

 ambari-functionsを見てきました。Ambari ShellでできないことやHadoopのサービスとコンポーネントの構成によっては実行できない関数があります。Dockerやクラウドへのプロビジョンングを考えると同じDockerイメージを使うHadoopk管理ツールのCloudbreakを選択した方が良さそうです。Groovyambari-rest-clientがAmbariやCloudbreakで共通して利用されているクライアントライブラリでした。AmbariClientMain.groovyのMainメソッドも直接試してみようと思います。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7