これまではSerfの基本的な使い方や、
Dockerコンテナ群をSerfで管理する方法
DockerはLinuxコンテナを簡単に起動・Dockerfileと言う設定ファイルを使った構成管理の自動化などの利点があります。
コンテナ管理問題を解決するSerf
コンテナを多く立ちあげた時に発生するのは、docker execコマンドを実行することにより、
docker execは、docker execを実行するのは手間になりがちです。また、
この問題を解決するために、
そこで登場するのが、
- メンバー管理の自動化
Serfがコンテナのホスト名とIPアドレスを自動的に管理するため、
コンテナの起動・ 停止時に人手で管理する必要がありません。 - タグ機能でコンテナの役割を明確化
Serfはエージェントにタグを動的に付与でき、
コンテナの役割や管理担当者の情報を動的に付与できます。 - イベントハンドラでコンテナ内の一斉操作
コンテナにログインすることなく任意のコマンドを一斉に実行できます。開発環境やテスト環境を問わず、
有用な機能です。
いずれも手動でも行えますが、
図1は1つのホスト上で複数のコンテナを管理するイメージです。この図ではホストOS側・172.で固定されているため、172.にしておくと便利です。
自動的にSerfクラスタを構成するDockerfile
Dockerでコンテナを起動・bashを実行させてみます。
前提として、serf agent等のコマンドで起動しているものとします。この時、172.をバインドしている必要がありますserf agent -bind=172.として明示することもできます)。
自動的にSerfを起動するためにはDockerfileを用います。Dockerには、Dockerfileという名称のテキスト形式のファイルを作成し、
作業用のディレクトリを作成し、Dockerfileを作成します。内容はcentosのコンテナイメージの使用を明示し、wgetとunzipパッケージの取得を行っています。それからserfのアーカイブを取得・
FROM centos
RUN yum -y install wget unzip
RUN wget -O 0.6.4_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.4_linux_amd64.zip
RUN unzip 0.6.4_linux_amd64.zip
RUN cp ./serf /usr/bin/serf
ENTRYPOINT ["serf"]
CMD ["agent","-join=172.17.42.1","-event-handler=query:ssh=/bin/sh"]
※ 実際のDockerfileは、
次に、Dockerfileを元にdocker buildコマンドを使い、serf-centosというタグを付けていますが、<ユーザ名>/serf-centosなど、
# docker build -t serf-centos . Sending build context to Docker daemon 3.31 MB Sending build context to Docker daemon Step 0 : FROM centos ---> 9dbcac75201e Step 1 : RUN yum -y install wget unzip ---> Using cache ---> 7d35b2710d1d Step 2 : RUN wget -O 0.6.4_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.4_linux_amd64.zip ---> Using cache ---> 6f943b9c59cd (省略) Successfully built 5aa497793ab2
画面上にSuccessfullyと表示されれば、serf-centosという名称のコンテナイメージが作成できました。次は、docker runコマンドを使い、
# docker run -d serf-centos 175dbd9034122edff3af72804c1a8cc8e968ebed5d53c25259e375f82b4b40f4
コンテナが正常に稼働しているかどうかは、docker psコマンドで確認することができます。ここでは自動的にSerfクラスタを形成しているか確認するためにserf membersコマンドを実行してみます。正常であれば、
# serf members dev2.pocketstudio.net 172.17.42.1:7946 alive 3f42611e8fe7 172.17.0.10:7946 alive
同時に複数台の起動も試してみましょう。先ほど同様docker run -d serf-centosを数回実行した後、serf membersコマンドを実行します。次のように、
# serf members dev2.pocketstudio.net 172.17.42.1:7946 alive 3f42611e8fe7 172.17.0.10:7946 alive 0f8a23cdc921 172.17.0.11:7946 alive 4bbedca26a70 172.17.0.14:7946 alive 175dbd903412 172.17.0.15:7946 alive
コンテナ内をserf queryを使って同時操作
Serfのイベントハンドラsshを使い、serf queryコマンドを使用します。任意のコマンドを実行するにはserf eventまたはserf queryを使う方法がありますが、query形式を定義していました。結果を知る必要がなければevent形式でも構いません。
例として、serf ssh uptimeを実行してみます。正常に処理されると、uptimeが実行され、sshが発生すると、/bin/と引数としてのコマンドを実行した結果が表示されます。
# serf query ssh uptime Query 'ssh' dispatched Ack from 'dev2.pocketstudio.net' Ack from '0f8a23cdc921' Response from '0f8a23cdc921': 09:11:04 up 2:23, 0 users, load average: 0.17, 0.06, 0.02 Ack from '4bbedca26a70' Response from '4bbedca26a70': 09:11:04 up 2:23, 0 users, load average: 0.17, 0.06, 0.02 Total Acks: 3 Total Responses: 2
ほかにもpsコマンドでプロセスの状況を知ることもできます。
# serf query ssh "ps ax" Query 'ssh' dispatched Ack from 'dev2.pocketstudio.net' Ack from '4bbedca26a70' Response from '4bbedca26a70': PID TTY STAT TIME COMMAND 1 ? Ssl 0:01 serf agent -join=172.17.42.1 -event-handler=query:sh=/bin/sh 19 ? S 0:00 /bin/sh 20 ? R 0:00 ps ax Ack from '175dbd903412' Response from '175dbd903412': PID TTY STAT TIME COMMAND 1 ? Ssl 0:00 serf agent -join=172.17.42.1 -event-handler=query:sh=/bin/sh 16 ? S 0:00 /bin/sh 17 ? R 0:00 ps ax Total Acks: 5
これはあくまで一例ですので、catやyumコマンドだけでなく、/bin/を指定しました。しかしroot権限で何でも実行できてしまうため、
メンバー管理とタグ
Serfはエージェントのメンバー毎にタグを付ける機能があります。コンテナを複数起動している場合、serf membersコマンドで参照できるだけではなく、
タグを指定するにはserf tags -set <key>=<value>の形式でコマンドを実行します。コマンドの実行は、role=adminというタグを設定し、serf membersコマンドで見た結果です。
$ serf tags -set role=admin Successfully updated agent tags $ serf members dev2.pocketstudio.net 172.17.42.1:7946 alive role=admin 3f42611e8fe7 172.17.0.10:7946 alive 0f8a23cdc921 172.17.0.11:7946 alive
タグの削除はserf tag -delete <key>の形式で指定します。また、
Serfの詳細設定
Serfエージェントの様々な設定は、serfコマンドの引数で指定する方法と、
外部の設定ファイルを使う方法
Serfを同じ設定で起動・
{
"node_name": "dev01", # ノード名称を「dev01」
"tags": {
"role": "develop" # タグ「role=develop」
},
"interface": "eth1", # インターフェースを「eth1」
"discover": "serf-cluster", # オート・ディスカバリで「serf-cluster」を検索
"event_handlers": [
"ssh=/bin/bash" # イベントハンドラ「ssh=/bin/bash」を定義
]
}このJSON形式のファイルを作成した後、-config-file=オプションを指定します。
$ serf agent -confg-file=/etc/serf.json
JSON形式の場合は、kill -1 <serfのPID>を実行します。
Serfの便利オプション
Serfには様々なオプションが用意されています。ここでは、
node_name (-node) Serfクラスタ内の自分のノード名称を指定するもので、
serf membersコマンド実行時に表示されます。省略時は自分自身のホスト名が利用されます。なお、Serfクラスタ内でノード名称の重複はできないため、 設定ファイルをコピーして流用する時は注意が必要です。 - 設定ファイル:"node_
name": "dev01" - コマンドライン:serf agent -node=dev01
- 設定ファイル:"node_
bind(-bind) Serfエージェントが内部の通信で利用するIPアドレスを指定します。通常は指定する必要はありませんが、
サーバが複数のインターフェースを持っている場合、 どのIPアドレスを使うか明示するために使います。 - 設定ファイル:"bind": "192.
168. 39. 3" - コマンドライン:serf agent -bind=192.
168. 39. 3
- 設定ファイル:"bind": "192.
interface(-iface) Serfが利用する標準インターフェース名を指定します。複数のインターフェースを持っている環境で多用します。
- 設定ファイル:"interface": "eth1"
- コマンドライン:serf agent -iface=eth1
badvertise(-advertise) Serfクラスタ内の自分のIPアドレスを指定します。
bindの指定に似ていますが、こちらはインターフェースが複数のIPアドレスを持っている場合や、 NATの環境で明示したい時に使います。 - 設定ファイル:"advertise": "192.
168. 39. 1" - コマンドライン:serf agent -advertise=192.
168. 39. 1
- 設定ファイル:"advertise": "192.
discover(-discover) マルチキャストDNS
(mDNS) がネットワーク内で利用可能な場合にオプションを指定すると、 serf joinで参加するクラスタを明示しなくても自動的にクラスタを形成します。この引数として指定したクラスタ名と一致する場合に自動参加します。- 設定ファイル:"discover": "development"
- コマンドライン:serf agent -discover=development
encrypt_key (-encrypt) Serfで暗号化したネットワーク通信を行う場合に使う秘密鍵を指定します。予め
serf keygenコマンドで生成した文字列を引数として使います。暗号化してクラスタを形成すると、ここで指定した鍵が一致しないとクラスタに参加できません。 - 設定ファイル:"encrypt_
key": "<文字列>" - コマンドライン:serf agent -encrypt=<文字列>
- 設定ファイル:"encrypt_
log_level (-log-level) Serfエージェント起動後に標準出力されるログの粒度を指定します。種類には情報が多い順にtrace、
debug、 info、 warn、 errを選べます。デフォルトはinfoです。 - 設定ファイル: "log_
level": "debug" - コマンドライン: serf agent -log-level=debug
- 設定ファイル: "log_
start_join (-join) Serfエージェント起動時、
どのSerfエージェントと通信を開始してクラスタを形成するか明示します。 - 設定ファイル:"start_
join": "192. 168. 39. 1" - コマンドライン:serf agent -join=192.
168. 39. 1
- 設定ファイル:"start_
その他にも設定用のオプションがあります。詳細はSerfのConfigurationページが参考になります。
まとめ
Dockerを使ったコンテナ環境に対しても、
