ECSで起動するDockerコンテナのルートボリュームの変更をスポットフリートを活用しながら変更してみる





今回、私が遭遇した問題としてECSが管理するDockerコンテナのルートボリュームはデフォルト約10GBがMAXであるが故にそれを超えてファイルの作成をしようとすると

```
No space left on device
```

といわれECSのタスクが途中で終了してしまいました。
ENTRYPOINTとして設定した独自のシェルで数Gのファイルを何個もおとしてくるようにしているんだから、そりゃおちるわ...(ため息)

解決しなければいけない課題
---

* ルートボリューム10GBの制限を取っ払ってあげないといけません。
* クラスターの設定で「プロビジョニングモデル」を選ぶといいインスタンスを安価に使えない...なんとかして低価格でいいインスタンスを使いたい


ざっくりとした解決方法
---

まず安価にコンテナインスタンスをたちあげるには「スポットリクエスト」もしくは「リザーブドインスタンス」を使うしか無いとおもいます。

**今回はスポットリクエストを使って、安価でいいインスタンスを手に入れたいと思います。**

そのスポットリクエストで立ち上がるインスタンス群に対して、

* dockerdの設定を変更
	* 10GB制限を取り払う
	* docker用のボリュームを追加
* ECSで立ち上げたクラスター傘下に入る
* dockerdの再起動

これらのことをスポットリクエストで立ち上がるインスタンスが起動時に実行できるように **ユーザーデータ** にシェルを書きたいと思います。



やってみる
---

### クラスター作成

まず、プロビジョニングモデルは **オンデマンドインスタンス** を選びます。

![スクリーンショット 2018-02-06 18.24.34.png](https://qiita-image-store.s3.amazonaws.com/0/18331/809ade28-c9e3-f4e4-6876-bf52071e4f23.png "スクリーンショット 2018-02-06 18.24.34.png")


それ以外を選ぶと、 **AutoScalingグループ** を作ってくれません。

スポットフリートでどのクラスターで管理するか指定するので、空のクラスターでもいいのですが、後々つくるのめんどくさそうだったので、とりあえずオンデマンドで。

このときつくったクラスタ名を覚えておいてください
例としてあげているクラスタ名は`autoscale-cluster`になります。


### スポットフリートでスポットインスタンスを立ち上げる

![スクリーンショット 2018-02-06 19.05.46.png](https://qiita-image-store.s3.amazonaws.com/0/18331/26ec56e3-ef1e-c1c6-c5e0-24ae78b3e320.png "スクリーンショット 2018-02-06 19.05.46.png")


まずAMIはECS対応のAMIを選択してください。
ECS対応AMIは、[ここ](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-optimized_AMI.html)から確認できます。

現時点（2018/02/07)では`amzn-ami-2017.09.g-amazon-ecs-optimized(ami-872c4ae1)`が最新です。

ネットワークやサブネットに関しては、クラスターで設定したネットワークと同じネットワークを設定します。
（ココらへんは適当でもいいと思いますが）



![スクリーンショット 2018-02-07 11.53.20.png](https://qiita-image-store.s3.amazonaws.com/0/18331/32cf596b-53d6-805d-d140-878f249d43b9.png "スクリーンショット 2018-02-07 11.53.20.png")

`/dev/xvda`はOS用のボリュームです。Dockerイメージが管理されるボリュームはクラスターで設定されたとき（デフォルトであれば、22GiB)のものが使われます。動きはバージョンによって異なるみたいなので、[公式ページ](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-ami-storage-config.html)を確認してください。

今回はdockerのためにEBSボリュームを追加しています。



![スクリーンショット 2018-02-07 16.42.31.png](https://qiita-image-store.s3.amazonaws.com/0/18331/53f2d55b-55db-20eb-9787-f70b31cbc8f5.png "スクリーンショット 2018-02-07 16.42.31.png")

セキュリティグループやキーペアは作業する環境に合わせて設定してください。


IAMインスタンスプロフィールには、

* AmazonEC2ContainerServiceforEC2Role 
* AmazonEC2ContainerRegistryReadOnly 

のポリシーがアタッチされたIAMを使っています。
これらが無いとECSに参加できないはずです。


ここが今回の問題を解決するユーザーデータへの記述内容になります。



**ユーザーデータに記述したシェル**

```
#!/bin/bash
echo ECS_CLUSTER=autoscale-cluster >> /etc/ecs/ecs.config
echo ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION=5m >> /etc/ecs/ecs.config
echo 'OPTIONS="${OPTIONS} --storage-opt dm.basesize=30G"' >> /etc/sysconfig/docker

sudo vgextend docker /dev/xvdba
sudo lvextend -L+30G /dev/docker/docker-pool
sudo service docker restart
```

やっていることは

1. 指定クラスターへの参加
2. コンテナのクリーナップを短く。
	* https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/automated_image_cleanup.html
3. 10GB制限を30GB制限まで拡張
4. dockerのボリュームはデフォルト22GiBなので、新たに追加した前述のEBSボリュームを追加してあげる
5. dockerdの再起動

となります。


このあとのスポット価格、いつまで継続するかなどの設定はご自身の環境に合わせて設定してください。

確認
---

#### ECSの設定確認

```
cat /etc/ecs/ecs.config
```

これを実行すると以下の結果が得られると思います。

```
ECS_CLUSTER=autoscale-cluster
ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION=5m
```

#### dockerdの設定確認

```
ps aux | grep dockerd
```

を実行すると

```
root      3389  0.6  0.1 1109744 56948 ?       Sl   04:06   1:37 /usr/bin/dockerd --default-ulimit nofile=1024:4096 --storage-opt dm.basesize=30G --storage-driver devicemapper --storage-opt dm.thinpooldev=/dev/mapper/docker-docker--pool --storage-opt dm.use_deferred_removal=true --storage-opt dm.use_deferred_deletion=true --storage-opt dm.fs=ext4 --storage-opt dm.use_deferred_deletion=true
```

のような結果が得られると思います。
`dm.basesize=30G` がちゃんと考慮されてますね。

実際に起動しているdockerに入り、dfコマンドを打つなどしたら

![スクリーンショット 2018-02-07 17.24.15.png](https://qiita-image-store.s3.amazonaws.com/0/18331/eee5ccf0-db78-18eb-4930-f7dc6bb2b274.png "スクリーンショット 2018-02-07 17.24.15.png")

30GBに拡張されているのがわかりますね。

お世話になったサイト
---

* https://dev.classmethod.jp/cloud/aws/ecs-root-volume-size/