はじめに
Apache Nifiを最近知った。
WebSocketが使えたり、簡単なMQサーバに出来たり、・・・とデータフローを視覚的にデザインしスケジュールし分散実行することができる。とても面白い。
スタンドアロンは簡単にできたものの、クラスタ構成を作るのに、ずいぶん手間取ったので、設定などの備忘録。
前提
- Dockerでやる(何台もAWSにEC2立てる金がもったいないので、便宜上です。)
- 3つのNifiノード(それぞれ、
nifi1
,nifi2
,nifi3
というホスト名) - 1つのZookeeperノード(
zookeeper
というホスト名) - NiFiにある内蔵Zookeeperは利用しない
(※実運用環境などではZookeeperも複数ノード用意すべきだが、そこは目的とは異なるので割愛)
手順
Dockerイメージの作成
結構ええ加減な作り方してます。使いやすくするには環境変数とかで、パラメータ調整できるようにすべきかもしれませんが、設定ファイルを直接マウントする形で進めます。
Apache Nifi
Dockerfile
FROM openjdk:11-jre
# nifiユーザの作成
RUN addgroup --system --gid 1001 nifi &&\
adduser --system --home /home/nifi --shell /bin/bash --uid 1001 --gid 1001 nifi &&\
cd /home/nifi
USER nifi
WORKDIR /home/nifi
# Apache Nifiのダウンロードと展開とパス通す
RUN wget ftp://ftp.riken.jp/net/apache/nifi/1.12.1/nifi-1.12.1-bin.tar.gz &&\
tar -xf nifi-1.12.1-bin.tar.gz
ENV NIFI_HOME=/home/nifi/nifi-1.12.1
ENV PATH=$PATH:$NIFI_HOME/bin
EXPOSE 8080
CMD ["nifi.sh","run"]
ビルドする
$ sudo docker build -t mynifi .
nifi.properties
Dockerイメージをビルド後、nifi.propertiesをHOST側へ持っていって編集。各ノード分用意する。
$ docker run --rm mynifi cat /home/nifi/nifi-1.12.1/conf/nifi.properties > nifi1.properties
$ vi nifi1.properties
変更するところだけ抜き出し
# (中略)
# ノードのホスト名と合わせる
nifi.remote.input.host=nifi1
# 適当なポートを設定
nifi.remote.input.socket=8090
# ノードのホスト名と合わせる
nifi.web.http.host=nifi1
# trueに変更
nifi.cluster.is.node=true
# ノードのホスト名と合わせる
nifi.cluster.node.address=nifi1
# 適当なポートを設定
nifi.cluster.node.protocol.port=8091
# ノードのリーダー選挙時間。デフォ5分が長くて待つのが面倒だったので、ちょっと短くした。
nifi.cluster.flow.election.max.wait.time=1 min
# 複数Zookeeperを指定する時はカンマ区切りで並べる
nifi.zookeeper.connect.string=zookeeper1:2181
state-management.xml
$ sudo docker run --rm mynifi cat /home/nifi/nifi-1.12.1/conf/state-management.xml > state-management.xml
$ vi state-management.xml
<!-- 中略 -->
<cluster-provider>
<id>zk-provider</id>
<class>org.apache.nifi.controller.state.providers.zookeeper.ZooKeeperStateProvider</class>
<!-- Zookeeperの宛先を設定 -->
<property name="Connect String">zookeeper1:2181</property>
<property name="Root Node">/nifi</property>
<property name="Session Timeout">10 seconds</property>
<property name="Access Control">Open</property>
</cluster-provider>
Apache Zookeeper
NiFiには内蔵Zookeeperがあり、nifi.state.management.embeded.zookeeper.start=true
とすればNiFiと同時にZookeeperも起動できるが、より実運用に近いイメージで外部のZookeeperを使うようにする。
Apache Kafkaなどで他に立てているZookeeperノードがあるなら、そちらに繋げても問題ないと思う。
Dockerfile
FROM openjdk:11-jre
RUN mkdir /home/zookeeper && mkdir /var/lib/zookeeper
WORKDIR /home/zookeeper
RUN wget https://downloads.apache.org/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz &&\
tar xzf apache-zookeeper-3.6.2-bin.tar.gz
ENV ZOOKEEPER_HOME=/home/zookeeper/apache-zookeeper-3.6.2-bin
ENV PATH=$PATH:$ZOOKEEPER_HOME/bin
COPY Start.sh /home/zookeeper/Start.sh
CMD ["./Start.sh"]
Start.sh
Zookeeperはmyid
ファイルをZookeeperのデータディレクトリ(/var/lib/zookeeper)に作成しておく必要がある。Dockerコンテナ実行時に環境変数で渡して、生成するようにシェルスクリプトを作成しておく。
# !/bin/bash
echo $ZOOKEEPER_MYID > /var/lib/zookeeper/myid
zkServer.sh start-foreground
zoo.cfg
Zookeeperのconfディレクトリにある、zoo_sample.cfg
ファイルをコピーして、zoo.cfg
という名前で編集する。
$ sudo docker build -t myzookeeper .
$ sudo docker run --rm myzookeeper cat /home/zookeeper/apache-zookeeper-3.6.2/conf/zoo_sample.cfg > zoo.cfg
$ vi zoo.cfg
# 最終行にでも以下を追記する。この1は先ほどのZOOKEEPER_MYIDと紐づく
server.1=zookeeper:2888:3888
Docker-Composeの作成
Dockerイメージの準備ができたので、Docker-Composeファイル作成する
docker-compose.yaml
version: '3'
services:
zookeeper:
build: ./zookeeper
image: "myzookeeper"
container_name: "zookeeper"
environment:
ZOOKEEPER_MYID: 1
volumes:
- ./zookeeper/zoo.cfg:/home/zookeeper/apache-zookeeper-3.6.2-bin/conf/zoo.cfg
nifi1:
build: ./nifi
image: "mynifi"
container_name: "nifi1"
ports:
- 8080:8080
volumes:
- ./nifi/nifi1.properties:/home/nifi/nifi-1.12.1/conf/nifi.properties
- ./nifi/state-management.xml:/home/nifi/nifi-1.12.1/conf/state-management.xml
nifi2:
build: ./nifi
image: "mynifi"
container_name: "nifi2"
ports:
- 8081:8080
volumes:
- ./nifi/nifi2.properties:/home/nifi/nifi-1.12.1/conf/nifi.properties
- ./nifi/state-management.xml:/home/nifi/nifi-1.12.1/conf/state-management.xml
nifi3:
build: ./nifi
image: "mynifi"
container_name: "nifi3"
ports:
- 8082:8080
volumes:
- ./nifi/nifi3.properties:/home/nifi/nifi-1.12.1/conf/nifi.properties
- ./nifi/state-management.xml:/home/nifi/nifi-1.12.1/conf/state-management.xml
出来上がったディレクトリ構成
+ /project_root
- docker-compose.yaml
+ /nifi
- Dockerfile
- nifi1.properties
- nifi2.properties
- nifi3.properteis
- state-mnagement.xml
+ /zookeeper
- Dockerfile
- zoo.cfg
- Start.sh
実行!
$ sudo docker-compose up -d
1分ほどリーダ選挙が行われるのでしばらく、待つ。docker exec
でApache NiFiの$NIFI_HOME/logs/nifi-app.log
をtail -f
して眺めてもいい。
http://localhost:8080/nifi
にブラウザでアクセス。クラスタマークが3/3になってれば成功。
右側のパン屑から、「Cluster」を選択し各ノードの状態をみる。Nifi2ノードがプライマリにNifi3ノードがコーディネータになった模様。