この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
ここ最近のDockerムーブメントの中で、キーワードとして良く取り上げられるようになったものの一つにCoreOSがあります。つい先日もGoogle Compute EngineがCoreOSを正式にサポートしたことが大きな話題となっていました。
CoreOSはLinuxディストリビューションの一つです。細かい説明については、外部サイトになりますがCoreOS 入門 - Qiitaという記事が非常に参考になりますのでご一読下さい。
ざっくり書くと、仮想化コンテナを大規模に運用することに特化したLinuxOSです。etcdという分散KVSとfleetという分散システムによるクラスタリング機能を標準的に持っています。
そこで今回は、Amazon EC2上でCoreOSを導入し、更にfleetを使ってDockerコンテナをクラスタリングして起動させる、ということをやってみました。
やったこと
CoreOSでEC2をLaunchする
まず最初に、etcdを分散KVSとして使用するためには、クラスタノードを管理するリーダーノードを構築する必要があります。しかし、CoreOSでその機能を代行しててくれるサービスがありますので、今回はそちらを使います。https://discovery.etcd.io/newにアクセスすると、一意のトークン番号を出力してくれるので、そのトークン番号をメモしておきます。
それではEC2のLaunchを行います。CoreOSのWebサイトにあるRunning CoreOS on EC2というページから、LaunchしたいAMIをクリックします。今回は東京リージョンのAMIを使いました。
すると通常のEC2のLaunch画面になります。各設定は通常通りで構いませんが、一点だけ、UserDataを以下のように設定します。これで今回の環境に必要なetcd、fleet、dockerが起動します。
#cloud-config
coreos:
etcd:
discovery: https://discovery.etcd.io/<払い出しされたトークン番号>
addr: $private_ipv4:4001
peer-addr: $private_ipv4:7001
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
- name: docker.service
command: start
セキュリティグループはこのような感じで、同一グループ内での4001/tcpと7001/tcpの通信を許可しておきます。
今回は全く同じ設定で、t1.microのEC2インスタンスを3台起動しました。起動したらSSHで接続します。このときに指定するユーザ名はcoreです。
$ ssh -i ./.ssh/key.pem -l core 54.178.212.XXX
CoreOS (beta)
$
さて、ではサービス状態を確認します。UserDataに記述した通り、etcd、fleet、dockerがサービス起動しています。
$ systemctl status etcd
● etcd.service - etcd
Loaded: loaded (/usr/lib64/systemd/system/etcd.service; disabled)
Drop-In: /run/systemd/system/etcd.service.d
└─10-oem.conf, 20-cloudinit.conf
Active: active (running) since Tue 2014-05-27 02:26:47 UTC; 4min 10s ago
Main PID: 3819 (etcd)
CGroup: /system.slice/etcd.service
└─3819 /usr/bin/etcd
$ systemctl status fleet
● fleet.service - fleet
Loaded: loaded (/usr/lib64/systemd/system/fleet.service; disabled)
Active: active (running) since Tue 2014-05-27 02:26:47 UTC; 4min 23s ago
Main PID: 3884 (fleet)
CGroup: /system.slice/fleet.service
└─3884 /usr/bin/fleet
$ systemctl status docker -l
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib64/systemd/system/docker.service; disabled)
Active: active (running) since Tue 2014-05-27 02:26:47 UTC; 4min 30s ago
Docs: http://docs.docker.io
Main PID: 3892 (docker)
CGroup: /system.slice/docker.service
└─3892 /usr/bin/docker -d -s=btrfs -r=false -H fd://
なお、etcdの起動オプションは以下のファイルに記述されていますので、上手く動作しない場合は確認してみると良いでしょう。
$ cat /run/systemd/system/etcd.service.d/20-cloudinit.conf
[Service]
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/<トークン番号>"
Environment="ETCD_ADDR=172.31.14.203:4001"
Environment="ETCD_PEER_ADDR=172.31.14.203:7001"
Environment="ETCD_NAME=2a8f721c072b4bc4a95b5a8e7afc59e7"
etcdの動作確認
ではまず、etcdがちゃんと分散KVSとして動作しているか確認してみましょう。
1台目のEC2で、以下コマンドを実行してメッセージをセットしてみます。
$ etcdctl set /message HelloWorld
HelloWorld
次に2台目のEC2で、以下コマンドを実行してメッセージをゲットしてみます。
$ etcdctl get /message
HelloWorld
ちゃんとゲット出来ましたね!
fleetでDockerコンテナをクラスタリングする
では本題です。今回登録するサービスはLaunching Containers with fleet - CoreOSを参考にしています。
まず、Apacheが起動するサービス定義ファイルを2つ作成します。
### 1つ目のサービス
$ sudo vi /etc/systemd/system/apache.1.service
[Unit]
Description=My Apache Frontend
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/docker run --name apache -p 80:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStop=/usr/bin/docker stop apache
[X-Fleet]
X-Conflicts=apache.*.service
### 2つ目のサービス
$ sudo vi /etc/systemd/system/apache.2.service
[Unit]
Description=My Apache Frontend
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/docker run --name apache -p 80:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStop=/usr/bin/docker stop apache
[X-Fleet]
X-Conflicts=apache.*.service
この2つのサービスをfleetに登録して起動します。
$ fleetctl start apache.1.service
Job apache.1.service scheduled to 98930432.../172.31.14.202
$ fleetctl start apache.2.service
Job apache.2.service scheduled to 61be18b7.../172.31.14.203
以下のコマンドでサービス状態を確認出来ます。3台のEC2のうち2台でサービスが起動していることが分かります。
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
apache.1.service loaded active running My Apache Frontend 98930432.../172.31.14.202
apache.2.service loaded active running My Apache Frontend 61be18b7.../172.31.14.203
このとき、別のEC2でも、同じようにサービス状態が確認出来ます。
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
apache.1.service loaded active running My Apache Frontend 98930432.../172.31.14.202
apache.2.service loaded active running My Apache Frontend 61be18b7.../172.31.14.203
実際にサービス起動対象となったEC2(上記例だと172.31.14.202と172.31.14.203)では、80/tcpがLISTENとなり、Webサーバが起動しています。
$ netstat -an | grep 80 | grep LISTEN
tcp6 0 0 :::80 :::* LISTEN
それではここで、サービス起動しているEC2を停止してみます。そうすると、サービスが起動していなかったEC2にサービスが移っています!
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
apache.1.service loaded active running My Apache Frontend 98930432.../172.31.14.202
apache.2.service loaded active running My Apache Frontend 3595aa64.../172.31.14.201
ちゃんとクラスタリング動作になっています!
なお、fleetに登録されたサービスを停止する場合はstopを使います。
$ fleetctl stop apache.1.service
Requested Job apache.1.service stop
またfleetからサービスを削除する場合はdestroyを使います。
$ fleetctl destroy apache.1.service
Destroyed Job apache.1.service
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
apache.2.service loaded active running My Apache Frontend 3595aa64.../172.31.14.201
まとめ
コンテナをデプロイしてサービスリリース、かつクラスタリングというのがこんなに簡易に出来るというのはとても便利ですね。etcdとfleetはなかなか奥が深そうなのでもっと調べたいです。