Help us understand the problem. What is going on with this article?

AWS Fargateをコマンドベースで作る(少しGUI)

こんにちわ、Loco ParntersでSREチームのエンジニアです。

ECSをCodepiplelineの中で使うことによってCI/CDが実現できます。
今回はECSのFargateでコンテナを簡単に構築する方法を書いてみました。

1.ECSの概要

Docker(コンテナ)をローカル端末で使用しているユーザは多いと思います。 docker-compose 使ったり Dockerfile を使用して Apache や nginx 、 MySQLなどを構築する。

ところが、AWSのEC2でDockerを使用したい場合、以下のような問題に直面すると思います。

  • WEBのDocker(同じコンテンツを持ったDocker)が5台、起動した際にALBに自動で接続したい
  • WEBのDockerを常に5台起動させておきたい
  • EC2をまたいでもWEBとMySQLを通信させたい(RDS使わない前提で)

このようなエンタープライズ向けのコンテナサービス展開をECSで実現できます。

2.ECSの概念

ECSを最初に起動したときに以下のような説明の画面が表示されます。こちらをベースに説明します。
スクリーンショット 2018-12-05 14.44.27.png

  • ContainerDefinition
    これはそのままコンテナの定義です。具体的には「コンテナのイメージはnginxを使う」
    と言ったコンテナの基本的な設定を指します。

  • Task definition
    次にTask definitionですが、これは
    「WEBのコンテナとRedisのコンテナを1つのグループにしたい」
    「タスク全体(コンテナ全体)といてどのくらいのCPUやメモリを割り当てたい」
    「EC2上で稼働させるEC2、サーバレスで稼働させるFargate」
    のようなグループを定義するものです。

  • Service
    「上記で定義したTask definitionをいくつ動かすか」
    「アタッチするALBはどれか?」
    「Dockerはどこのsubnetに属するか」
    「AutoScalingを実施するか?」
    ・・・・
    と言った内容を設定できます。

  • Cluster
    上記のタスクとサービスを稼働させる箱です。

今回は以下の条件でECSを作成します。
+ ECRよりイメージを作成するようにする
+ nginxとredisの2つのコンテナを一つのタスクにする
+ タイプはサーバレスの「Fargate」で作成
+ ALBにnginxだけアタッチする

3.ECRの作成

1.aws cliでの作成

aws cli が既に使える前提で書いておきます。
まだの人は AWS Command Line Interface のインストール
設定ファイルと認証情報ファイルを手順を踏んで使える状態にしてください

2.Dockerfileの作成

コンテナはDockerhubよりプルして構築してもいいのですが、折角なのでDockerhubのAWS版(?)であるECRを使用します。

nginxでは特定の設定を行っていません。必要に応じて設定を行ってください。

FROM amazonlinux:2.0.20180827

ADD nginx/nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum --enablerepo=nginx install -y nginx

RUN yum update -y
RUN yum --enablerepo=nginx install -y nginx
RUN yum install -y zip \
                   procps \
                   iputils \
                   awscli \
                   unzip \
                   libtool-ltdl \
                   libtool \
                   libXpm \
                   mysql \
                   httpd \
                   libtiff \
                   autoconf \
                   gcc \
                   gcc-c++ \
                   automake \
                   git \
                   systemd-sysv \
                   libxslt \
                   https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
                   http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

RUN yum install -y --enablerepo=amzn2-core gd-last
RUN yum install -y supervisor

## Install PHP7.2
RUN yum install --enablerepo=remi-php72 --disablerepo=amzn2-core -y php \
                                           php-fpm \
                                           php-devel \
                                           php-mbstring \
                                           php-pdo \
                                           php-mysqlnd \
                                           php-gd \
                                           php-xml \
                                           php-mcrypt

## Modify TimeZone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

## Add supervisor
ADD supervisor/supervisord.conf /etc/supervisord.d/supervisord.conf

## Start nginx settings
EXPOSE 80
CMD /usr/bin/supervisord -c /etc/supervisord.d/supervisord.conf

上記で必要なファイルは nginx.reposupervisord.conf ですが、それぞれ

nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
supervisord.conf
[supervisord]
nodaemon=true

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"

[program:php-fpm]
command=/usr/sbin/php-fpm --nodaemonize

2.イメージリポジトリの作成

ECRにイメージリポジトリを作成します。

$ aws ecr create-repository --repository-name myrepo
{
    "repository": {
        "registryId": "353XXXXXXXXX",
        "repositoryName": "myrepo",
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:[AWSのID]:repository/myrepo",
        "createdAt": 1543991375.0,
        "repositoryUri": "[AWSのID].dkr.ecr.ap-northeast-1.amazonaws.com/myrepo"
    }
}

3.ECRへの登録

レジストリに対して Docker クライアントを認証するために使用するログインコマンドを取得

$ aws ecr get-login --no-include-email --region ap-northeast-1
(以下のreponse)
docker login -u AWS -p eyJwYXlsb2FkIjoiWlRla0xlNlUw
・・・・
・・・・
・・・・ap-northeast-1.amazonaws.com

返ってきたresponseをそのままコピペしてコンソールに貼り付けてEnter

・・・・・・・
RGxJb3BDNnpzMGJNZFJyWVNIYS9DMzlrQ3JjUDhrVnByRTlmK2tRQUFBSDR3ZkFZSktvWklodmNOQVFjR29HOHdiUUlCQURCb0Jna3Foa2lHOXcwQkJ3RXdIZ1lKWUlaSUFXVURCQUV1TUJFRURLUVJQeUVvbHZmZDUvL1FBUUlCRUlBNyt3SEV2Q2haeXNaQldhSkRoNmo5UDE2U0JUQlZVQUo1YU5uM0Z4elNhSThrdmdyZDYwWHBpQ0dpWm9NWUhoTXQ4MnJ5VlVRWkppU05VQlk9IiwidmVyc2lvbiI6IjIiLCJ0eXBlIjoiREFUQV9LRVkiLCJleHBpcmF0aW9uIjoxNTQ0MDM0NzQ0fQ== XXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded

上記のように Login Succeeded と出たら成功です。

あとは登録するために以下のコマンドを順番に入力します。

(Dockerfileが存在するディレクトリ内で)
$ docker build -t myrepo .

$ docker tag myrepo:latest [AWSのID].dkr.ecr.ap-northeast-1.amazonaws.com/myrepo:latest

$ docker push [AWSのID].dkr.ecr.ap-northeast-1.amazonaws.com/myrepo:latest

イメージの確認を行います。

$ aws ecr describe-images --repository-name myrepo
{
    "imageDetails": [
        {
            "imageSizeInBytes": 571860528,
            "imageDigest": "sha256:cb1a28b1eXXXXXXXXXXXXXx",
            "imageTags": [
                "latest"
            ],
            "registryId": "35363XXXXXXXXX",
            "repositoryName": "myrepo",
            "imagePushedAt": 1543307109.0
        }
    ]
}

以上で、WEBのイメージがECRに登録されました。

4.clusterの作成

最初にECSの大外から作成していきます。

$ aws ecs create-cluster --cluster-name mycluster
[以下のresponseが返る]
{
    "cluster": {
        "status": "ACTIVE",
        "statistics": [],
        "clusterName": "mycluster",
        "registeredContainerInstancesCount": 0,
        "pendingTasksCount": 0,
        "runningTasksCount": 0,
        "activeServicesCount": 0,
        "clusterArn": "arn:aws:ecs:ap-northeast-1:111111111111:cluster/mycluster"
    }
}

5. Task definitionの作成

今回は、Fargateで作成したので以下の制限やお決まりごとがあります。

パラメータ おきまりごと
networkMode awsvpcのみ対応
links 同じタスク定義内のコンテナはlocalhostを共有しているので、localhost+ポート番号でアクセスさせる
イメージ ECRとDocker Hubのパブリックリポジトリのみサポート
Task Size タスク全体に割り与えるメモリとCPUで、Fargateでは必須パラメータ。値は組み合わせから選ぶ必要がある

上記の条件を加味して以下のtask.jsonを作成します。
最初にTaskのRoleとexecutionのRoleをIAMで作成します。
[参考URL]
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-iam-roles.html#create_task_iam_policy_and_role
Roleができたら(今回はAmazonECSTaskS3BucketRoleという名前で作りました)下記のtask.jsonを作成します。
このRoleについてはもう少し詳しく+詳細に設定しなければならないのですが今回は長くなるので一つのRoleで作成しました。

task.json
{
    "family": "mytask",
    "taskRoleArn": "arn:aws:iam::[AWSのID]:role/AmazonECSTaskS3BucketRole",
    "executionRoleArn": "arn:aws:iam::[AWSのID]:role/AmazonECSTaskS3BucketRole",
    "networkMode": "awsvpc",
    "containerDefinitions": [
        {
            "name": "web",
            "image": "[AWSのID].dkr.ecr.ap-northeast-1.amazonaws.com/myrepo",
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                }
            ]
        },
        {
            "name": "redis",
            "image": "redis:latest",
            "portMappings": [
                {
                    "containerPort": 6379,
                    "hostPort": 6379,
                    "protocol": "tcp"
                }
            ]
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "512",
    "memory": "2048"
}

上記で

 "taskRoleArn": "arn:aws:iam::[AWSのID]:role/AmazonECSTaskS3BucketRole",
 "executionRoleArn": "arn:aws:iam::[AWSのID]:role/AmazonECSTaskS3BucketRole",

の部分はタスク用の IAM ロールを参考にIAMでRoleを作成します。

タスクの登録を行います。

$ aws ecs register-task-definition --cli-input-json file://task.json

6.ALBの作成

ALBを作成します。これはGUIで作成しても構いません。
サービス登録にあたりALBを使用しますが、ALBを作成する際にターゲットグループの部分で、「ターゲットの種類」を選択するが「インスタンス」と「IP」が選べます。

  • Fargateはインスタンスタイプでは無いので「IP」でロードバランサを作成してください。
  • ヘルスチェックは[index.html]を指定してください。

7.サービスの登録

$ aws ecs create-service \
--cluster cluster-api \
--service-name cluster-service \
--launch-type "FARGATE" \
--task-definition cluster-task \
--network-configuration "awsvpcConfiguration={subnets=[subnet-XXXXXX,subnet-YYY],securityGroups=[sg-ZZZ],assignPublicIp=ENABLED}" \
--deployment-configuration  maximumPercent=200,minimumHealthyPercent=100 \
--load-balancer targetGroupArn=arn:aws:elasticloadbalancing:ap-northeast-1:111111:targetgroup/web-pre-target/23614c822222222f272,containerName=web_pre_nginx,containerPort=80  \
--desired-count 1

以下、説明します。
* --network-configurationには配置するSubnetを指定することができます。
* 「containerName=web」の部分は、上記のtask.jsonの「"name": "web"」の文言と合わせます。
* 最後の --desired-count は タスクをいくつ起動させるかになりますので必要数設定してください

8.確認

あとは、ALBのDNS経由でコンテンツが見れればOKです。

スクリーンショット 2018-12-05 16.10.34.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした