概念図

とりあえずECSに出てくるエンティティがそれぞれどんな多重度で関連しているのかをまとめてみました。ここからはそれぞれのエンティがどんな概念なのかを解きほぐしていきたいと思います。

図1 概念図
EC2 Container Serviceの概念図

Serviceが中心

ECSは平たく言うと

  • クラスター(=複数EC2インスタンスの集合)の上で
  • Dockerコンテナを使って、
  • Serviceを動作させる

ものです。

図2 例えばの構成
例

上図は、

  1. Front Service
    (裏にいるAPIをCallしてWEB UIを提供するもの)
  2. API Service
    (ビジネスロジック、DBへの読み書きをRESTful APIで提供するもの)

と言う2つのService で構成されるWEBアプリケーションの例です。

ECSで言うServiceは、Serviceは利用者から見た「サービス」よりも一段階か二段階細かいもので、APIサーバーとか、フロントサーバーとかそういった単位の単機能なものです。ロールとかそういう言い方が近いのかもしれません。
(作り方によってはサービス=Serviceにもできるのですが、ECSのスケールアウトが容易であるという特性を使うためには先に述べたような単機能な単位になってくるかと思われます。)

Serviceってなんなの?

最初の時点では非常に説明しづらい概念なのですが、以下の情報を管理するものです。

管理する情報 指定する方法
どんなコンテナを起動するのか どのTask Definitionを使うかを指定する
何個起動するのか Number of Tasksとして常時起動しておきたい個数を指定する
リクエスト分散するのか コンテナとELBの紐付けを指定する

Serviceの実体はDockerコンテナである

さて、実行中のServiceというのは複数個のDockerコンテナの集合体です。
上の図2の例では

  • Front Serviceは2種類のコンテナから成り立つ
    • expressのアプリケーション のコンテナ
    • nginx(expressにプロキシする) のコンテナ
  • API Serviceは1種類のコンテナから成り立つ
    • Djangoを使ったAPI実装 のコンテナ

という構造を表しています。(今回の例ではDBはRDSを利用するものとして、ECSの外の要素としています)

Dockerコンテナを束ねるのがTask

図2の例では計3種類のコンテナが動作している図ですが、3種類それぞれがバラバラに管理されている訳ではありません。
Taskと言う単位で2つのグルーピングがされています。

  1. Fornt Task
    • express コンテナ
    • nginx コンテナ
  2. API Task
    • Django コンテナ

Taskは複数個並列で動く

さて、図2は、

  1. Front Service の中で FrontのTaskが3個 起動している
  2. API Service の中で 、APIのTaskが4個 起動している

と言う状態を示しています。

図2のような構成を物理で組んだ場合には当然ながら対障害性、負荷分散を目的として冗長化をするかと思います。

このような冗長化をする場合、ELBを使って分散する事になるかと思いますが、ECSでも同様にELBを使用します。
ECSではServiceに一つELBを指定します。
ELBの作成自体は事前に済ませておき、既存のELBを指定する感じになります。
(ELBを使わないNo ELBも選択可能です。その場合はDNSラウンドロビンなどの方法を取ることになるでしょう)

Taskの定義はTask Definition(ってそんまんま)

オブジェクト指向の喩えでタスクをインスタンス(オブジェクト)とするとTask Definitionはクラスになります。
Task DefinisionはほぼほぼDockerコンテナの起動方法を指定するもので、Docker Composeのcompose.ymlファイルとだいたい同じです。

Task DefinitionはJSON形式で記述する設定ファイルで、書き方についてはとりあえずこちらを見てねという形でお茶を濁しておきます。
http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html

ということでServiceの作り方

まずServiceはTask Definitionを元にして作ります。
Screenshot from 2015-10-13 23:11:14.png

createservice.png

項目 なんとなく説明
Task Definition Serviceの元となるTask DefinitionでTask Definitionは事前に作成されている必要があります
Cluster Serviceを動作させるクラスタを指定します(後述)
Service name Serviceの識別子で適当にわかりやすい名前をつけてください
Number of tasks このService上でTaskをいくつ動かすかを定義します。あとから変更可能です。
Load Balancer 前述の通り負荷分散するためのELBの名前と使うポート番号を指定します。

クラスター

クラスターはContainer Instanceの集合体で、要するにEC2インスタンスの集合体です。
クラスター内のそれぞれのインスタンスはただのリソース量(CPU,メモリ,ポートを供給するリソース量)として捉えられ、個々はあまり重要ではありません。

  • 足りなくなればインスタンスを足せリソース量が増える
  • 状況に対してリソース量が過剰であればインスタンスを減らす

というもので、どのインスタンス上で何のタスクを動かすかはECSの采配で自動的に決まります。

Container Instance

Container InstanceとなるEC2インスタンスは、

  • Docker入り
  • Amazon ECS Container Agent 入り

である必要がありますが、通常はECS最適化されたAMIからインスタンスを作るので特に気にする必要はないでしょう。
2017/11時点での最新のAMIはamzn-ami-2017.09.b-amazon-ecs-optimizedですが、ECS Container AgentのアップデートとともにAMIもアップデートされていくので下記の公式ページを時々チェックすると良いでしょう。

http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-optimized_AMI.html

また、Container Instanceを構成するためには以下も必要になります。

  • インスタンスにアタッチするIAMロール
  • ECSクラスタの名前(インスタンスのuser-dataに以下のように設定する)
user-data
#!/bin/bash
echo ECS_CLUSTER=MyCluster>> /etc/ecs/ecs.config

See:

普通はAuto Scalingグループを使う

上記のようなEC2インスタンスをポコポコ作っていけばクラスタのメンバーを増やしていく事ができますが、結構面倒です。普通はAuto Scalingグループを使うことになるでしょう。
ECSの管理画面を初めて起動した時に出てくるチュートリアルを実施すると上記のような起動設定のAuto Scalingグループが作られるので、その起動設定をコピーしてAuto Scalingグループを作ってインスタンス管理をするのが良いでしょう。

クラスタの上でService、タスクがどう動くのか

図3:クラスターの上でタスクが動いているの図

  • Frontサービスはタスクを2つ起動
  • APIサービスはタスクを3つ起動

上図3-AはHogeクラスター上でFront、APIの両サービスを稼働させている例です。
お財布都合でインスタンス数を抑えたい時にはこのようなクラスタ構成になるでしょう。
ただし状況によっては逆にリソースが有効に使われていないインスタンスがあるかもしれません。(図3-パターンAの003の例)

図3-Bはfront用とapi用でクラスターを分けている例です。
ピーク特性などが違う場合にはこちらのパターンのようにクラスタを分けて構成したほうがインスタンス数の調整はし易いでしょう。この例では1インスタンスに一つのTaskとなることでそれぞれのインスタンスタイプは下げる事ができて、結果的にお財布に優しくなるかもしれません。

さて、上図3(A,Bとも)ではfrontのタスクが別インスタンスに分散されていますが、CPU,メモリといっったリソースの状況が許せば一つのインスタンス上で複数タスクが動作するという事も有り得ます。

ECSが出た頃の2015年当時はELBと組み合わせるためにタスクのポートホストのポートにマッピングする必要があり、上記の構成ではホストの80番ポートの衝突をするという理由でfrontタスクが同じインスタンス上で複数動作することはかないませんでしたが、2016年に登場したALBによってこの縛りはなくなりました。ALBと動的ポートを使ったロードバランスにすいてはこちらを参照してください。

ちょっと嘘つきました

ECSは平たく言うと

  • Dockerコンテナを使って、
  • クラスターの上で
  • Serviceを動作させる

ものです。

実はクラスターの上ではServiceだけではなくて、タスクを直接動作させることもできます。
バッチジョブなどがこれに該当するでしょう。


Google Container Engine(GKE)も大体似たような概念になっています。
余力があれば別途GKEについても書きたいと思います。