LoginSignup
6
7

More than 5 years have passed since last update.

決めろ最強のECS! 〜起動タイプ × 負荷分散 × デプロイ方法で自分だけのアーキテクチャ〜

Last updated at Posted at 2019-02-06
1 / 16

決めろ最強のECS! 〜起動タイプ × 負荷分散 × デプロイ方法で自分だけのアーキテクチャ〜

※このノートはJAWS DAYS 2019懇親会LTの発表の詳細です!


アジェンダ

  • 起動タイプ
  • 負荷分散
  • デプロイ方法
  • 実際のシナリオ
  • まとめ

起動タイプ

  • ec2
  • fargate

ec2

Pros:
* コスト面でfargateに勝る

Cons:
* インスタンスの死活を気にする必要が出てくる


fargate

Pros:
* EC2インスタンスを作成しないため、環境構築の手順を減らせる!
* インスタンスに物理的に入ることができないため、監査が楽(と思われます)!
Cons:
* 2019年2月時点ではドキュメントがそこまで多くなく、ecs-cliとの組み合わせなど応用的(?)なことを試すと事例が探しづらい。
* IPアドレスを固定できないため、何らかの負荷分散方法と組み合わせないとインターネットからアクセスできるようにできない


負荷分散

  • ALB
  • API Gateway + NLB
  • サービスディスカバリ

ALB

Pros:
* パスベースマッピングが重宝する
* WAFをセットできる

Cons:
* 普通はALBで十分だと思われるが...API Gatewayにある機能がこちらにも欲しくなる!


API Gateway + NLB

Pros:
* APIを構築する上ではとても便利!
* カスタムオーソライザーの提供
* ex) アクセストークンをみてリクエストヘッダーを書き換える)
* マネージドなAPIのバージョン管理
* VPC_LINKでNLBをプライベートサブネットに置くことができる。
* API Gatewayをプロキシ統合にすれば、ルーティングは実質アプリのフレームワークで握ることができる → 開発者に嬉しい!!!

Cons:
* パスベースのマッピングができない。
* 複数のECSサービスをインターネットと接続する場合、一つのNLBではそれらのサービスをインターネットに接続することができない。
* 内部にロードバランサーを置く、NLBより手前でポート番号を変換するなど方法は考えられる


サービスディスカバリ

Pros:
* あくまで名前解決なので、gRPCやWebSocketを使いたい場合にも便利
* 名前で参照するため、サーバー間の参照方法が環境・デプロイ結果に依存しない

Cons:
* 2019年2月時点ではドキュメントが多くない


デプロイ方法

  • CloudFrmation
  • ecs-cli
  • Terraform(今回は対象外)
  • CDK(今回は対象外)

CloudFormation

Pros:
* 先行事例が多い
* ロードバランサーやサブネットの指定時に!Refで参照できる

Cons:
* タスク定義を更新した場合、サービスを自前で再起動する必要がある
* justInCaseではsilinternational/ecs-deployを利用しています


ecs-cli

Pros:
* docker-compose.ymlを利用できる
* タスク定義を更新した場合のサービスの再起動について考慮が不要になる
* ECRとECSのサービスがクロススタック参照で依存しないので、スタックを削除するときにテンプレートをごにょごにょしないてOK

Cons:
* コマンドの癖が若干強い
* ex) サービス作成時と更新時でサービスディスカバリを利用するオプションが異なる
* ...もしかして、CIでヘビーにデプロイすることは想定されていない???
* CloudFormationではないので、クロススタック参照を使ってリソースを参照できない

ecs-cliでサブネットやロードバランサーを動的に指定するとちょっと大変でした。次のページを参照。


SAMPLE: ecs-cliでサブネットやロードバランサーを動的に指定する

AWS_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r .Account)
export IMAGE="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${ENV}-app"
export LOGS_GROUP="/aws/ecs/task/${ENV}-App"
export LOGS_REGION="${AWS_DEFAULT_REGION}"
export TASK_ROLE_ARN="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`TaskRoleArn`].OutputValue' --output text)"
export EXECUTION_ROLE_ARN="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`TaskExecutionRoleArn`].OutputValue' --output text)"
export TARGET_GROUP_ARN="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`TargetGroupArn`].OutputValue' --output text)"
export VPC_ID="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`VpcId`].OutputValue' --output text)"
export SUBNET1="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`ECSSubnet1aId`].OutputValue' --output text)"
export SUBNET2="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`ECSSubnet1cId`].OutputValue' --output text)"
export SECURITY_GROUP="$(aws cloudformation describe-stacks --stack-name ${ENV}-infrastracture --query 'Stacks[0].Outputs[?OutputKey==`ECSSecurityGroupId`].OutputValue' --output text)"
export MYSQL_HOST=${MYSQL_HOST}
export MYSQL_USERNAME=${MYSQL_USERNAME}
export MYSQL_PASSWORD=${MYSQL_PASSWORD}
[ $(aws ecs list-services --cluster ${ENV}-ECSCluster --query 'serviceArns' | grep \".*/app\") ] && export SERVICE_DISCOVERY_DEPLOYMENT_OPTION="--update-service-discovery" || export SERVICE_DISCOVERY_DEPLOYMENT_OPTION="--enable-service-discovery"
# ↑↑ ecs-cliでサービスディスカバリを有効にする場合、初回起動では `--enable-service-discovery`オプションを、更新では `--update-service-discovery`オプションを有効にする必要がある...
ecs-cli compose --project-name app -f ecs/docker-compose.yml --ecs-params ecs/ecs-params.yml service up \
    ${SERVICE_DISCOVERY_DEPLOYMENT_OPTION} --private-dns-namespace local --vpc ${VPC_ID} \
    --container-name app --container-port 8080 --cluster ${ENV}-ECSCluster --target-group-arn ${TARGET_GROUP_ARN} --launch-type FARGATE --timeout 10

実際のシナリオ

  • toBでAPIを提供する
  • 認証はCognito Userpoolを使うが、認可サーバーは自前/サードパーティのものを使う
  • ECSサーバーはプライベートサブネットに置きたい
  • ECSサーバー同士の相互参照がありえる
  • 構築初期なので、スタックの削除もそこそこやる可能性がある

→ API Gateway + NLB + ECS on fargate w/ ecs-cliで構築


まとめ

要件によって起動タイプ x 負荷分散 x デプロイ方法 を使い分けて、自分だけのECSのアーキテクチャを見つけ出そう!

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