GCP上でCoreOSクラスタを作ってコンテナ起動をしてみた

     - ネットワーク  


Google Cloud Platform(GCP)上でCoreOS + etcd +  fleet + docker でコンテナ起動まで行ったので紹介したいと思います。

CoreOSの起動

CoreOSは、コンテナの実行環境を構築することに特化したLinuxディストリビューションです。
なお、この記事ではCoreOS 815.0.0 を利用しており、GCPのCloud SDKがインストール済みであることを前提にしてます。

GCPでの起動

CoreOSでは、cloud-configというファイルで初期設定をします。
例えば以下のような内容です。

[code]
#cloud-config

coreos:
update:
reboot-strategy: off
etcd2:
discovery: <https://discovery.etcd.io/new?size=3 で取得した内容>
initial-advertise-peer-urls: http://$private_ipv4:2380
listen-peer-urls: http://$private_ipv4:2380
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001
fleet:
public_ip: $private_ipv4
etcd-servers: http://0.0.0.0:2379
units:
– name: etcd2.service
command: start
– name: fleet.service
command: start
– name: docker.service
command: start

[/code]

 

GCPでは、以下のようにインスタンスを起動します。

[bash]
$ gcloud compute instances create <ホスト名>
–image-project coreos-cloud
–image <最新CoreOSのイメージ名>
–boot-disk-size 200GB
–machine-type g1-small
–zone asia-east1-c
–metadata-from-file user-data=<cloud-configファイル>
[/bash]

CoreOSのイメージ名は以下のコマンドで取得してください。

[bash]
$ gcloud compute images list
[/bash]

インスタンス起動したら以下のコマンドでログインできます。

[bash]
gcloud compute ssh <ホスト名> –zone asia-east1-c
[/bash]

もしかすると、初回はprojectを設定するように促されるかもしれません。

また、GCPだとprojectに属するメンバーのssh鍵が予め登録されるみたいなのですが、登録されておらずログインできない場合はGCPコンソール画面からインスタンスへssh鍵を登録してください。

etcdクラスタ

etcd の状態

etcdクラスタの状態は以下のコマンドで確認できます

[bash]
$ etcdctl cluster-health
member 166142cf9d722824 is healthy: got healthy result from http://10.240.0.2:2379
member c6d31dfab88110de is healthy: got healthy result from http://10.240.0.3:2379
member df537aa4f51bc509 is healthy: got healthy result from http://10.240.0.4:2379
cluster is healthy
[/bash]

etcdのメンバーは以下のコマンドで確認できます。

[bash]
$ etcdctl member list
166142cf9d722824: name=0961a55a5c11f91b9604ab2e9e174b90 peerURLs=http://10.240.0.2:2380 clientURLs=http://10.240.0.2:2379,http://10.240.0.2:4001
c6d31dfab88110de: name=c7eeb70a321d94c46e03e5cc798a1ec0 peerURLs=http://10.240.0.3:2380 clientURLs=http://10.240.0.3:2379,http://10.240.0.3:4001
df537aa4f51bc509: name=0ddbef29e654d7f949a90256c0f92ece peerURLs=http://10.240.0.4:2380 clientURLs=http://10.240.0.4:2379,http://10.240.0.4:4001
[/bash]

bootstrap処理

ここでは、etcdクラスタの初期設定のことです。先ほどcloud-config内に以下のような内容を記述していました。

[code]
discovery: <https://discovery.etcd.io/new?size=3 で取得した内容>
[/code]

これは、

[code]
https://discovery.etcd.io/new?size=3
[/code]

のようにアクセスすると

[code]
https://discovery.etcd.io/729fd97bfee6537de4f26174d06c6582
[/code]

のように返ってくるので、これをcloud-configに記載します。

今回discovery:で https://discovery.etcd.io/ のサービスを利用しましたが、自前で別に立てたクラスタ用のetcdとは別のetcdで同じように作成することもできます。また、etcdのクラスタサイズとして”new=3″として作成していますので、4台目以降のetcdはプロキシモードで動作します。なお、3台etcdが参加するまでetcdクラスタとしては正常に動作しませんので注意が必要です。

上記とは別に静的にetcdクラスタを構成することもできます。1台目は以下のようにcloud-configへ記載します。

[code]
coreos:
etcd2:
name : master
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001
initial-cluster-token: testetcd
listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001
initial-advertise-peer-urls: http://$private_ipv4:2380
initial-cluster: master=http://$private_ipv4:2380
initial-cluster-state: new
[/code]

2台目以降は以下のように書くとetcdクラスタに参加できます。こちらもプロキシモードでの参加です。IPアドレスが事前にわかっていれば、プロキシモードで無くとも参加できます。

[code]
coreos:
etcd2:
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
advertise-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
initial-cluster: master=http://<masterのip>:2380
proxy: on
[/code]

メンバーの追加

etcdクラスタへメンバーを追加することが出来ます。etcdクラスタは、その利用している”Raft”というアルゴリズムがあまり大規模なクラスタには不向きであるらしく、5~9メンバーが適切なサイズと言われています。3メンバーだと1メンバーダウン時の挙動が不安定になることがあったため、5メンバーいると良いと思います。

メンバー追加は以下のように行います。

まず、追加するCoreOSで以下のコマンドを実行します

[bash]
$ cat /etc/machine-id
[/bash]

次に、既存のクラスタメンバーで以下のコマンドを実行します。

[bash]
$ etcdctl member add http://<追加するメンバーのIPアドレス>:2380
[/bash]

すると、以下のような出力がでます

[bash]
$ etcdctl member add 0b54ddfcc16f6595d15dd6fbb75da153 http://10.240.0.5:2380
Added member named 0b54ddfcc16f6595d15dd6fbb75da153 with ID 1aea5ee2f7aaddac to cluster
ETCD_NAME="0b54ddfcc16f6595d15dd6fbb75da153"
ETCD_INITIAL_CLUSTER="0961a55a5c11f91b9604ab2e9e174b90=http://10.240.0.2:2380,0b54ddfcc16f6595d15dd6fbb75da153=http://10.240.0.5:2380,c7eeb70a321d94c46e03e5cc798a1ec0=http://10.240.0.3:2380,0ddbef29e654d7f949a90256c0f92ece=http://10.240.0.4:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"
[/bash]

ここでの出力結果を追加するメンバーで利用します。

追加するメンバーの/etc/systemd/system/etcd2.service.d/50-join-cluster.confに以下の内容記載します。

[code]
[Service]
Environment="ETCD_NAME=0b54ddfcc16f6595d15dd6fbb75da153"
Environment="ETCD_INITIAL_CLUSTER=0961a55a5c11f91b9604ab2e9e174b90=http://10.240.0.2:2380,0b54ddfcc16f6595d15dd6fbb75da153=http://10.240.0.5:2380,c7eeb70a321d94c46e03e5cc798a1ec0=http://10.240.0.3:2380,0ddbef29e654d7f949a90256c0f92ece=http://10.240.0.4:2380"
Environment="ETCD_INITIAL_CLUSTER_STATE=existing"
Environment="ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379,http://0.0.0.0:4001"
Environment="ETCD_LISTEN_PEER_URLS=http://10.240.0.5:2380"
Environment="ETCD_ADVERTISE_CLIENT_URLS=http://10.240.0.5:2379,http://10.240.0.5:4001"
[/code]

[Service]からの上3行は、先ほどのコマンドの出力結果です。下3行はetcdクラスタ通信のための設定です。IPアドレスは追加するメンバーのIPアドレスを記載してください。

ファイルを書き込んだら、systemdからetcdを起動します。

[bash]
$ sudo systemctl start etcd2
[/bash]

起動したらクラスタの状態を見てみます。

[bash]
$ etcdctl cluster-health
member 166142cf9d722824 is healthy: got healthy result from http://10.240.0.2:2379
member 1aea5ee2f7aaddac is healthy: got healthy result from http://10.240.0.5:2379
member c6d31dfab88110de is healthy: got healthy result from http://10.240.0.3:2379
member df537aa4f51bc509 is healthy: got healthy result from http://10.240.0.4:2379
cluster is healthy
[/bash]

クラスタにメンバーを追加できていることがわかります。

メンバーの削除

メンバーを削除するときは、削除するメンバーのetcd上のIDを指定して以下のコマンドを実行します。

まず、IDを確認します。

[bash]
$ etcdctl member list
166142cf9d722824: name=0961a55a5c11f91b9604ab2e9e174b90 peerURLs=http://10.240.0.2:2380 clientURLs=http://10.240.0.2:2379,http://10.240.0.2:4001
1aea5ee2f7aaddac: name=0b54ddfcc16f6595d15dd6fbb75da153 peerURLs=http://10.240.0.5:2380 clientURLs=http://10.240.0.5:2379,http://10.240.0.5:4001
c6d31dfab88110de: name=c7eeb70a321d94c46e03e5cc798a1ec0 peerURLs=http://10.240.0.3:2380 clientURLs=http://10.240.0.3:2379,http://10.240.0.3:4001
df537aa4f51bc509: name=0ddbef29e654d7f949a90256c0f92ece peerURLs=http://10.240.0.4:2380 clientURLs=http://10.240.0.4:2379,http://10.240.0.4:4001
[/bash]

今回は、先ほどメンバーに追加したname=0b54ddfcc16f6595d15dd6fbb75da153をクラスタから削除しましょう。行先頭の文字列がIDです。

[bash]
$ etcdctl member remove
[/bash]

今回の例では以下のようになります

[bash]
$ etcdctl member remove 1aea5ee2f7aaddac
Removed member 1aea5ee2f7aaddac from cluster
[/bash]

上記のコマンドを実行すると、削除されたメンバーのetcdがそれを検知してetcdが停止します。クラスタに復帰するときは、再度メンバー追加を行う必要があります。再度参加させるときは、/var/lib/etcd2/member/を削除しておく必要があるので注意が必要です。

最後にクラスタメンバーが削除されたことを確認してみます。

[bash]
$ etcdctl member list
166142cf9d722824: name=0961a55a5c11f91b9604ab2e9e174b90 peerURLs=http://10.240.0.2:2380 clientURLs=http://10.240.0.2:2379,http://10.240.0.2:4001
c6d31dfab88110de: name=c7eeb70a321d94c46e03e5cc798a1ec0 peerURLs=http://10.240.0.3:2380 clientURLs=http://10.240.0.3:2379,http://10.240.0.3:4001
df537aa4f51bc509: name=0ddbef
[/bash]

 

コンテナ起動

etcdクラスタも動いたところで、dockerコンテナを動かしてみたいと思います。今回は、コンテナとしてmackerel-agentを動かしてみたいと思います。

fleetを利用したコンテナ起動

まずは、fleetの管理下にあるマシンを見てみます

[bash]
$ fleetctl list-machines
MACHINE         IP              METADATA
0961a55a…     10.240.0.2      –
0b54ddfc…     10.240.0.5      –
0ddbef29…     10.240.0.4      –
c7eeb70a…     10.240.0.3      –
[/bash]

先ほど作成したetcdクラスタの4台がいることがわかります。

[bash]
$ fleetctl list-unit-files
UNIT    HASH    DSTATE  STATE   TARGET
$ fleetctl list-units
UNIT    MACHINE ACTIVE  SUB
[/bash]

まだ、fleet上ではまだ何も動いていません。

それでは、fleetでコンテナを起動するために、unitファイルを作成します。fleet用のunitファイルは、systemd用のunitファイルに非常に似ています。以下のファイルmackerel-agent.serviceを 適当な場所に置きます。

[code]
[Unit]
Description=Mackerel Agent
After=docker.service
Requires=docker.service
[Service]
ExecStartPre=-/usr/bin/docker kill mackerel-agent
ExecStartPre=-/usr/bin/docker rm mackerel-agent
ExecStartPre=/usr/bin/docker pull mackerel/mackerel-agent
ExecStart=/usr/bin/sh -c "/usr/bin/docker run –log-driver=journald –privileged –name mackerel-agent -h %H -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/mackerel-agent/:/var/lib/mackerel-agent/ -v /proc/mounts:/host/proc/mounts:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -e apikey=/usr/bin/etcdctl get /mackerel/apikey mackerel/mackerel-agent"
ExecStop=/usr/bin/docker stop mackerel-agent
[X-Fleet]
Global=true
[/code]

最後の[X-Fleet]がfleetに対してどこでコンテナを動かすかを指示する内容になります。

[code]
[X-Fleet]
Global=true
[/code]

と書くことでetcdクラスタすべてのホストでコンテナを起動する事ができます。

今回mackerel-agent起動時にapikeyをetcd経由で取得しているので、

[code]
$ etcdctl set /mackerel/apikey <your-api-key>
[/code]

のようにapikeyを登録して置く必要があります。

etcdにapikeyを登録したら、以下のコマンドでfleetからコンテナを起動します

[bash]
$ fleetctl submit mackerel-agent.service
Unit mackerel-agent.service
$ fleetctl load mackerel-agent.service
Triggered global unit mackerel-agent.service load
$ fleetctl start mackerel-agent.service
Triggered global unit mackerel-agent.service start
[/bash]

最初にsubmitでfleetにファイルの内容を登録します。その後、loadstartでfleet登録した内容を起動します。コンテナの起動を確認してみます。

[bash]
$ fleetctl list-unit-files
UNIT                    HASH    DSTATE          STATE   TARGET
mackerel-agent.service  668bf63 launched        –       global
$ fleetctl list-units
UNIT                    MACHINE                 ACTIVE  SUB
mackerel-agent.service  0961a55a…/10.240.0.2  active  running
mackerel-agent.service  0b54ddfc…/10.240.0.5  active  running
mackerel-agent.service  0ddbef29…/10.240.0.4  active  running
mackerel-agent.service  c7eeb70a…/10.240.0.3  active  running
$ docker ps
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS               NAMES
4c03a9571b74        mackerel/mackerel-agent   "/startup.sh"       2 seconds ago       Up 1 seconds                            mackerel-agent
[/bash]

CoreOSが動いているすべてのホストでコンテナが起動していることが確認できました。

執筆時点のmackerel-agent 0.23.0では、CoreOS上のdockerの状態を取ることは出来ません。https://github.com/mackerelio/docker-mackerel-agent を少し細工をして利用する必要があります。

参考

CoreOSを使ってDockerコンテナを動かす——15分でできるCoreOSクラスタの作り方
Monitoring Docker with Mackerel


DACエンジニア採用情報

  関連記事

AWSのcredentialsを注意して取り扱う話

はじめに 最近ではオンプレミスでサーバを自前で用意する他に、クラウドサーバを使う機会が増えているかと思います。 弊社では、Amazon Web Services (AWS)を利用しており、多くの処理をAWS上で行っています。 AWSを利用していくにあたっては、アクセス情報(credentials)を …

Burpの使い方!

こんにちは、第二ソリューション開発部の谷口です。 受託開発の部署で開発を担当してます。 APIを扱う機会が多く、今回は通信内容を確認するためのローカルプロキシツール「Burp」について書かせて頂きます。 Burpとは Webアプリケーション開発時の検証において、Webサーバとブラウザ間の通信内容を確 …

no image
AnsibleでJunosのバージョン情報を取得

インフラ開発部 松田です。 今回は弊社で検証中のAnsibleについて書きます。 Ansibleを使ったサーバ構築の記事は最近よく見かけますが、私が触る機会の多いネットワーク機器も操作できる(Ansibleはエージェントレス)ということで、Ansible+NW機器について色々書いていきます。 初回は …