1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS】public subnet を使用せずに private subnet 内で ECR と ECS の接続を設定してみた

Posted at

0. 初めに

ある日、 ECS から ECR への接続を private subnet 内で完結させる必要が生じたため、備忘録としてここに記しておこうと思います。

基本的にはこちらの記事1を参照させていただきました。

今回の要件に必要なリソースの作成から、作成したコンテナへ、ローカルの AWS CLI から接続してみるところまでを実施します。

全体の流れとしては次の通りです。

  1. VPCエンドポイント及びセキュリティグループの作成
  2. IAM Policy, IAM Roleの作成
  3. ECR, ECSの作成
  4. 最後に

1. VPC, VPCエンドポイント及びセキュリティグループの作成

まず今回の条件である「public subnet を使用せずに private subnet 内で ECR と ECS の接続を構築する」を満たすためには下記の3つの VPC エンドポイントを用意する必要があります。

・com.amazonaws.region.ecr.dkr (インターフェース)
・com.amazonaws.region.ecr.api(インターフェース)
・com.amazonaws.region.s3(ゲートウェイ)

また、今回は作成したコンテナへ AWS CLI から接続するため、次のエンドポイントも必要になります。

・com.amazonaws.us-east-1.ssmmessages (インターフェース)

本記事では com.amazonaws.region.s3 は VPC 作成時にまとめて作成するため、ルーティング等の詳細は省きます。
また、なぜ com.amazonaws.region.s3 が必要なのかは1に詳しく記載されています。

これら4つのエンドポイントを作成する前に、VPCとセキュリティグループを作成していきます。
また、今回はあくまで ECR と ECS の接続に重点を置いているため CIDR 等の設定については説明を省略します。

スクリーンショット 2025-01-13 010208.png

次の VPC endpoints の項目を S3 Gateway にしておくことで、作成とルーティングをしておきます。

image.png

これでメインとなる VPC の作成が完了したため、セキュリティグループの作成に移ります。

最初に ECS 用のセキュリティグループを作成します。

スクリーンショット 2025-01-13 013750.png

ECR との接続用にアウトバウンドのみ許可しておきます。
今回は簡単のためにインバウンドルールを削除しています。

次に4つのエンドポイント用のセキュリティグループを作成します。

スクリーンショット 2025-01-13 014044.png

ECSからの通信はhttpsの443ポートが使用されるため、インバウンドを許可しておきます。
今回は簡単のためにアウトバウンドルールを削除しています。
これでセキュリティグループの作成は完了です。

最後に VPC エンドポイントを作成していきます。
Create endpoint から AWS service の項目を選択し、 ecr.api の項目を選びます。

スクリーンショット 2025-01-13 010922.png

Network settings の項目 vpc は先ほど作成したものを選択し、subnet も同様に先ほど作成した private subnet を選択します。

スクリーンショット 2025-01-13 011413.png

まれに subnet の欄に作成した subnet が反映されていない場合があります。
その際はリロードや時間を置いたりすると反映される場合があります。

セキュリティグループは先ほど作成したエンドポイント用のものを選択します。

スクリーンショット 2025-01-13 014754.png

同様に dkr.api, ssmmessages のエンドポイントを作成しておきます。

2. IAM Policy, IAM Roleの作成

次に ecs execution コマンドを実行するのに必要な IAM Policy と Role を作成していきます。
必要なものは次の通りです。

IAM Policy
・ssmmessage full access

ssmmessage-fullaccess.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
        }
    ]
}

こちらの json をコピペすることで作成可能です。

IAM Role
・ssmmessage full access

こちらは上記の policy をアタッチして作成することができます。
今回は ecs-exec という名前でロールを作成したものとして進めます。

3. ECR, ECSの作成

まず ECR のプライベートリポジトリを作成します。

スクリーンショット 2025-01-13 103400.png

そして今回作成したプライベートリポジトリへ DockerImage を push していきます。
今回は特段こだわりがないため nginx を ubuntu 上で動かすようなものを使用します。

あまりにも適当な Dockerfile を使用してしまうと、コンテナが起動後すぐに終了してしまい、サービスが立ち上がらなくなってしまうので気を付けましょう(1敗)

ubuntu.dockerfile
FROM ubuntu:latest
 
RUN apt-get update && apt-get install -y nginx
 
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]

そしてこちらの Dcokerfile をローカル環境で build し、先ほど作成した ECR へ push します。

push-comand.sh
#最初に ECR との認証を通しておく
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com

#先ほどの Dockerfile を build しておく
docker buuild -t ecr-ecs .

#build した Dockerfile をタグ付けする
docker tag ecr-ecs <aws_account_id>.dkr.ecr.<region>.amazonaws.com/ecr-ecs:latest  

#ECR へ push する
docker push <aws_account_id>.dkr.ecr.<region>.amazonaws.com/ecr-ecs:latest

これで ECR 側の準備は完了になります。

次にECS側の作成に移ります。
最初にクラスターの作成をします。今回は CloudWatch の設定を切っていますが、必要な場合は CloudWatch のエンドポイントを立てる必要があります。

image.png

次にタスク定義を作成します。
この時にタスクロールを ecs-xec、タスク実行ロールを ecsTaskExecutionRole に設定しておきます。
また、今回は CloudWatch の設定を切っておきます。

imagepng

スクリーンショット 2025-01-13 112053.png

タスク定義の作成が完了したので、サービスの作成に移ります。
先ほど作成したタスク定義を使用します。

image.png

image.png

Networking の設定は事前に作成しておいた ECS 用のセキュリティグループを使用します。

image.png

これでサービスの作成が完了し、少し時間が経過した後にコンテナがデプロイされます。

最後に、作成したコンテナに対してローカル環境からアクセスすることができることを確認していきます。

AWS CLI と SSM がローカル環境にインストールされていることを前提としています。
それぞれの入れ方はこちらの公式サイト23を参照してください。

最初に aws ecs execute-command を利用できるように、有効化します。

exec-enable.sh
aws ecs update-service --region <region> --cluster ecs-ecr-cls --service ecs-ecr-service --enable-execute-command 

このときに表示される json の内容を確認して、次のように ExecuteCommand が有効化されていることを確認してください。
"enableExecuteCommand": true,

ExecuteCommand が有効化されたことを確認したら、タスクを再デプロイします。

new-deployment.sh
aws ecs update-service --region <region> --cluster ecs-ecr-cls --service ecs-ecr-service --task-definition ecs-ecr-taskdef:1 --force-new-deployment

次に aws ecs execute-command を利用して、稼働しているコンテナに入ってみます。

ecs-exec.sh
aws ecs execute-command --region <region> --cluster ecs-ecr-cls --task <task_ID> --container <container_name> --interactive --command "/bin/bash"

下図の赤枠で囲われている部分の値を使用します。
TaskをクリックしてコピーするとARNがコピーされることに注意しましょう(1敗)
スクリーンショット 2025-01-13 120345.png

無事に interactive mode で bash が表示されていれば一連の作業が完了です。

スクリーンショット 2025-01-13 121236.png

4. 最後に

private subnet のみで ECS と ECR の接続を一から作成している記事がなかなか見当たらなかったので、記事を執筆してみました。
レイアウトなどの見やすさへ直結する部分に苦戦しましたが、なんとか書き終えることができました。
CloudWatch や Route 53 、ALB を追加すれば、外部向けのサービスをある程度セキュアに作成できたりするので、AWS を使用すれば気軽にインフラを作成することができるなぁと改めて実感しました。
private subnet のみで ECS と ECR の接続する場合の最小限の手順を用意することは出来たと思っていますので、どなたかのお役に立てば幸いです。

参考文献

  1. 今回の記事の執筆にあたって参考にさせていただきました。(参考文献にも記載)
    https://qiita.com/KurokawaKouhei/items/9389f36420ebaa0390bd 2

  2. AWS CLI のインストール方法
    https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

  3. SSM のインストール方法
    https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/plugin-version-history.html

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?