AWS Fargate


AWS ECS Fargate とは Docker コンテナを動かすための仕組み。Docker コンテナを起動して外から URL でアクセス出来るようになるまでやってみた。

* コンテナは 8001 (WebSocket) と 8002 (HTTP) の２つのポートを受け付ける。
* 外から両方のポートを使いたい。

AWS ECS には Clusters, Task Definitions, Repository の３つの設定項目がある

* Clusters:
    * 複数の Service をまとめて動作させる箱。
    * Service:
        * 複数の Task をまとめて動作させる箱。
* Task Definitions:
    * Task とは、Docker コンテナの動作単位。使う Docker image は AWS の Repositories から取ってきても良いし、他の Docker repository を使っても良い。
* Repositories:
    * AWS 用の Docker Repository. Docker image を保存する場所。

作業手順は次のようになる。

1. Repositories に Docker image を登録
2. Task Definition に Docker repository を指定
3. Cluster を作成
4. Application Load Balancer を作成
5. Cluster 内に Service と Task を作成
6. Security Group の設定

## AWS Fargate First run

* https://qiita.com/riywo/items/b223bdad2b3ae3bebf55 の通りに First runチュートリアル試した。
* 次へ次へと押すだけ
* Unable to assume the service linked role. Please verify that the ECS service linked role exists というエラーが出る。
* 二回目同じ事をやると何故か問題なく完了した。
* Cluster : default > sample-app-service 
* AWS Console > Elastic Container Service > Clusters : default > Tasks > Task をクリック
* IP が割り当てられている事を確認。

## AWS Cluster を削除する時の注意点

* The vpc 'vpc-xxx' has dependencies and cannot be deleted. のエラーが出て消せなかった。
* EC2 security group が参照していたので消したら OK。

## AWS ECS Repositories に Docker image を登録

[AWS FargateでFlaskを動かしてみる](https://qiita.com/oyngtmhr/items/45a0d3158e6dccb0882d) を参考に作業。

* Console で Region N. Virginia を選択
* AWS Console > Elastic Container Service (ECS) > Repositories
* Create repository
* Repository name: hoge-websocket-server
* Repository URL: xxx.dkr.ecr.us-east-1.amazonaws.com/hoge-websocket-server

画面に表示されるコマンドを実行してログイン

    $ aws ecr get-login --no-include-email --region us-east-1
    docker login -u AWS -p eyJwYXlsb2...
    $ docker login -u AWS -p eyJwYXlsb2... (表示された長いコマンドをそのまま実行)

先程出来た Docker image にタグを追加

    $ docker tag hoge-websocket-server:latest xxx.dkr.ecr.us-east-1.amazonaws.com/hoge-websocket-server:latest

Docker image を Registory に追加

    $ docker push xxx.dkr.ecr.us-east-1.amazonaws.com/hoge-websocket-server:latest
    file integrity checksum failed for "usr/lib/x86_64-linux-gnu/libjpeg.a"

Docker image が大きいと上のようなエラーが出た。小さい node のイメージを使ってイメージをダイエットすると成功。

## Task Definition に Docker repository を指定

ここで Docker image の場所や使いたいリソースを定義する。

* AWS Console > ECS > Task Definitions > Create a new definition
    * 1: Select launch type compatibility
        * FARGATE
    * 2: Configure task and container definitions
        * Task Definition Name: hoge-websocket-server
        * Task memory (GB): 0.5GB
        * Task CPU (vCPU): 0.25 vCPU
        * Add container
            * Container name: hoge-websocket-server
            * Image: xxx.dkr.ecr.us-east-1.amazonaws.com/hoge-websocket-server:latest
            * Port mappings
                * 8001
                * 8002
        * Create

## Cluster を作成

* AWS Console > ECS > Clusters > Create Cluster
    * 1: Select cluster template
        * Networking only
    * 2: Configure cluster
        * Culster name: hoge-cluster
        * Create VPC: チェック (意味はよくわからない)
            * 作成されるネットワーク情報に目を通しておく。
            * デフォルトで２つのサブネットが定義されるようだが、そのままにしておいた。
    * View Cluster

これで Cluster 本体の他、色々な Cluster Resources が作成される。これらの大事な情報を後から参照する方法が分からなかったので必ずメモっておく。

# Load Balancer の作成

このままだと起動停止のたびに IP アドレスが変わってしまうので、Application Load Balanceer (ALB) を使ってドメイン名を割り当てる。

* AWS Console > EC2 > Load Balancers
* Application Load Balancer > Create
* 1: Configure Load Balancer
    * Name: hoge
    * Scheme: internet-facing
    * IP address type: ipv4
    * Listeners
        * HTTP: 8001 (Websocket も HTTP で良い)
        * HTTP: 8002 (HTTP 用の Listener は ECS Service 設定時に出来るのでここで作らなくて良い)
    * Availability Zones
        * VPC (Create Cluster で設定した VPC)
        * 下の Subnet は２つとも選択する
    * Tag
        * project : hoge
* 2: Configure Security Settings
    * 設定なし
* 3: Security Groups
    * Create a new security group
    * Security group name: hoge-security-group
    * 使いたいポート番号を設定
    * あとで AWS Console > ECS > Clusters > hoge-cluster > Tasks > Task : a44f... から編集出来る。
* 4: Configure Routing
    * ヘルスチェックの設定らしい
    * Name: hoge-8002
    * Port: 8002
* 5: Register Targets
    * 何も設定しない

## Cluster 内に Service を作成

* AWS Console > ECS > Clusters > hoge-cluster > Services > Create
    * 1: Configure service
        * Launch type: FARGATE
        * Task Definition: (作成した Task)
        * Service name: hoge-service
        * Number of taksk: 1
    * 2: Configure network
        * Cluster VPC: (Create Cluster で設定した VPC)
        * Subnets: (Create Cluster で設定した subnet)
        * Security groups > Edit
            * Assigned security groups: Select existing security group
            * Load Balancer で作った hoge-security-group を選択
        * Load balancing
            * Load balancer type: Application Load Balancer
            * Load balancer name: hoge
        * Container to load balance
            * ここで設定すると、コンテナの IP が変わっても自動的に一つのポートだけ Load Balancer に割り当てられる。
            * hoge-websocket-server:8002 > Add to load balancer
                * Listner port: 8002:HTTP
                * Path pattern: /*
                * Evaluation order: 1
                * Health check path: /
            * hoge-websocket-server:8002
    * 3: Set Auto Scaling
        * デフォルトのまま
    * 4: Review
        * 特に VPC Id と Subnets に気をつける。間違うとややこしい事になる。
    * Create Service

## コンテナに割り当てられた IP アドレスの確認

* AWS Console > ECS > Clusters > hoge-cluster > Tasks > Task : a44f... を選択
* Private IP と Public IP が表示される。

## もう一つのポート Port 8001 の設定

ECS Service の作成時に Load Balancer を割り当てると、IP が変化しても Load Balancer が勝手に面倒を見てくれる。ただしポート番号は一つしか設定出来ない！！！！この例のように２つ目のポートを Load Balancer に見せるには、手動で IP を指定した Target Groups を作る必要があった。なので、更新の際にはこの IP をわざわざ再入力する必要がある。

* AWS Console > EC2 > LOAD BALANCING Target Groups
    * Target group name: hoge-8001
    * Protocol: HTTP
    * Port: 8001
    * Target type: ip
    * VPC: Cluster の VPC
    * Create
* AWS Console > EC2 > LOAD BALANCING Target Groups > hoge-8001
    * Targets > Edit
    * Task の IP を登録
* AWS Console > EC2 > LOAD BALANCING Load Balancers > hoge > Listeners
    * HTTP:8001 > View/edit rules
    * THEN に hoge-8001 を登録

## Docker image の更新

* AWS Console > ECS > Clusters > hoge-cluster > hoge-service > Update
    * Force new deployment: Check
    * 次へ次へ。。。
* しばらく待つと新しいコンテナが起動して古いコンテナが停止する。
* IP アドレスが変わっているので Load Balancer の Target Group も更新する。

## Task 削除

Task は service が管理するので、直接止められないらしい。Service の Update で Number of tasks を 0 にすると止められた。

* AWS Console > ECS > Clusters > hoge-cluster > hoge-service > Update
* Number of tasks: 0
* 次へ次へ

やりたかった事は node 一つの単純なサーバをテストしたいだけだったんだけど、随分大げさな構成になってしまった。