2017年4月10日月曜日

ECS と ALB を組み合わせてコンテナを簡単にスケールアウトする

概要

ECS と ALB を連携してコンテナアプリケーションのスケールアウトを行ってみました
ECS にはホスト側のポートを動的に決定する仕組みがあり、その動的に割り振れたポートを ALB に接続することでスケールアウトを実現します

環境

  • CentOS 7.3
    • docker 17.03
    • ruby 2.3.3
    • gem 2.6.11
    • aws cli 1.11.71
  • ECS, ALB (2017/04/05 時点)

ECS の作成

前回 チュートリアルから基本的なコンポーネントを作成しました
今回もその方法で作成していきます
基本的な流れは同じなのでポイントだけ紹介します

「Amazon ECS クラスターにサンプルアプリケーションをデプロイする」「Amazon ECR によりコンテナイメージをセキュアに保存する 」には両方チェックして次に進みます

レジストリですが今回はアプリケーションをスケールさせたときにどのコンテナにリクエストが行っているかちゃんと確認するために独自のコンテナアプリを作成します
ecs_with_alb1.png

ついでに作成したレジストリにイメージを push します
独自アプリは sinatra を使っています

  • aws ecr get-login –region ap-southeast-2
    • docker login コマンドが表示されたらそのままそれを使ってログインする
  • bundle init
  • vim Gemfile
gem "sinatra"
  • vim app.rb
require 'sinatra'

set :bind, '0.0.0.0'

get '/host' do
  `hostname`
end
  • vim Dockerfile
FROM ruby:latest

ADD . /work
WORKDIR /work
RUN bundle install

CMD ["bundle", "exec", "ruby", "app.rb"]
  • docker build -t simple-sinatra-app .
  • docker tag simple-sinatra-app:latest 123456789012.dkr.ecr.ap-southeast-2.amazonaws.com/simple-sinatra-app:latest
  • docker push 123456789012.dkr.ecr.ap-southeast-2.amazonaws.com/simple-sinatra-app:latest

で OK です
ECS の作成画面はイメージを push したあとで次に進んでください

次にタスクの設定ですが、ここの「ポートマッピング」の設定でホストポートを 0, コンテナポートを 4567 にします
ホストポートを 0 にすることでホスト側のポートを動的に決定することができます
ecs_with_alb2.png

サービスはとりあえずデフォルトのままで OK です
あとで ALB を作成したあとで新しいサービスを作成します

クラスタの設定もそのままで OK です
SSH などは必要に応じて作成してください

あとは確認し問題なければ作成を開始してください

EC2 コンテナホストが所属する VPC ID を確認する

チュートリアル方式で ECS を作成すると EC2 コンテナホストの設定も自動で行われます
ALB を作成する際にどの VPC 配下にいるコンテナを組み込むかという設定が必要になります
なので、ECS が作成できたら EC2 コンテナホストが所属する VPC を確認してください

クラスタ -> デフォルト -> ECS インスタンス -> インスタンスを選択 -> 画面が飛んだら EC2 の画面で VPC ID を確認

EC2 コンテナホストが所属するセキュリティグループの設定を確認する

チュートリアルで作成した場合セキュリティグループも設定を確認したほうがいいと思います
おそらくデフォルトだとインバウンドの設定が以下になっていると思います

  • プロトコル -> TCP
  • ポート範囲 -> 0
  • 送信元 -> 0.0.0.0/0

これだと動的に割り振れれたポートにアクセスできないのでポートの範囲を以下のように変更します

  • ポート範囲 -> 0 - 65535

送信元などは必要に合わせて変更してください

ALB の作成

次に ALB を作成します
EC2 の管理画面画から作成します
ロードバランサーを選択し「ロードバランサーの作成」を選択します
次にロードバランサーのタイプを選択する画面になると思います
ここでは必ず「Application Load Balancer」を選択します

次に ALB の設定です
名前など設定します
ALB が LISTEN するポートは 80 にしています
ecs_with_alb3.png

その下で VPC の設定をします
ここで先程確認した VPC ID を必ず選択するようにしてください
ここが間違うとスケールしたコンテナがうまく ALB にぶら下がってくれません
サブネットを 2 つ以上選択したら次に進みます
ecs_with_alb4.png

セキュリティの設定はとりあえずスルーします

セキュリティグループの設定は今回は default を選択します
アクセス元など絞りたい場合は独自のセキュリティグループを適宜設定してください

ターゲットグループの作成です
新しく ECS のコンテナを管理するターゲットグループを作成しましょう
ポートはアプリが LISTEN する 4567 にしヘルスチェックのパスを今回のアプリが動作する「/host」に変更します
ecs_with_alb5.png

ターゲットの登録は何もしません
すでに ECS コンテナインスタンスが割り当てられていることが確認できると思います
あとは作成すれば OK です

ALB が所属するセキュリティグループの設定を確認する

今回 default を選択しましたがおそらく外部からアクセスできない設定になっていると思います
ALB は 80 番ポートで LISTEN する設定にしているので 80 番ポートでアクセスできる設定を入れてあげましょう

サービスを作成し直す

チュートリアルで作成したサービスを削除し先程作成した ALB を使用するサービスを作成します
クラスタを選択しサービスタブから既存のサービスを削除します
エラーが出て削除できない場合はタスク数が 1 以上になっていると思うので 0 にしてから削除します

削除できたら新規でサービスを作成していきます
サービス名を決定しタスクの数を設定します
タスクの数はとりあえず 1 にしておきましょう (あとからここの数を変更してスケールアウトさせてみます)
ecs_with_alb6.png

ELB の選択で「Application Load Balancer」を選択します
ecs_with_alb7.png

そしてタスクを追加したら以下のように設定します
ターゲットグループは先程作成したターゲットグループを選択しましょう
ecs_with_alb8.png

これで保存しサービスを作成します

動作確認

これでコンテナが ALB にぶら下がり ALB 経由でアプリにアクセスできるようになります
EC2 のロードバランサーのターゲットグループのターゲットタグを確認するとコンテナが「healthy」の状態でぶら下がっているのが確認できると思います
ecs_with_alb9.png

この状態で ALB にデフォルトで振られているドメインにアクセスしてみましょう
http://albforecs-1234567890.ap-southeast-2.elb.amazonaws.com/host (URL はダミーです)

するとコンテナのホスト名が表示できると思います
何度かアクセスしてみて表示されているホスト名が変わらないことを確認してください

コンテナをスケールアウトさせてみる

では、スケールアウトさせてみます
先程作成したサービスのタスクの数を 1 -> 3 くらいまで増やしてみましょう (5 にしても 3 までしか増えなかったのでとりあえず 3 にしました)

これで再度 ALB にアクセスするとホスト名がちょくちょく変わるのが確認できると思います
ALB のターゲットグループを見ると healthy なターゲットが 3 つに増えていることも確認できると思います

最後に

ECS + ALB で web アプリコンテナをスケールアウトしてみました
やってることは単純なのですが概念を理解したり VPC やセキュリティグループまで絡んでくるので結構ハマりポイントが多かったです

ステートレスな Web アプリならこれで単純にスケールアウトできそうです
セッションなどを管理する必要がありアプリがステートフルな場合は、アプリ側でもう少し頑張る必要があるかなと思います

Tips

作成した ECS のリソースでクラスタを削除しようとするとエラーになると思います
その場合は

alb 削除 -> ターゲットグループ削除 -> VPC (インターネットゲートウェイ) -> 使っていた VPC からインターネットゲートウェイをデタッチ

としてからクラスタを削除してみてください

参考サイト

0 件のコメント:

コメントを投稿