LoginSignup
13
13

More than 5 years have passed since last update.

Amazon ECSを使った簡単なコンテナアプリの構築

Posted at

はじめに

仕事でChatBotを使ってDigdagコマンドを叩きたいっていう案件があって、あまりAWS触ったことなかったので、以下のような構成のものを作りました
案件を満たすだけであれば、ECSとかDockerとか必要なくて、Lambdaで出来そうだったんですけど、勉強のために使いました
今回の記事ではDigdag関連は全て省いてます

 2018-10-04 20.23.05.png

HubotのDockerfileを用意

FROM node
LABEL maintainer="kurosame"

RUN npm install -g yo generator-hubot && \
    useradd bot && \
    mkdir /home/bot && \
    chown bot:bot /home/bot

USER bot
WORKDIR /home/bot
RUN yo hubot --defaults && \
    npm install hubot-chatwork && \
    rm -rf hubot-scripts.json

COPY --chown=bot:bot scripts /home/bot/scripts

CMD bin/hubot -a chatwork

Amazon ECRにプッシュする

Amazon ECRとはDockerのコンテナイメージを保存できるレジストリ
つまり、Docker Hub的なサービス
AWSを使っている場合は、他のAWSサービスとの統合が簡単になるので、Docker HubよりECRを使った方が良さそう

リポジトリを作成

 2018-09-06 15.57.57.png

リポジトリ名を決めて作成

Dockerイメージをプッシュ

作成したリポジトリを選択すると、以下のように「プッシュコマンドの表示」というボタンが出てるので、これをクリック
後は表示されたコマンドを順番に実行するとECRにプッシュされる

 2018-09-06 17.24.54.png

一応実行したコマンドを書いておきます(aws-cli使う前提です)

以下を実行するとDockerのログインコマンドが出力されるので、コピペして実行して、ログインする

aws ecr get-login --no-include-email --region ap-northeast-1

ログイン後、以下のコマンドでイメージを作成し、プッシュする

docker build -t [イメージ名] .
docker tag [イメージ名]:latest **********.dkr.ecr.ap-northeast-1.amazonaws.com/[イメージ名]:latest
docker push **********.dkr.ecr.ap-northeast-1.amazonaws.com/[イメージ名]:latest

タスク定義を作成

タスク定義とは、以下から引用すると
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definitions.html

Amazon ECSでDockerコンテナを実行するには、タスク定義が必要で、以下のような項目を設定する

  • タスクのコンテナで使用する Docker イメージ
  • 各コンテナで使用する CPU とメモリの量
  • 使用する起動タイプ。この起動タイプにより、タスクをホストするインフラストラクチャが決定される
  • タスクのコンテナをリンクするかどうか
  • タスクのコンテナで使用する Docker ネットワーキングモード
  • (オプション) ホストコンテナインスタンスにマッピングするコンテナのポート
  • コンテナが終了または失敗した場合にタスクを実行し続けるかどうか
  • コンテナの開始時に実行するコマンド
  • (オプション) コンテナの開始時に渡す環境変数
  • タスクのコンテナで使用するデータボリューム
  • (オプション) タスクでアクセス権限の取得に使用する IAM ロール

 2018-09-21 15.22.00.png
この図でいう、Container definitionとTask definitionの部分を作る


 2018-09-07 10.39.48.png

新しいタスク定義の作成をクリック

コンテナの起動タイプの選択

FargateかEC2のどちらにホスティングするか決める

 2018-09-07 10.53.49.png

AWS Fargateは、AWS re:Invent 2017のKeynoteで発表され、2018年7月3日に東京リージョンに対応された新しいサービス
従来はコンテナの実行環境として、EC2を選択してプロビジョニングする必要があったが、Fargateを使うとそれが不要
今までは、EC2とコンテナの管理を考える必要があったが、Fargateを使うとコンテナだけ考えれば良くて、スケールもFargateがやってくれる的な理解をした

せっかくなので、今回はFargateを使ってみます

Fargateを使わずに、従来のようにEC2インスタンス上でコンテナを動かしたい場合は、EC2を選択する

タスクとコンテナの定義の設定

 2018-09-07 19.06.32.png

設定名 設定値
タスク定義名 適当な名前
タスクロール なし

今回はタスクから他のAWSサービスにリクエストはしないので、タスクロールはなし

■ awsvpcネットワークモードについて
今までは、セキュリティグループなどの情報をもつENI(Elastic Network Interface)をEC2(ホスト)に設定してタスクに共有していたが、awsvpcでは直接タスクにENIを割り当てることが可能になる
Fargateの場合、EC2をプロビジョニングしないため、awsvpc固定

タスクの実行IAMロール

 2018-09-07 19.34.39.png

こちらのロールはタスクを実行するためのロールを設定する
Fargateでは、ログをCloudWatchに公開する必要があるので、ロールの設定は必須とのこと

今回は「新しいロールの作成」を選択し、自動的に作成してもらう
これを選ぶと、タスク定義の作成時に、ecsTaskExecutionRoleというロールが自動的に作られる
IAMで中身を見ると、CloudWatch LogsのWrite権限が付与されていることが分かる

タスクサイズ

 2018-09-10 14.55.54.png

こちらはタスクのメモリとCPUを指定する
Fargateでは、必須とのこと

今回はメモリやCPUを使うタスクは無さそうなので、最小構成のメモリとCPUにした

コンテナの追加

ここからはコンテナ定義を作成する

コンテナの追加をクリック

 2018-09-13 12.59.59.png

スタンダード

 2018-10-01 18.25.58.png

設定名 設定値
コンテナ名 適当な名前
イメージ ECRのリポジトリのURI
プライベートレジストリの認証 なし
メモリ制限(MB) 設定なし
ポートマッピング 9090

■ メモリに関して
タスクに設定したメモリより小さい値を設定する必要がある

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/AWS_Fargate.html
ただし、AWSの開発ガイドを見てみると、コンテナのメモリはオプションで、
「ほとんどのユースケースでは、タスクレベルでこれらのリソースを指定するだけで十分です。」
って書いてあるので、今回は設定しなかった

■ ポートに関して
Fargateを使うとawsvpcネットワークモードに固定となる
bridgeネットワークモードが使えないため、ホストと異なるポートマッピングはできない
よって、EC2を選んだ場合と違い、Fargateの場合はコンテナのポートのみを指定すれば良い

HEALTHCHECK

 2018-09-20 13.10.23.png

タスク内のコンテナのヘルスチェックを定義できる
ヘルスチェックのコマンドの設定やヘルスチェックの実行間隔、リトライなどを定義する

今回は設定なし
(チャットボットを呼んで反応無ければ、死んでるって判断できそうだったので)

環境

 2018-10-01 20.14.39.png

コンテナに渡すコマンドや環境変数などを設定する

このコンテナに割り当てるCPUユニット数はタスクに設定したCPUの値以下にする必要がある
ただし、Fargateでは、省略可能とのこと

ChatWorkアダプターが参照するトークンやルームIDなどを環境変数として、ここで設定する
(DockerfileのENV命令と同様)

ネットワーク設定

 2018-09-20 13.44.41.png

コンテナレベルでのネットワーク設定

今回は設定なし

ストレージとログ

 2018-09-20 13.53.37.png

ログとか設定
Fargateでは、awslogsのみをサポートしている

今回は設定なし

リソースの制限

 2018-09-20 14.00.55.png

コンテナが利用するリソースを制限する

今回は設定なし

DOCKERラベル

 2018-09-20 14.06.08.png

docker runのlabelオプションにマッピングする
環境変数みたいなものだが、ラベルはコンテナ内で実行中のプロセスから参照不可

今回は設定なし

クラスターの作成

クラスターは、先程作成したタスクや後述で作成しているサービスをグルーピングできる

 2018-09-21 15.22.21.png

この図でいう、Clusterの部分を作る


 2018-09-21 17.30.32.png

クラスターの作成をクリック


 2018-09-21 17.31.31.png

クラスターもFargateにした


 2018-09-21 17.49.34.png

クラスター名に適当な名前を設定して、作成

サービスを作成

サービスでは、以下のような項目を設定する

  • 使用するタスク定義
  • サービスを実行するクラスター
  • サービスに配置するタスク数
  • ネットワークの設定(VPCとセキュリティグループ)
  • ELB
  • ELBのヘルスチェック
  • Auto Scaling

 2018-09-21 15.22.09.png

この図でいう、Serviceの部分を作る


 2018-10-01 13.07.38.png

作成をクリック

サービスの設定

 2018-10-01 18.17.20.png

設定名 設定値
起動タイプ FARGATE
タスク定義 hubot:1
プラットフォームのバージョン LATEST
クラスター hubot
サービス名 適当な名前
サービスタイプ REPLICA
タスクの数 1
最小ヘルス率 50
最大率 200

■ サービスタイプに関して
・REPLICA
クラスター全体で必要なタスクの実行数を指定する

・DAEMON
ホストの増減に合わせて、タスクの実行数を制御する
Fargateではサポートされていない

■ 最小ヘルス率と最大率に関して
タスク数に対して、最小ヘルス率は最低でもタスク数を維持する値(タスク数2に対して、最小ヘルス率が50%ならばタスク数は最低1つは維持)
最大率は起動するタスク数の最大値(タスク数2に対して、最大率が200%ならばタスク数は最大4つになる)

ネットワーク構成

VPC とセキュリティグループ

この辺は今AWSを使っている環境に合わせて設定してください

Elastic Load Balancing(オプション)

今回は設定なし

サービスの検出 (オプション)

今回は設定なし

Auto Scaling (オプション)

 2018-10-01 19.59.40.png

今回は設定なし

サービス及びタスクが正常稼働しているか確認

サービス
 2018-10-02 9.56.06.png


タスク
 2018-10-02 9.56.36.png

Hubotのコード管理

Hubotのコード(CoffeeScript)管理をGitHubなりで管理しないと辛いので、GitHubへのpushをフックして、ECSへデプロイする仕組みを作っておいた方が良い
今回は使い慣れているCircleCIで作成した
使ったことないけど、AWS CodePipelineでも良さそうです

.circleci/config.yml
references:
  commands:
    setup-docker: &setup-docker
      ...
      environment:
        AWS_ACCESS_KEY_ID: XXXXXXXXXX
        AWS_SECRET_ACCESS_KEY: XXXXXXXXXX
        AWS_DEFAULT_REGION: ap-northeast-1
        ECR_REGISTRY_NAME: XXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com

jobs:
  ...
  build-hubot:
  <<: *setup-docker
  steps:
    - checkout
    - setup_remote_docker
    - run:
        name: Login ECR
        command: $(aws ecr get-login --no-include-email)
    - run:
        name: Deploy
        command: |
          ROOT_DIR=$(pwd)
          docker build -t hubot ${ROOT_DIR}/docker/hubot/
          docker tag hubot:latest ${ECR_REGISTRY_NAME}/hubot:latest
          docker push ${ECR_REGISTRY_NAME}/hubot:latest
          ecs-deploy -c hubot -n hubot -t 300 -i ${ECR_REGISTRY_NAME}/hubot:latest

workflows:
  ...
  jobs:
    - build-hubot:
      filters:
        branches:
          only:
            - master

https://github.com/silinternational/ecs-deploy
このツールがすばらしくて、面倒なサービスやタスクの更新を引き受けてくれる
使うときは、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_DEFAULT_REGIONを環境変数に設定しておく必要がある

さいごに

Amazon EKSでなく、ECSを使った理由の1つにEKSは現在(2018/10)、東京リージョンが無いっていうのがあったんですが、今回みたいなパフォーマンスをあまり気にしない案件であれば、海外リージョンのEKSで良かったかもしれません
将来的にもKubernetesベースの方が良さそうな気がします
ただ、現状はFargateやCodePipelineのサポートがあり、使いやすいので、ECSでもいいかなと思います

13
13
0

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
13
13