2
1

More than 1 year has passed since last update.

AWS ECS on Fargateを使ってコンテナ構築~ネットワーク構築編~

Last updated at Posted at 2021-11-09

はじめに

機械学習モデルの推論結果を返す Web API を FastAPI で作成で作成したものを AWS 環境でデプロイする。Docker を用いた開発環境で作成したアプリであるため、そのままコンテナイメージを活用して AWS ECS on Fargate 上で稼働させる。AWSコンテナ設計・構築[本格]入門を参考にした。全体の流れは以下である。

  1. ネットワーク構築
  2. コンテナレジストリ構築
  3. オーケストレーション構築

構築はすべて AWS CloudFormation を用いて実行する。CloudFormation で使用するテンプレートファイルは、AWSコンテナ設計・構築[本格]入門で提供されているテンプレートファイルをベースにしている。
説明の流れに合わせてテンプレートファイルを network.yml, registry.yml, orchestration.yml の3つに分けるが、分け方として適切ではないので、実際には AWS CloudFormation ベストプラクティスなどを参考にファイルを分割した方がよい。
本記事ではネットワーク構築に関して述べるため、network.yml のみ使用する。

ベースとなるネットワーク

まずベースとして以下図のようなネットワークを構築する。Multi Availability Zone としており、各 AZ にて Ingress 用の Public Subnet と App 用の Private Subnet を作成している。またルートテーブルを2つ作成しており、1つは Ingress 用の Public Subnet とインターネットゲートウェイを紐付けており、もう1つは現段階では App 用の Private Subnet のみを紐付けている。これは本記事では以降触れないが、今後予定しているコンテナレジストリ構築編でゲートウェイ型 VPC エンドポイントとの紐付けに使用するため、この段階ではその準備をしている。
AWSネットワーク.drawio.png

VPC、サブネットの設定は以下のようにした。

VPC 名 IPv4 CIDR
testVpc 10.0.0.0/16
用途 NW 区分 AZ CIDR サブネット名
Ingress 用 Public 1a 10.0.0.0/24 test-subnet-public-ingress-1a
Ingress 用 Public 1c 10.0.1.0/24 test-subnet-public-ingress-1c
App 用 Private 1a 10.0.8.0/24 test-subnet-private-container-1a
App 用 Private 1c 10.0.9.0/24 test-subnet-private-container-1c

さらにこれらのセキュリティグループの設定は以下図のようになっている。インバウンドルールは図のように制限しており、アウトバウンドルールはすべてを許容するものとした。
AWSセキュリティグループ.drawio.png

CloudFormation テンプレートファイル

上記で説明したネットワークを構築するテンプレートファイルが以下となる。

network.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: Network template
Resources:
  # VPCの設定
  testVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: testVpc

  ############### Subnet, RouteTable, IGW ###############
  # Ingress周りの設定
  ## Ingress用のパブリックサブネット
  testSubnetPublicIngress1A:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/24
      VpcId:
        Ref: testVpc
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-subnet-public-ingress-1a
        - Key: Type
          Value: Public
  testSubnetPublicIngress1C:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.1.0/24
      VpcId:
        Ref: testVpc
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: test-subnet-public-ingress-1c
        - Key: Type
          Value: Public
  ## Ingress用のルートテーブル
  testRouteIngress:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: testVpc
      Tags:
        - Key: Name
          Value: test-route-ingress
  ## Ingressサブネットへルート紐付け
  testRouteIngressAssociation1A:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: testRouteIngress
      SubnetId:
        Ref: testSubnetPublicIngress1A
  testRouteIngressAssociation1C:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: testRouteIngress
      SubnetId:
        Ref: testSubnetPublicIngress1C
  ## Ingress用ルートテーブルのデフォルトルート
  testRouteIngressDefault:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: testRouteIngress
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: testIgw
    DependsOn:
      - testVpcgwAttachment

  # インターネットへ通信するためのゲートウェイの作成
  testIgw:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: test-igw
  testVpcgwAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: testVpc
      InternetGatewayId:
        Ref: testIgw

  # コンテナ周りの設定
  ## コンテナアプリ用のプライベートサブネット
  testSubnetPrivateContainer1A:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.8.0/24
      VpcId:
        Ref: testVpc
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-subnet-private-container-1a
        - Key: Type
          Value: Isolated
  testSubnetPrivateContainer1C:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.9.0/24
      VpcId:
        Ref: testVpc
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: test-subnet-private-container-1c
        - Key: Type
          Value: Isolated
  ## コンテナアプリ用のルートテーブル
  testRouteApp:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: testVpc
      Tags:
        - Key: Name
          Value: test-route-app
  ## コンテナサブネットへルート紐付け
  testRouteAppAssociation1A:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: testRouteApp
      SubnetId:
        Ref: testSubnetPrivateContainer1A
  testRouteAppAssociation1C:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: testRouteApp
      SubnetId:
        Ref: testSubnetPrivateContainer1C

  ############### Security groups ###############
  # セキュリティグループの生成
  ## インターネット公開のセキュリティグループの生成
  testSgIngress:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for ingress
      GroupName: ingress
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow all outbound traffic by default
          IpProtocol: "-1"
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          Description: from 0.0.0.0/0:80
          FromPort: 80
          IpProtocol: tcp
          ToPort: 80
        - CidrIpv6: ::/0
          Description: from ::/0:80
          FromPort: 80
          IpProtocol: tcp
          ToPort: 80
      Tags:
        - Key: Name
          Value: test-sg-ingress
      VpcId:
        Ref: testVpc
  ## コンテナアプリ用セキュリティグループの生成
  testSgContainer:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Group of app
      GroupName: container
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow all outbound traffic by default
          IpProtocol: "-1"
      Tags:
        - Key: Name
          Value: test-sg-container
      VpcId:
        Ref: testVpc

  # ルール紐付け
  ## Internet LB -> Container
  testSgContainerFromsSgIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      IpProtocol: tcp
      Description: HTTP for Ingress
      FromPort: 80
      GroupId:
        Fn::GetAtt:
          - testSgContainer
          - GroupId
      SourceSecurityGroupId:
        Fn::GetAtt:
          - testSgIngress
          - GroupId
      ToPort: 8000

Outputs:
  # VPC
  testVpc:
    Value: !Ref testVpc
    Export:
      Name: testVpc

  # Subnet, RouteTable
  ## Ingress public subnet
  testRouteIngressAssociation1A:
    Value: !Ref testRouteIngressAssociation1A
    Export:
      Name: testRouteIngressAssociation1A
  testRouteIngressAssociation1C:
    Value: !Ref testRouteIngressAssociation1C
    Export:
      Name: testRouteIngressAssociation1C
  ## Container private subnet
  testSubnetPrivateContainer1A:
    Value: !Ref testSubnetPrivateContainer1A
    Export:
      Name: testSubnetPrivateContainer1A
  testSubnetPrivateContainer1C:
    Value: !Ref testSubnetPrivateContainer1C
    Export:
      Name: testSubnetPrivateContainer1C
  ## Route table
  testRouteApp:
    Value: !Ref testRouteApp
    Export:
      Name: testRouteApp

  # Security group
  ## Ingress security group
  testSgIngress:
    Value: !Ref testSgIngress
    Export:
      Name: testSgIngress
  ## Container security group
  testSgContainer:
    Value: !Ref testSgContainer
    Export:
      Name: testSgContainer

Resources にて、スタックを構成するリソースなどを定義している。テンプレートの基礎についての学習などを参考に、コードとネットワーク図を見ればわかるため説明は割愛。
Outputs では、このテンプレートファイルにて作成されたリソースを他テンプレートファイルから参照できるようエクスポートしている。以降の記事では、クロススタックリファレンスを使ってこれらを参照していく。

スタックの作成

作成したテンプレートファイルを用いてスタックを作成する。AWS マネジメントコンソールにて、[CloudFormation]→[スタックの作成]と進むと以下のような画面に遷移するので、Amazon S3 URL またはテンプレートファイルをその場でアップロードして進めれば作成できる。

create_stack.png

以降の記事でクロススタックリファレンスする際には、S3 上の URL が必要となるのでここでは事前に S3 にテンプレートファイルをアップロードしておき、その URL を入力することでスタックを作成した。アップロード前には aws cloudformation validate-template --template-body file://[Template file path] コマンドを実行することで CloudFormation のテンプレートファイルの文法などをチェックすることもできる。詳細はテンプレートの検証を参照。
作成を実行後、ステータスが UPDATE_COMPLETE となっていれば、問題なく作成できている。

おわりに

AWS ECS on Fargate を使ってコンテナを構築する第1段階として、ベースとなるネットワークを作成した。今回作成したネットワークにスタックを追加していく形で、以降も進めていく。

2
1
1

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
2
1