AWS CDKを使ったAWS Fargate Serviceの構築

## はじめに
AWS CDK(Python)を使ってAWS Fargate Serviceを構築してみたいと思います。

今回作成したコードは[こちら](https://github.com/yacchin/cdk-fargate)

↑このコードで下記構成を作成します。

## 構成図
![CDK_Fargate-全体構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27525/cb7d338f-bc8f-962c-18c3-e0afecee9a78.png)

## 準備
- AWSアカウント
- CDK用IAM User

## フロー
1. 環境変数
1. [cdk install](#cdk-install)
1. [cdk init](#cdk-init)
2. [実装](#実装)
3. [cdk deploy](#cdk-deploy)
4. [動作確認](#動作確認)
5. [cdk destroy](#cdk-destroy)

## cdk install
```bash
$ npm install -g aws-cdk
```
`cdk`が実行できない場合は、PATHが通っているか確認する。

```bash
$ which node
/path/to/bin/node
$ export
...
PATH=/path/to/hoge:/path/to/fuga
...
$ export PATH=$PATH:/path/to/current/bin
$ export
...
PATH=/path/to/hoge:/path/to/fuga:/path/to/current/bin
...
```

## 環境変数設定
```
export AWS_ACCESS_KEY_ID=hoge
export AWS_SECRET_ACCESS_KEY=fuga
export ROLE_ARN=arn:aws:iam::xxxxxxxxxxxx:role/ecsTaskExecutionRole
export ECR_REGISOTRY=xxxxxxxxxxxx:role.dkr.ecr.ap-northeast-1.amazonaws.com/django-app:latest
```

## cdk init
```bash
$ mkdir /path/to/cdk_fargate
$ cd /path/to/cdk_fargate
$ cdk init --language python
```

## 実装
```bash
$ pwd
/path/to/cdk_fargate
$ cd cdk_fargate/
vi cdk_fargate_stack.py  
```
`cdk_fargate_stack.py`は[こちら](https://github.com/yacchin/cdk-fargate/blob/master/cdk_fargate/cdk_fargate_stack.py)

### VPC作成
 - Availability Zoneを2つ指定してVPC作成。

### ECS Cluster作成
 - 作成したVPCを指定してECS Clusterを作成。

### Fargate Service作成
 - [ecs_pattern.ApplicationLoadBalancedFargateService](https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecs_patterns/ApplicationLoadBalancedFargateService.html)を使って、Fargate Serviceを構築。
 - 今回は、Nginxのイメージを参照。

### Output
 - ALBのDNSをOutputする

```python
import os
from dotenv import load_dotenv

from aws_cdk import (
    aws_ec2 as ec2,
    aws_ecs as ecs,
    aws_iam as iam,
    aws_ecs_patterns as ecs_patterns,
    core,
)

load_dotenv()

ROLE_ARN = os.environ["ROLE_ARN"]
ECR_REGISOTRY = os.environ["ECR_REGISOTRY"]


class CdkFargateStack(core.Stack):
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        vpc = ec2.Vpc(self, "CdkFargateVpc", max_azs=2)

        cluster = ecs.Cluster(self, "Ec2Cluster", vpc=vpc)

        role = iam.Role.from_role_arn(self, "Role", ROLE_ARN)
        image = ecs.ContainerImage.from_registry(ECR_REGISOTRY)
        task_definition = ecs.FargateTaskDefinition(
            scope=self, id="TaskDefinition", execution_role=role, task_role=role
        )
        port_mapping = ecs.PortMapping(container_port=80, host_port=80)
        container = task_definition.add_container(
            id="Container", image=image
        ).add_port_mappings(port_mapping)

        fargate_service = ecs_patterns.ApplicationLoadBalancedFargateService(
            self, "FargateService", cluster=cluster, task_definition=task_definition
        )

        core.CfnOutput(
            self,
            "LoadBalancerDNS",
            value=fargate_service.load_balancer.load_balancer_dns_name,
        )


```

## cdk deploy
```bash
$ export AWS_ACCESS_KEY_ID=hoge
$ export AWS_SECRET_ACCESS_KEY=fuga
$ cdk deploy
```

## 動作確認
```bash
$ curl cdk-f-farga-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com
```

## cdk destroy
```bash
$ cdk destory
```
リソースがすべて削除されている！

## 次やりたいこと
 - ECRを使ったイメージ管理
 - ACM, Route53をつかったカスタムドメイン対応

## まとめ
チームではPythonを使って開発していますが、共通言語を使って構成管理ができることは素晴らしいと感じました。
CDKを使った構成管理をどんどん推し進めていきたいです。
カスタムドメイン設定まで実装できなかったので

## 参考文献
- https://docs.aws.amazon.com/ja_jp/cdk/latest/guide/ecs_example.html
- https://docs.aws.amazon.com/cdk/api/latest/docs/aws-ecs-readme.html
- https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecs_patterns.html
- https://github.com/aws-samples/aws-cdk-examples