プライベートサブネットにECS(Fargate)を作成する
以下のページでFargateタイプのECSコンテナを作成する方法をご紹介しました。
今回はプライベートサブネットにFargateを作成する方法を確認します。
構築する環境
ECSクラスターを作成し、FargateタイプのECSタスクをプライベートサブネットに関連付けます。
タスクは以下の2種類のイメージを使用して作成します。
- DockerHubで公開されている公式のNginxイメージ
- 自作し、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を確認します。
正常にECRリポジトリが作成され、イメージがプッシュされていることがわかります。
続いてECSクラスターを確認します。
正常にクラスターが作成され、2つのECSサービスが作成されていることがわかります。
以下が各サービス内に作成されたタスクの詳細です。
それぞれ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の詳細につきましては、以下のページをご確認ください。
タスク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を作成する方法を確認しました。