はじめに
AWSのFargateを使ってみたいけど、何から始めていいかわからない...という方へ。
一緒に超シンプルな構成を試して「これがFargateか😃」を体感してみましょう。
書こうと思ったきっかけ
この記事は、インフラ・AWS初学者がFargateを理解して使えるようになるための学びの記録です。
初回は下記の記事です。ECRとECS、Fargateの概要説明とCloudShellを使って10分でECRにDockerイメージをプッシュする方法をまとめました。(多分3分で読めます)
今回はちょっとステップアップして、GitHubActionsを使ってECRにイメージをプッシュする方法も併せてご紹介します。
この記事一本で、シンプルなAWS ECS on Fargateを体験できます
ECS on Fargate とは?
Fargateっていうリソース環境(エンジンやメモリがある場所)でコンテナ管理するECSだよ、というやつです。
コンテナとは「アプリケーションを動かすために必要なものの集まり」と思ってください。
リソース環境がEC2になると「ECS on EC2」と呼びます。
Fargate と EC2の違いは「人間がコンテナを動かすためのサーバーを管理しないといけないのか」という点です。
Fargateは、AWSが自動でサーバーを用意してくれるので管理不要です。
ECSは、例えると「牧場」です。
広い草原がある環境(Fargate)で牛(コンテナ)を管理しています。
ということで次は ECS の構成を理解していきます。
ECSの構成要素
ECSは、クラスター、サービス、タスク定義・タスクで構成されます。
引用画像:https://zenn.dev/issy/articles/zenn-ecs-overview
① クラスター (Cluster)
サービスやタスクを管理する 「まとめ役」です。
② サービス (Service)
タスクを管理する 「実行役」です。
③④ タスクとタスク定義 (Task Definition)
タスク定義は「設計図」です。
タスク定義をもとに「起動させるコンテナの集まり」をタスクといいます。
あるルールに従う構成員、その上に実行役、さらに上にまとめ役がいる...
まるで何かの組織図のようですね。
ECSの構成 → 組織図
クラスター → 親玉
サービス → 実行役(構成員をまとめるリーダー)
タスク定義 → 構成員のためのルール・仕組み
タスク → 構成員たち
やってみよう
今回は簡単に、パブリックサブネットにECSを構築して1つのタスクを実行します。
タスクに割り振られたIPアドレスでアクセスするまでがゴールです。
下記の手順で進めます。
- GitHubActionsを使って、ECRにDockerイメージをプッシュ
- CloudFormation(コードでインフラ構築できるツール)を使ってECSを構築
- タスクに割り振られたIPアドレスでアクセスし「これがFargateか😃」を体感する
- GUIでクラスターを作ってみる
- もう一回タスクに割り振られたIPアドレスでアクセスし「これがFargateか😃」を体感する
前提:AWSとGitHubにログインしている
それではチュートリアルスタートです。
GitHubActionsを使って、ECRにDockerイメージをプッシュ
1-1.ECS → ECR → リポジトリを作成
1-2. GitHubActionsを使う準備
リポジトリを作成して、下記のDockerfileとhtmlディレクトリ、index.htmlを保存します
FROM nginx:latest
COPY ./html /usr/share/nginx/html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Web App</title>
</head>
<body>
<h1>初めてのFargate</h1>
</body>
</html>
GitHubActions用のymlファイルを作成します
エディタ上に下記のコードを貼り付けてymlファイルを作成します
name: Push to ECR
# トリガー 「mainブランチにプッシュされたら」
on:
push:
branches:
- main
workflow_dispatch:
jobs:
# ジョブ
build-and-push:
runs-on: ubuntu-latest # 実行環境(ランナー)を指定 ubuntu-latestを指定した場合、stepsでUNIX系のコマンドが使用できる
# ステップ
steps:
# リポジトリのクローン
- name: Checkout code
uses: actions/checkout@v3
# AWS CLI のセットアップ
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
# Dockerログイン
- name: Log in to Amazon ECR
run: |
aws ecr get-login-password --region ${{ secrets.AWS_REGION }} \
| docker login --username AWS --password-stdin \
$(aws sts get-caller-identity --query 'Account' --output text).dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com
# Dockerイメージのビルド
- name: Build Docker image
run: |
docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} -f Dockerfile .
# Dockerイメージのタグ付け
- name: Tag Docker image
run: |
docker tag ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} \
$(aws sts get-caller-identity --query 'Account' --output text).dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }}
# Dockerイメージのプッシュ
- name: Push Docker image to Amazon ECR
run: |
docker push \
$(aws sts get-caller-identity --query 'Account' --output text).dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }}
1-3. GitHubActionsを使ってリポジトリにイメージをプッシュする
リポジトリのSettingsに、アクセスキー、リージョン、シークレットキー、ECRリポジトリ名、イメージタグを保存します。
IAMユーザーのアクセスキーとシークレットキーは、
AWSコンソールの画面右上のアカウントをクリック → セキュリティ情報 → アクセスキーの作成で作成できます。
新規の場合は、New repository secretをクリックして一つずつ保存してくださいね。
AWS_ACCESS_KEY_ID:
IAMユーザーのアクセスキー。人に見せちゃダメ。
AWS_SECRET_ACCESS_KEY:
IAMユーザーのシークレットキー。人に見せちゃダメ。
AWS_REGION:
ECRのリージョン(例: 東京リージョンならap-northeast-1)。
ECR_REPOSITORY:
ECRリポジトリ名(例: my-docker-repo)。自分のに変更してね
IMAGE_TAG:
Dockerイメージのタグ(例: latest)。このまま使用OK
[1-1. ] で付けたリポジトリ名を保存
それではGitHubActionsを実行します
ちょっと興奮しますね
ECRの中に、イメージがプッシュできました
2. CloudFormationを使ってECSを構築
まず、イメージのURLをコピーします
CloudFormationにアップロードするファイルを、ローカルで作成します。
自動でECS構築する魔法のファイルです。
今回は必要最小限のリソースを構築します。
下記のコードを使用する場合は、
"xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-repo:latest"の部分に
イメージのURLを貼り付けてください
AWSTemplateFormatVersion: "2010-09-09"
Resources:
# VPCの作成
VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: "Name"
Value: "honda-vpc"
# サブネットの作成
PublicSubnet1:
Type: "AWS::EC2::Subnet"
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.0.0/20"
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: "Name"
Value: "honda-subnet-public1-ap-northeast-1a"
# インターネットゲートウェイの設定
InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: "Name"
Value: "honda-igw"
AttachInternetGateway:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
# ルートテーブルの設定
PublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: "Name"
Value: "honda-rtb-public"
PublicRoute:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
# ECS用セキュリティグループ
SecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "Allow HTTP traffic"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: "tcp"
FromPort: 80
ToPort: 80
CidrIp: "0.0.0.0/0"
# ECSクラスターの作成
ECSCluster:
Type: "AWS::ECS::Cluster"
Properties:
ClusterName: "my-ecs-cluster"
# ECSタスク定義
ECSTaskDefinition:
Type: "AWS::ECS::TaskDefinition"
Properties:
Family: "my-app-task"
RequiresCompatibilities:
- FARGATE
NetworkMode: "awsvpc"
Cpu: "256"
Memory: "512"
ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn
ContainerDefinitions:
- Name: "my-app-container"
Image: "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-repo:latest" ← ご自身のイメージURLを貼り付けてください
PortMappings:
- ContainerPort: 80
HostPort: 80
Protocol: "tcp"
# ECSタスク実行ロール
ECSTaskExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "ecs-tasks.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "ecsTaskExecutionPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "ecr:GetAuthorizationToken"
- "ecr:GetDownloadUrlForLayer"
- "ecr:BatchGetImage"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "s3:GetObject"
Resource: "*"
# ECSサービスの作成
ECSService:
Type: "AWS::ECS::Service"
Properties:
Cluster: !Ref ECSCluster
TaskDefinition: !Ref ECSTaskDefinition
DesiredCount: 1
LaunchType: "FARGATE"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref PublicSubnet1
SecurityGroups:
- !Ref SecurityGroup
AssignPublicIp: "ENABLED"
引用元:https://qiita.com/free-honda/items/c7a68a216eef2161c567
CloudFormation → スタックの作成
先ほど作成したtest.yamlをアップロードします
スタックに名前を付けます
承認チェックに✅します
最後のページは特に何も変更せずに「送信」をクリックします
test.yamlに書いたリソースがどんどん作られていきます。
更新ボタンを押して、スタック名に「CREATE_COMPLETE」ステータスが付いたら完了です。
3. タスクに割り振られたIPアドレスでアクセスし「これがFargateか😃」を体感する
ECS → クラスター → クラスターをクリック
タスクをクリック
パブリックIPアドレスをクリック
Fargateにアクセスできました!
4. GUIでクラスターを作ってみる
先ほどは自動でクラスターとサービスを作成しましたが、試しに作ってみましょう
まず先ほど作成したクラスターを削除します
タスクからタスクを停止し、クラスターからクラスターを削除
クラスターの作成をクリック
クラスターに名前を付けます
クラスターができました
サービスを作成します
ネットワーキングのタブを開いて、VPCやサブネットをdefaultではなく、自分で作成したものに変更しましょう
「正常にデプロイされました」の表示は出たら完了です
5. もう一回タスクに割り振られたIPアドレスでアクセスし「これがFargateか😃」を体感する
ECS → クラスター → クラスターをクリック
タスクをクリック
パブリックIPアドレスをクリック
Fargateにアクセスできました!
まとめ
- 「ECS on Fargate」とは「Fargate載せECS」の意味で、ECSがメイン
- ECSはクラスター、サービス、タスク・タスク定義で構成される
最後までお付き合いくださりありがとうございます。
今回はECRにDockerイメージをプッシュし、ECSの中のFargateで簡単なWebサイトをデプロイする方法を学び、Fargateを体感しました。
次回はハッカソンで開発したアプリをFargateでデプロイしてみます。
参考文献