プライベートサブネットにECS(Fargate)を作成する

目次

プライベートサブネットにECS(Fargate)を作成する

以下のページでFargateタイプのECSコンテナを作成する方法をご紹介しました。

あわせて読みたい
CloudFormationでFargate入門 【CloudFormationでFargateに入門するための構成】 AWS FargateはサーバーレスでDockerコンテナを実行することができるサービスです。今回はFargate入門ということで、C...

今回はプライベートサブネットにFargateを作成する方法を確認します。

構築する環境

Diagram of create ECS(Fargate) in Private Subnet.

ECSクラスターを作成し、FargateタイプのECSタスクをプライベートサブネットに関連付けます。
タスクは以下の2種類のイメージを使用して作成します。

  1. DockerHubで公開されている公式のNginxイメージ
  2. 自作し、ECRにプッシュしたカスタムのNginxイメージ

公式Nginxイメージを取得するために、パブリックサブネットにNATゲートウェイを配置します。

ECRにプッシュしたイメージを取得するために、ECR用およびS3用VPCエンドポイントを作成します。

EC2インスタンスを作成します。
2つのイメージ作成されたコンテナにアクセスするためのクライアントして使用します。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/068

テンプレートファイルのポイント解説

ECSおよびFarfagateに関する基本的な事項については、冒頭のページをご確認ください。
本ページでは、プライベートサブネットにFargateを構成するポイントを取り上げます。

イメージを取得するための構成

タスクを作成する上で、Dockerイメージを取得する必要があります。
取得するイメージがDockerHubに公開されているイメージか、ECRにプッシュされたイメージかによって対応が異なります。

プライベートサブネットからDockerHubのイメージを取得する

Resources:
  IGW:
    Type: AWS::EC2::InternetGateway

  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref IGW

  EIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      SubnetId: !Ref PublicSubnet

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref CidrIp1
      VpcId: !Ref VPC
      AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"

  ContainerRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  RouteToInternet:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW

  RouteToNATGateway:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref ContainerRouteTable1
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGateway

  PublicRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  ContainerRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ContainerSubnet1
      RouteTableId: !Ref ContainerRouteTable1
Code language: YAML (yaml)

DockerHubで公開されているイメージを取得するためには、インターネットへの経路を用意する必要があります。
プライベートサブネット内に配置されるECSクラスターからインターネットに接続するために、パブリックサブネットにNATゲートウェイを配置します。

さらにNATゲートウェイ経由でインターネットにアクセスするために、ルートテーブルの設定も行います。
ECSクラスターが配置されるプライベートサブネットに関連づけるルートテーブルには、NATゲートウェイ向けのルートを設定します。
NATゲートウェイが配置されるパブリックサブネットに関連づけるルートテーブルには、インターネットゲートウェイ向けのルートを設定します。

プライベートサブネットからECRにプッシュされたイメージを取得する

Resources:
  ContainerSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref CidrIp4
      VpcId: !Ref VPC
      AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone3}"

  ContainerRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  ContainerRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ContainerSubnet2
      RouteTableId: !Ref ContainerRouteTable2

  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      RouteTableIds:
        - !Ref ContainerRouteTable2
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcId: !Ref VPC

  ECRDkrEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup2
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.dkr"
      SubnetIds:
        - !Ref ContainerSubnet2
      VpcEndpointType: Interface
      VpcId: !Ref VPC

  ECRApiEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup2
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.api"
      SubnetIds:
        - !Ref ContainerSubnet2
      VpcEndpointType: Interface
      VpcId: !Ref VPC
Code language: YAML (yaml)

Fargateにはいくつかプラットフォームバージョンがありますが、デフォルトではLATEST(1.4.0)が選ばれます。
バージョン1.4.0のFartateでは、ECR用のVPCエンドポイントは3種類必要です。

Fargate 起動タイプおよびプラットフォームバージョン 1.4.0 以降を使用する Amazon ECS タスクでは、com.amazonaws.リージョンecr.dkrおよびcom.amazonaws.リージョンecr.apiAmazon ECR VPC エンドポイントおよび Amazon S3 ゲートウェイエンドポイントは、この機能を利用します。

Amazon ECR VPC エンドポイントに関する考慮事項

ECR用のVPCエンドポイントはインターフォース型、S3用のVPCエンドポイントはゲートウェイ型で作成します。

タスクにパブリックアドレスは割り当てない

Parameters:
  Service1:
    Type: AWS::ECS::Service
    Properties:
      #Cluster: !Ref Cluster1
      Cluster: !Ref Cluster
      LaunchType: FARGATE
      DesiredCount: 1
      TaskDefinition: !Ref TaskDefinition1
      ServiceName: !Sub "${Prefix}-service1"
      NetworkConfiguration:
        AwsvpcConfiguration:
          #AssignPublicIp: ENABLED
          SecurityGroups:
            - !Ref ContainerSecurityGroup
          Subnets:
            - !Ref ContainerSubnet1

  Service2:
    Type: AWS::ECS::Service
    Properties:
      #Cluster: !Ref Cluster1
      Cluster: !Ref Cluster
      LaunchType: FARGATE
      DesiredCount: 1
      TaskDefinition: !Ref TaskDefinition2
      ServiceName: !Sub "${Prefix}-service2"
      NetworkConfiguration:
        AwsvpcConfiguration:
          #AssignPublicIp: ENABLED
          SecurityGroups:
            - !Ref ContainerSecurityGroup
          Subnets:
            - !Ref ContainerSubnet2
Code language: YAML (yaml)

AssignPublicIpプロパティで、タスク(コンテナ)にパブリックアドレスを付与するか設定できます。
今回はプライベートサブネット内にタスクが作成されるため、本プロパティは使用しません。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

操作は冒頭のページと同様です。
まずECRリポジトリ用CloudFormationスタックを作成し、その後に残りのスタックを作成します。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • ECRリポジトリ:[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-068:latest
  • ECSクラスター:fa-068-cluster
  • ECSサービス1:fa-068-service1
  • ECSサービス2:fa-018-service2
  • EC2インスタンス:i-0daf944e613851dd3

作成されたリソースをAWS Management Consoleから確認します。
まずECRを確認します。

Detail of ECR Repository.

正常にECRリポジトリが作成され、イメージがプッシュされていることがわかります。

続いてECSクラスターを確認します。

Detail of ECS Cluster 1.

正常にクラスターが作成され、2つのECSサービスが作成されていることがわかります。

以下が各サービス内に作成されたタスクの詳細です。

Detail of ECS Cluster 2.
Detail of ECS Cluster 3.

それぞれDockerHubおよびECRリポジトリから取得したイメージをベースとして、各コンテナが作成されていることがわかります。

また各タスク(コンテナ)にライベートサブネットが割り当てられている一方、パブリックサブネットは割り当てられていないことがわかります。
以下に割り当てられたプライベートアドレスを整理します。

  • タスク1:10.0.3.83
  • タスク2:10.0.4.91

動作確認

EC2インスタンスにアクセス後、2つのタスクにアクセスします。

インスタンスへのアクセスはSSM Session Managerを使用します。

% aws ssm start-session --target i-0daf944e613851dd3

Starting session with SessionId: root-0f881269c9b4cb613
sh-4.2$
Code language: Bash (bash)

SSM Session Managerの詳細につきましては、以下のページをご確認ください。

あわせて読みたい
LinuxインスタンスにSSM Session Manager経由でアクセスする 【LinuxインスタンスにSSM Session Manager経由でアクセスする】 EC2インスタンスにSSM Session Manager経由でアクセスする構成を確認します。 Session Manager は完全...

タスク1

curlコマンドでタスク1内のコンテナにアクセスします。

sh-4.2$ curl http://10.0.3.83
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Code language: Bash (bash)

正常にアクセスできました。
公式イメージから生成されたコンテナであることがわかります。

タスク2

続いてタスク2内のコンテナにcurlコマンドでアクセスします。

sh-4.2$ curl http://10.0.4.91
<html>
  <head>
  </head>
  <body>
    <h1>fa-068 index.html</h1>
  </body>
</html>Code language: JavaScript (javascript)

こちらも正常にアクセスできました。
カスタムイメージから生成されたコンテナであることがわかります。

まとめ

プライベートサブネットにFargateを作成する方法を確認しました。

目次