Fargate を使って Docker コンテナを起動する方法
Fargate はインフラ部分をAWSに丸投げしてコンテナを利用できる、サーバレスなサービスです。
FargateでNginxを動かすところまでCloudFormationを使って構築していきます。
この記事で触れる内容
- CloudFormationでリソースを作成する
- Fargate でNginxを動かす
この記事で作成する環境
今回のゴールは以下の構成です。
完成品はこちらのリポジトリにあります。
作成するリソース
ざっくり以下のリソースです。
サービス名 | リソース | 用途 |
---|---|---|
VPC | VPC | ECSを起動するためのネットワーク |
VPC | Subnet | ECSを起動するためのネットワーク |
EC2 | SecurityGroup | ALB用・ECS用 |
EC2 | ApplicationLoadBalancer | コンテナの負荷分散用 |
IAM | Role | ECSのタスク実行ロール |
ECS | TaskDefinition | コンテナ起動用のタスク定義 |
ECS | Service | サービス |
ECS | Cluster | クラスター |
ネットワーク部分作成
まずは、Fargateが動作するためのネットワーク部分を作成していきます。
メインのコンテンツではないので解説は割愛します。
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
CidrIp:
Type: String
Description: secondary octet ip addr
Project:
Type: String
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Sub '10.${CidrIp}.0.0/16'
EnableDnsHostnames: True
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
Igw:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref Igw
##----------------------------------##
# Subnets
##----------------------------------##
SubnetPublic1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref Vpc
CidrBlock: !Sub 10.${CidrIp}.10.0/24
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
SubnetPublic2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1c
VpcId: !Ref Vpc
CidrBlock: !Sub 10.${CidrIp}.20.0/24
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
##----------------------------------##
# RouteTable
##----------------------------------##
RouteTableForPublicSubnet:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
DefaultRouteForPublicSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTableForPublicSubnet
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref Igw
RouteAssocPubSubnet1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref SubnetPublic1
RouteTableId: !Ref RouteTableForPublicSubnet
RouteAssocPubSubnet2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref SubnetPublic2
RouteTableId: !Ref RouteTableForPublicSubnet
構成としてはとてもシンプルなネットワーク部分だけ構築されます。
また、上記のテンプレートはこちらのリポジトリをベースに作成しています。
タスク実行ロール作成
次にタスク実行ロールを作成する記述をご紹介します。
##----------------------------------##
# Task Execute Role
##----------------------------------##
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${Project}-task-role'
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
このロールは、タスク定義からコンテナを作成するためにECSが利用するロールになります。
セキュリティーグループの作成
次にセキュリティグループを作成する記述です。
セキュリティグループは、インターネットからのhttpアクセスを許可するALB用と、ALB経由のhttpアクセスのみ許可するECS用の2つを作成します。
##----------------------------------##
# Security Group
##----------------------------------##
AlbSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Project}-alb-sg"
GroupDescription: allowed http access from internet.
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
EcsSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Project}-ecs-sg"
GroupDescription: allowed http access from alb.
VpcId: !Ref Vpc
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref AlbSg
IpProtocol: tcp
FromPort: 80
ToPort: 80
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
ALBの作成
次にALBを作成する記述をご紹介します。
今回は、複数のコンテナを作成してALBで負荷分散する構成になります。
##----------------------------------##
# ALB
##----------------------------------##
Alb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
Type: application
SecurityGroups:
- !Ref AlbSg
Subnets:
- !Ref SubnetPublic1
- !Ref SubnetPublic2
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
AlbTg:
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
Properties:
VpcId: !Ref Vpc
Name: !Sub "${Project}-tg"
Protocol: HTTP
Port: 80
TargetType: ip
Tags:
- Key: Name
Value: !Ref Project
- Key: Project
Value: !Ref Project
AlbListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AlbTg
ここまでのリソースを作成すると以下のような構成になります。
タスク定義の作成
ここからがECSに関連するリソースです。
タスク定義とは、ECSでコンテナを起動させる時に必要な定義です。
例えばコンテナように確保するリソースや動作させるイメージを指定します。
##----------------------------------##
# TaskDefinition
##----------------------------------##
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub "${Project}-ecs-task"
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn
Cpu: 256
Memory: 512
ContainerDefinitions:
- Name: !Sub "${Project}-container"
Image: nginx:latest
PortMappings:
- HostPort: 80
Protocol: tcp
ContainerPort: 80
「タスク実行ロール」と「タスクロール」
ECSタスク定義には、「タスク実行ロール」と「タスクロール」があります。
前者は必須でECSが実行するために必要なロール、後者は起動したコンテナに付与される任意のロールで、例えば起動したコンテナにS3操作をさせる場合に必要です。
サービスの作成
次にサービスを作成する記述を紹介します。
サービスとは、起動したコンテナをまとめるためのグループです。
起動するコンテナの個数、紐づけるセキュリティーグループ、負荷分散に使うALBなどの設定を行います。
Service:
Type: AWS::ECS::Service
DependsOn: Alb
Properties:
Cluster: !Ref Cluster
LoadBalancers:
- TargetGroupArn: !Ref AlbTg
ContainerPort: 80
ContainerName: !Sub "${Project}-container"
LaunchType: FARGATE
DesiredCount: 3
TaskDefinition: !Ref TaskDefinition
ServiceName: !Sub "${Project}-service"
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref EcsSg
Subnets:
- !Ref SubnetPublic1
- !Ref SubnetPublic2
ポイントは、DependsOnです。
テンプレートを実行するとき、CloudFormationがわでよしなに順番を決めて事項してくれますが、依存関係を解決しきれないこともあります。
今回の場合、ServiceとALBの関係がそれに当たります。
ALBがまだ作成されていない状態でServiceを作成しようとしているので「参照しているターゲットグループがALBに紐づいていない」みたいなエラーになります。
DependsOnをつけることでServiceの作成順をALBよりも後にできます。
クラスターの作成
最後にクラスターを作成する記述の紹介です。
クラスターは、サービスをまとめる論理的なグループです。
ここまでの解説で、「タスク定義」を包括するのが「サービス」のイメージですが、クラスターはそのサービスを包括するというものになります。
##----------------------------------##
# Cluster
##----------------------------------##
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub "${Project}-cluster"
稼働確認
では、ALBのDNS名にアクセスしてコンテナが起動しているかを確認します。
問題なく動いていますね。
ここから先は、自分でビルドしDockerイメージを使うためにECRを使ったり、AutoScalingの設定を入れたりとご自身で調整してみてください。
CodePipelineの基本的な内容もご紹介しているので、コンテナのCICDにもぜひ挑戦してみてください。
1人で進めるのが難しい?
私は、AWSに関するスキルをRaiseTechのAWSフルコースからスタートさせました。
入会&受講後の感想はコチラ
コース受講後も、半永久的に質問し放題なので転職後の今も技術的な悩みを相談しています。
RaiseTechは毎週金曜日20時から無料説明会を開催しています。
IT業界や転職について「本当に無料?」というくらいボリュームのある内容でしたのでぜひみてみてください!