Fargateで、オートスケールする様子を観察してみる

## はじめに
本POSTは、Fargate Advent Calendarの12/21分の記事になります。

### 当社の状況
すでに、皆様もご存知だった通り。種類も、数も、質も、圧倒的な各種の魅力的なサービスが目白押しだったRe:Invent 2017でした。私の携わっているサービスでは、IaaSの上にアプリケーションをデプロイした形で展開しております。これはこれで、キャパシティプランニングの上で、対応する部分では問題がない、ということでこの構成を維持しておりますが、近年の流れは追わねばならぬ、ということでコンテナやサーバレスなどの導入の検討を進めております。（すでに開発環境はコンテナ化が完了していますが、productionへの投入は慎重になるべき、と考えています）

### 何を導入すべきか
コンテナとサーバレス、どちらかだろうなあ・・・と思っていたのですが、とあるイベントにてコンテナのサービス投入に関する話を聞く機会がありまして、その方のお話では「とあるAPIサービスで短期間にアクセスがスケールし、かつ予測が難しいところにECSを使っている」というまさに我々にとってうってつけのシチュエーションだったので、実際どうか訪ねたところ

「結局ECSのためのEC2を起動する必要があり、そのスケールに依存してしまう。EC2が足りなくなるとそれを投入することになるが、結局それは普通にインスタンスをスピンインするのと同じくらいの時間がかかるので、余力を持って運用しておくしかなく、その場合は起動しているインスタンス分課金があるため、結局コンテナを詰め込んでる（笑）」

とのことで、なるほどまだまだ色々あるのだなーと思っていたのでした。

### そしてre:Invent 2017
そんな課題があるんだなと思い赴いたre:Inventで今回のFargateは、事前に聞いたその不満が、全く払拭されるアップデート「Fargate」がリリースされ、よくまあこんなに根本的な解決策を出してくるなあ・・・と関心すると同時に、俄然このサービスを試してみたくなり、今回advent calendarに参加することとしました。

## 試すこと
- EC2の管理がいらない、とあるがどれほど実用的にそれが可能になっているのか
- どうやってオートスケールの設定するのか
- オートスケールの際にどれくらいでコンテナがあがってきてくれるか
- その他

## 構成
このような構成で試しました。

(internet) -> ALB -> ECS(Fargate) <- Docker Hub <-Github

## 用意したアプリケーション
個人的趣味によりpythonをチョイス。python CGIアプリケーションとしました。

```code:digest.py
#!/usr/bin/python

import os
import hashlib
import urlparse

if 'QUERY_STRING' in os.environ:
    qs = urlparse.parse_qs(os.environ['QUERY_STRING'])
else:
    qs = {}

st = qs['str'][0]
hash_md5 = hashlib.md5()
hash_sha256 = hashlib.sha256()
hash_sha512 = hashlib.sha512()


if st is None:
    print 'Status: 400 Bad Request'
else:
    hash_md5.update(st)
    hash_sha256.update(st)
    hash_sha512.update(st)
    for i in range(10000):
        hash_md5.update(hash_md5.hexdigest())
        hash_sha256.update(hash_sha256.hexdigest())
        hash_sha512.update(hash_sha512.hexdigest())

print('Content-type: text/plain; charset=UTF-8\r\n')
print(hash_md5.hexdigest())
print(hash_sha256.hexdigest())
print(hash_sha512.hexdigest())
```

適度に負荷がかかるように、query stringに指定した値を持ってきて、それぞれ1万回ハッシュを繰り返し取り、その結果を返すというコードを用意しました。

## コンテナ構成
OS:CentOS 6.7
httpd:apache 2.4

チューンしたものではないのは、単純に時間がなかったので、個人的に慣れているものを使いたかったため・・・です。

## Docker Hub + GitHub
Dockerfile及び上記コード、apache設定などをgithubレポジトリに公開し、そちらを使って、DockerHubを作成しています。
どちらも以下においております。

まだDocker HubとAmazon ECRにしか対応していないようなので、こちらは従うしかないですね。

https://github.com/heatsea/adventcalendar-2018-docker
https://hub.docker.com/r/heatsea/adventcalendar-2018-docker/tags/

## ECS(Fargate)の設定
### タスク

![Screen Shot 2017-12-22 at 5.40.54.png](https://qiita-image-store.s3.amazonaws.com/0/27161/e5de765c-69d4-d4b0-f7e6-ae0249fdb1ae.png "Screen Shot 2017-12-22 at 5.40.54.png")


標準設定ですね。Fargateにしています。

#### コンテナ
![Screen Shot 2017-12-22 at 5.41.21.png](https://qiita-image-store.s3.amazonaws.com/0/27161/8e009482-d189-aa30-e238-201c7382e1f5.png "Screen Shot 2017-12-22 at 5.41.21.png")


エントリポイントに、apacheの起動コマンドを書いてます

### クラスター
#### サービス
![Screen Shot 2017-12-22 at 5.52.43.png](https://qiita-image-store.s3.amazonaws.com/0/27161/54ab5f83-d575-efb7-6edc-c26daba625e4.png "Screen Shot 2017-12-22 at 5.52.43.png")

ロードバランサとVPC。FargateはVPC接続のみです。今回は試験目的だったので、ウィザードがらくらくすべて用意してくれたので簡単でした。

#### オートスケーリング
![Screen Shot 2017-12-22 at 5.54.21.png](https://qiita-image-store.s3.amazonaws.com/0/27161/1288f920-400a-a6c3-8102-5690ad7bb56d.png "Screen Shot 2017-12-22 at 5.54.21.png")
　
70%以上でコンテナ追加、30%切ったらコンテナ削除、としています。
それぞれ1コンテナ単位での増減としてみました。

## ロードかけてみる。
この設定でJMeterさんに頑張ってもらいました。

![Screen Shot 2017-12-22 at 5.28.14.png](https://qiita-image-store.s3.amazonaws.com/0/27161/5c7ee73e-bf47-d887-61f6-7e36d9a2acf9.png "Screen Shot 2017-12-22 at 5.28.14.png")

![Screen Shot 2017-12-22 at 5.28.39.png](https://qiita-image-store.s3.amazonaws.com/0/27161/21a53f29-28f3-7d5d-af11-cd3dfbf65535.png "Screen Shot 2017-12-22 at 5.28.39.png")

合計2万アクセスです。

## 結果
・response time graph
![Response Time Graph.png](https://qiita-image-store.s3.amazonaws.com/0/27161/05624875-4a8e-ee93-0097-e1e3214cdb85.png "Response Time Graph.png")


・サービスイベント（上から新しいです）
![Screen Shot 2017-12-22 at 5.59.21.png](https://qiita-image-store.s3.amazonaws.com/0/27161/6075969e-c487-9818-7c1d-10a2da3134e6.png "Screen Shot 2017-12-22 at 5.59.21.png")

![Screen Shot 2017-12-22 at 5.58.56.png](https://qiita-image-store.s3.amazonaws.com/0/27161/748a87aa-b8ee-c6fc-69ec-23120cd6d51f.png "Screen Shot 2017-12-22 at 5.58.56.png")

## 結論
- EC2なしでの全自動コンテナマネジメントとCloudwatch連動のスケーリングは概ね設定通り動いている。
- 検知-(20s)->タスク追加スタート-(60-120s)->タスク追加完了-(20s)正常状態に戻る-(60-120s)->検知・・・・という感じ。

## 考察
- デプロイ用のEC2を管理しなくていいのはやはりすごく楽！これなら使いたいと思える。
- コンテナがあれば、スパイクの負荷の対応についてパラメータでいじれる値（cool downの時間や一度に増やす台数、減らす台数等）を適切にハンドルできれば十分にスパイクする負荷にも対応可能かと思われる。少なくとも当社ではAPIサーバでも、このレベルのスケールができればFaaSでなくても、これで十分かもしれない。現行アプリケーションがそのまま活かせる利点を考えると、ファーストステップとしてはコンテナが十分な移行対象になりうるなと感じました。

##でも・・・
そういえば、うちのサービスAzureの上に乗ってるんだった！