former2 を AWS CLI を使って ECS にデプロイしてみた

クラウド

前回、AWSの既存環境をIaC化するために、former2 を使用する環境をEC2上に作成しました。

Dockerfile で提供されているので、せっかくなので学習の意味も込めて、WebブラウザのGUIではなくAWS CLI を使用して、コンテナサービスであるECSを使用してにデプロイしてみます。

やること

  • former2 の環境を、ECSでデプロイする
  • AWS CLI を使用する

前提

  • docker および AWS CLI が実行できる環境を用意します
    • 今回はあらかじめEC2にdockerをインストールしたものを用意してます
  • アクセスキーIDとシークレットアクセスキーがあるものとします

概要

大まかな流れは以下の通りです。

  1. AWS CLI にアクセスキー等を紐づける
  2. github から former2 のソース(Dockerfile)をダウンロードし、Dockerイメージにビルドする
  3. ビルドしたイメージをECRにアップロードする
  4. ECS にデプロイする

手順

1. AWS CLI にアクセスキー等を紐づける

既にAWS CLIがインストールされている環境で以下を実行します。

# AWS CLI の設定
$ aws configure
AWS Access Key ID [None]: <アクセスキーIDを入力>
AWS Secret Access Key [None]: <シークレットアクセスキーを入力>
Default region name [None]: ap-northeast-1
Default output format [None]:

2. github から former2 のソース(Dockerfile)をダウンロードし、Dockerイメージにビルドする

以下が former2 のリポジトリです。MITライセンスです。

GitHub - iann0036/former2: Generate CloudFormation / Terraform / Troposphere templates from your existing AWS resources.
Generate CloudFormation / Terraform / Troposphere templates from your existing AWS resources. - iann0036/former2

ダウンロードしてDockerイメージにビルドします。

# former2 のリポジトリをダウンロード
$ git clone https://github.com/iann0036/former2.git
# former2 の Docker イメージをビルド
$ cd former2
$ docker build -t former2 .

以下を実行してイメージがビルドされたか確認できます。

$ docker images
REPOSITORY         TAG             IMAGE ID       CREATED          SIZE
former2            latest          fb4eb2102ea3   26 seconds ago   369MB

3. ビルドしたイメージをECRにアップロードする

ECS でデプロイするためには、コンテナイメージを ECR にアップロードする必要があるみたいです。たぶん・・・

まず、ECR リポジトリを作成します。

$aws ecr create-repository --repository-name former2
# 以下実行結果
{
    "repository": {
        "repositoryUri": "{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/former2",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        },
        "registryId": "{アカウントID}",
        "imageTagMutability": "MUTABLE",
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:{アカウントID}:repository/former2",
        "repositoryName": "former2",
        "createdAt": xxxxx.0
    }
}

以下を実行し、作成したECRリポジトリに、Dockerイメージをアップロードします。

# ECRにログイン
$ aws ecr get-login-password | docker login --username AWS --password-stdin {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com
# ECRにアップロードする用にDockerイメージをタグ付け(ここでは、バージョンを日付20230504としています。任意の文字列でよいです)
$ docker tag former2:latest {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/former2:20230504
# ECRにアップロード
$ docker push {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/former2:20230504

4. ECS にデプロイする

ECSクラスター作成 → ECSタスク作成 → ECSサービス作成という流れでデプロイを実行できます。

まず、ECSクラスターを作成します。

$ aws ecs create-cluster --cluster-name {クラスター名}

次に、ECSタスクを作成します。
ここでは、コンテナ起動時の設定をJSONファイルで定義し、それをアップロードする方法で実行します。

// EcsTaskDefinition.json
{
    "family": "{タスク名}",
    "networkMode": "awsvpc",
    "requiresCompatibilities": ["FARGATE"],
    "containerDefinitions": [
      {
        "name": "former2",
        "image": "{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/former2:20230504",
        "portMappings": [
          {
            "containerPort": 80,
            "protocol": "tcp"
          }
        ]
      }
    ],
    "memory": "1 GB",
    "cpu": ".5 vCPU",
    "executionRoleArn": "arn:aws:iam::{アカウントID}:role/ecsTaskExecutionRole"
}
# タスク定義をアップロードで作成
$ aws ecs register-task-definition --cli-input-json file://EcsTaskDefinition.json

次にECSサービスを作成します。

# 注:subnet-XXXXX や sg-XXXXX はあらかじめ作成したものを指定する必要があります
aws ecs create-service \
    --cluster {クラスター名} \
    --service-name {サービス名} \
    --task-definition arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/{タスク名} \
    --launch-type FARGATE \
    --desired-count 1 \
    --network-configuration "awsvpcConfiguration={subnets=[subnet-XXXXX,subnet-XXXXX],securityGroups=[sg-XXXX],assignPublicIp=ENABLED}"

動作確認

上記まで実行すると、ECSが自動でサービスを起動します。

アクセスするためのIPアドレスは以下の手順で確認できます。
(結構面倒な手順ですが、これ以外なさそうです)

# タスクIDの取得
$ aws ecs list-tasks --cluster {クラスタ名} --service {サービス名} --desired-status RUNNING
{
    "taskArns": [
        "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxxxxxxx/{ここに英数字文字列でタスクIDが表示される}"
    ]
}
# タスクIDからネットワークインターフェースIDを取得
aws ecs describe-tasks --cluster {クラスタ名} --tasks {上記で取得したタスクID} --query "tasks[].attachments[].details[?name=='networkInterfaceId'].value" --output text
# ネットワークインターフェースIDから、パブリックIPアドレスを取得
aws ec2 describe-network-interfaces --network-interface-ids {上記で取得したネットワークインターフェースID} --query "NetworkInterfaces[].Association.PublicIp" --output text

取得したIPアドレスを使用して、ブラウザに http://<IPアドレス> を入力すると、アクセスできるはずです。

注意

アクセスするためのIPアドレスですが、ECSタスクが起動するたびに変わるようです。

IPアドレスがコロコロ変わるのを防ぐためには、ALBを設置し、ALBにパブリックなDNSを設定する必要があるみたいです。

追記

と、さらに調べてみると、後からALBをくっつけるのはかなり厳しそう。少なくともマネジメントコンソールからは後付けできない仕様みたい・・・

とりあえず後からALBを設定する方法を端的にメモしておきます。

  • AWS CLI を最新にバージョンアップする
    • 古いCLIだとALBを後付けできない
  • 以下を実行
$ aws ecs update-service \
  --cluster {クラスタ名} \
  --service {サービス名} \
  --load-balancers targetGroupArn=}ターゲットグループのARN},containerName={タスクに割り当てているコンテナ名},containerPort=80

最新にしないといけなかったり、マネジメントコンソールでできなかったり。。。流石に個の仕様は糞過ぎる。

コメント

タイトルとURLをコピーしました