CoreOSをAmazon EC2上で動かす方法


基本的には[公式サイト](https://coreos.com/docs/running-coreos/cloud-providers/ec2/)の記述の通りやればOKです。

ご丁寧にCloudFormationのテンプレートまで用意されているのでそれを使えば、セキュリティグループやAutoScalingの設定も含めてやってくれます。(ソースは[こちら](https://s3.amazonaws.com/coreos.com/dist/aws/coreos-stable-hvm.template)を参照)

ただ、いくつか修正した方がよい箇所がありますが、それについては後述します。
とりあえずただ起動してみたい、という場合は、以下の手順通りでOKです。

## 起動する!!

上では色々書いてますが、まずは早速このテンプレートを使って起動しましょう。CoreOSのWebサイトで`Launch Stack`ボタンをクリックすると、以下のようにマネジメントコンソールが起動されます(ログイン画面が間にはいることもあります)。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/43246/a5a6740b-8772-666c-19c8-6b0b352fe81d.png "01.png")

既に利用するCloudFormationのテンプレートはURLの箇所に指定済なので、`Next`ボタンをクリックします。すると以下のような画面が表示されます。

![02.png](https://qiita-image-store.s3.amazonaws.com/0/43246/639b9e79-df6a-707d-9932-ca6c03b71a5d.png "02.png")

図のようにいくつかのパラメータが聞かれます。それぞれの役割は以下の通りなので適宜入力してください。

* AdvertisedIPAddress etcdの設定に使います。通常はprivateでOK
* AllowSSHFrom SSH接続を許可するアドレスをCIDR形式で記入する。Public Subnetに配置するのであれば0.0.0.0/0は避けること
* ClusterSize 立ち上げるインスタンスの台数
* DiscoveryURL etcdのdiscovery用のエンドポイント。自分で用意しても良いし、https://discovery.etcd.io/new を使っても良い。公開サービスを使う場合はトークンの扱いに気をつけるとともに、アウトバウンドでエンドポイントに繋がるようになっているのを確認すること
* InstanceType 利用するインスタンスタイプ。好きなものを記入
* KeyPair インスタンスに接続する際に利用するキーペア。これがないとインスタンスにログインできない

終わったら、ページ下部の`Next`をクリックします。次のような画面が表示されます。

![03.png](https://qiita-image-store.s3.amazonaws.com/0/43246/9edafb7b-4a89-e2b5-0c63-074c4da744a6.png "03.png")

ここでは追加のタグの設定やSNSトピックの設定などができるのですが、割愛して`Next`をクリックし、先に進みましょう。

確認画面が表示されます。入力内容に間違いがないことを確認してください。

![04.png](https://qiita-image-store.s3.amazonaws.com/0/43246/9cd3cc4a-aa4e-b923-4082-67a60c5bdb14.png "04.png")

問題なければページ下部の`Create`をクリックします。CloudFormationのイベントログのページに移動しますので、`CREATE_COMPLETE`という表示がされるまで、寿司でも食べながら待ってください。3カンくらいは食べれます。

![05.png](https://qiita-image-store.s3.amazonaws.com/0/43246/7930cbb7-6a56-0800-fef7-b75935129ead.png "05.png")

## インスタンスへのログイン

インスタンスへのログインは、普通に、`ssh -i 秘密鍵のパス core@IPアドレス`でOKです。

ログインしていつものようにマシンの一覧を表示してみましょう(なお、4001番ポートはCloudFormationのテンプレートを見れば分かる通り外部には公開されていないので、自分の端末からは繋がりません)。

```
core@ip-172-31-24-49 ~ $ fleetctl list-machines
MACHINE		IP		METADATA
32ecb0ef...	172.31.24.48	-
5c76e4c4...	172.31.24.49	-
bfd08b19...	172.31.10.102	-
```

次にユニットの確認。当然ながら何も登録されてないですね。

```
core@ip-172-31-24-49 ~ $ fleetctl list-units
UNIT	MACHINE	ACTIVE	SUB
```

ということで、試しに以下のようなUnitファイル(web@.service)を用意します。これはapacheを動かしているだけのものです。

```
[Unit]
Description=Apache Frontend
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run -rm --name apache%i -p 80:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStop=/usr/bin/docker stop apache%i

[X-Fleet]
Conflicts=web@*.service
```

で登録します。

```
fleetctl submit web@.service
```

では、起動しましょう。

```
fleetctl start web@{1,2,3}.service
```

結果、以下のように表示されればOKです。

```
Unit web@1.service launched on bfd08b19.../172.31.10.102
Unit web@2.service launched on 32ecb0ef.../172.31.24.48
Unit web@3.service launched on 5c76e4c4.../172.31.24.49
```

とりあえず動作を確認したい場合は、一端インスタンスのセキュリティグループで80/tcpを通すようにすればOKですが、きちんとやるのであれば、ELBを使います。
ただ、ELBに手で登録したり外したりしてたのでは何やっているのか全く分からないので、ここも自動化しましょう。

## ELBへの自動登録・解除

まず、先ほど起動したクラスタと同じリージョン(かつ同じVPC)にElastic Load Balancingを1つ起動します(今回はcoreelbという名前にしました)。さらにCloudFormationで作られたセキュリティグループで、このELBからインスタンスへのアクセスが可能になるようにルールを追加してください。

次に、先ほど起動したapacheを死活監視して、ELBに登録したり、追加したりするためのユニットを追加します。

ファイル名は、`presence@.service`として、中身は以下のようにします。

```
[Unit]
Description=apache presence service
BindsTo=web@%i.service

[Service]
ExecStartPre=-/usr/bin/docker kill apache-presence-%i
ExecStartPre=-/usr/bin/docker rm apache-presence-%i
ExecStart=/usr/bin/docker run --rm --name apache-presence-%i -e AWS_ACCESS_KEY=[自分のAWSアクセスキー] -e AWS_SECRET_KEY=[自分のシークレットキー] -e AWS_REGION=ap-northeast-1 -e ELB_NAME=[設定するELB] quay.io/coreos/elb-presence
ExecStop=/usr/bin/docker stop apache-presence-%i

[X-Fleet]
MachineOf=web@%i.service
```

出来たらUnitを追加して起動します。

```
fleetctl submit presence@.service
fleetctl start presence@{1,2,3}.service
```

現時点では以下のようになっているはずです。

```
core@ip-172-31-24-49 ~ $ fleetctl list-units
UNIT			MACHINE				ACTIVE	SUB
presence@1.service	bfd08b19.../172.31.10.102	active	running
presence@2.service	32ecb0ef.../172.31.24.48	active	running
presence@3.service	5c76e4c4.../172.31.24.49	active	running
web@1.service		bfd08b19.../172.31.10.102	active	running
web@2.service		32ecb0ef.../172.31.24.48	active	running
web@3.service		5c76e4c4.../172.31.24.49	active	running
```


これでしばらく待っているとELBにインスタンスが追加されると思います(インスタンス側のセキュリティグループがELBからの接続を受け付けられるようにしておいてください)。

あとは、もう好きにUnitを更新するなり、自分でDockerのイメージを作って自由に遊ぶなりなんなりどうぞ。Serviceを落とせば自動でELBから外され、Serviceをスタートすると自動でELBにすぐ追加されるのがわかると思います(web@.serviceとpresence@.serviceが連動して動きます)。

## アクセスキーとシークレットキーの取り扱い

上でELBの設定を弄くるために、アクセスキーとシークレットキーをベタで書いてますが、これはマズイやり方です。AWSの場合、EC2からAPIを呼び出したい場合は、インスタンスにIAM Roleを設定します。これはご存じの通り、一度起動したインスタンスには設定できず、起動時に設定することになります。

大本のCloudFormationのテンプレートがそうなってしまっているからなので、いっそのことテンプレートを修正しておくとよいかと思います。

## CloudFormationのテンプレートの修正

ということでテンプレートを修正します。主な修正点は、

* 死活監視用のUnitではbotoでAWSのAPIを呼んでいるので、アクセスキーとシークレットキーの埋め込みを避けるために、IAM RoleもCloudFormationの中で作る
* 元々のテンプレートでは起動するVPCやサブネットを指定できないので、自分で好きなところに起動できるようにする
* ついでにELBも作る

スクリプトは[こちら](https://github.com/ryuzee/coreos-aws-cloudformation-sample/blob/master/coreos-stable.template)

## 最後に

[ECS](http://aws.amazon.com/jp/ecs/)使え!!って話もありますね。。