メモ ECS AWSコンソールからクラスタ、タスク、サービス作成

## やること
- ECSリソース操作に関してはAWSコンソール上で行う
- ECSクラスタを作成
- ECSタスクを作成 (自前ビルドしたイメージを起動)
- ECSサービスを作成
- 起動したコンテナのログを確認 CloudWatchLogs
- 終了したコンテナの再起動確認
- タスクのイメージを更新

ECSの概念についてはこちらの記事で [Amazon EC2 Container Service(ECS)の概念整理](https://qiita.com/NewGyu/items/9597ed2eda763bd504d7)


## 環境
- AWSコンソールにログインできる (今回使うリソースの作成権限があるユーザで)
- ECRに標準出力するイメージを持つリポジトリがある [ここで作ったechoalpine使う](https://qiita.com/TakashiOshikawa/items/04795d5d95eb5d0b5b9b)


## 作業

### ECSクラスタを作成する
何はともあれクラスタを作ってみる
コンソールの検索バーからECSと検索してECS画面に遷移
クラスタを選択して、クラスタの作成

##### クラスタのテンプレート選択

- ネットワークのみ (AWS Fargeteを使用)を選択して次のステップ

##### クラスタの設定

CIDRブロックは余ってるのを使う

- クラスタ名: `ecs-cluster-echoalpine`
- VPC作成: `チェックする`
- CIDRブロック: `11.0.0.0/16`
- サブネット1: `11.0.0.0/24`
- サブネット2: `11.0.1.0/24`

作成

### ECSタスクを作成

AWSコンソールからタスク定義のページへ遷移 -> 新しいタスク定義の作成

##### 起動タイプの互換性の選択
- Fargate

##### タスクとコンテナの定義の設定

- タスク名: `echoalpine-task`
- タスクロール: `ecsTaskExecutionRole`
- ネットワークモード: `awsvpc`

- タスクメモリ: `2GB`
- タスクCPU: `1 vCPU`

コンテナの追加から
- コンテナ名: `echoalpine`
- イメージ: `AWSアカウントID.dkr.ecr.イメージのあるECRリージョン.amazonaws.com/echoalpine:1.0.0`
- メモリ制限: `128`
- 環境変数追加: `MY_ENV_VAL` `VALUE` `"This is my env val !!"`

指定箇所以外はデフォルトの指定
作成

タスクを作成するとCloudWatchロググループも作成される
今回のロググループ名は`/ecs/echoalpine-task`だった

### サービスの作成

クラスタ一覧から作成したクラスタを選択して遷移するとサービスというタブが開いていると思うのでサービスの新規作成を行う
作成するサービスで先ほど作成したタスクを利用する
※記述していない箇所はデフォルトの設定

##### サービスの設定
- 起動タイプ: Fargate

- タスク定義(Family): `echoalpine-task`
- タスク定義(Revision): `1(latest)`
- プラットフォームのバージョン: `LATEST`
- クラスタ: `ecs-cluster-echoalpine`
- サービス名: `echoalpine-service`
- タスクの数: `1`

##### ネットワーク構成
- クラスタVPC: クラスタ作成時に作成したVPC ここではCIRDブロック11.0.0.0のもの
- サブネット: クラスタ作成時に作成した2つのサブネットを指定

サービスを作成するとAWS Cloud Mapにリソースが作成されるのでサービス削除時にそれも削除するようにする

##### Auto Scalingオプション
- Service Auto Scaling: サービスの必要数を直接変更しない


入力項目が確認できたらサービスの作成


### 起動したコンテナのログを確認 CloudWatchLogs

サービスを作成したことで指定タスクのコンテナが立ち上がり、動作している状態になっていると思うのでCloudWatchLogsでコンテナで動かしているシェルの標準出力を確認してみる

CloudWatchページでタスク作成時に生成された`/ecs/echoalpine-task`を選択しログを確認する
起動させているコンテナは10秒毎に`my echoalpine container!! 1.0.0`と出力し、10回出力すると`kiss of death...`と言い残し一生を終えるドラマチックなセミみたいなコンテナ

恐らくCloudWatchでその出力が確認できる (タスク定義でイメージをechoalpineにしていれば)
タスク定義で環境変数MY_ENV_VALを指定したので、このシェルが

```sh
echo my echoalpine container!! 1.0.1 $MY_ENV_VAL
```
となれば出力は`my echoalpine container!! 1.0.1 This is my env val !!`となる


### 終了したコンテナの再起動確認

セミコンテナは10回echoすると死んでしまうので、ECSのサービスがよしなに復活させてくれているか確認する

特に行う操作は無く、コンテナが再起動されると新しいログストリームが作成されるのでその中で再び同じ動作をしているか確認する

DockerイメージのCMDで指定しているプロセスが終わったらしっかりと再起動されているので嬉しくなった

### 動作させる新しいDockerイメージが用意できたのでタスクの新しいリビジョンを作成し、サービスで新しいリビジョンのタスクを使うように変更

(web)サービス等を運用していると動作可能な新しいイメージが出来ると思うので、それの適用を行う
新しいイメージの指定はタスク定義の`echoalpine-task`の中に入って最新のリビジョンを選択してから新しいリビジョンの作成を行う

変更する部分はコンテナの中身
登録されている`echoalpine`を選択しイメージを新しいバージョンにする

```
# before
xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/echoalpine:1.0.0

# after
xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/echoalpine:1.0.1
```

1.0.0を1.0.1にした
コードは書かないが、echo.shの`echo "my echoalpine container!! 1.0.0"`を`echo "my echoalpine container!! 1.0.1 $MY_ENV_VAL"`に変更した
[echoalpineの記事](https://qiita.com/TakashiOshikawa/items/04795d5d95eb5d0b5b9b)

イメージのみを更新したら作成
そうすると1つだったリビジョンが2つに増えている

ここまでがタスクの更新だが、これだけでは動いているコンテナの動作は変わらない
1.0.1を動かすためにはサービスの更新を行う
クラスタ`ecs-cluster-echoalpine` -> サービス`echoalpine-service`を選択

右上の更新ボタンを押すと、サービスの作成で行った画面に登録した情報が入っている状態になっている

タスク定義(Family)は`echoalpine-task`のまま
タスク定義(Revision)を`2(latest)`に設定

それ以外は何も変更せずにサービスの更新を行う

少し待っていると新しいCloudWatchのログストリームが生成され
`my echoalpine container!! 1.0.1 This is my env val !!`
と出力されるようになっている


### 動作させているコンテナを停止させる

サービスの`タスクの数`を0にして更新するとコンテナの動作は止まる


## まとめ
確かめたかったことは自前ビルドしたDockerイメージを使ってみること、プロセスが終了したときの再起動処理、標準出力へのログ確認、イメージ新バージョンになった時の更新、コンテナに環境変数渡せるか
この記事ではやってないけどALBから指定ポートへのルーティングも出来ていたのでとりあえず良さそう


## 懺悔
AWSコンソールを操作しているのに画像が1枚もないのは甘え


## 参考
[Amazon EC2 Container Service(ECS)の概念整理](https://qiita.com/NewGyu/items/9597ed2eda763bd504d7)