Amazon ECSを触ってみる


## 前置き

[Kubernetes Advent Calendar](http://qiita.com/advent-calendar/2014/kubernetes) 22日目 の記事です。

はい、いきなり何言ってんだ状態です

KubernetesのAdventカレンダーなのに、Amazon ECSとは喧嘩売ってるだろとか言われそうですが、kubernetes記事はいろいろ出てきていますが、ちょうど先週Previewがローンチしたばかりで、情報も少ないので、この機会に比較してみようと思います

チュートリアルをすでに、クラスメソッドさんが触っておられるそうなのでネタ不足すぎる感じではありますが・・・
http://dev.classmethod.jp/cloud/ecs-ataglance/

#アーキテクチャ概要

AmazonECSには、kubeletやNode,Podのような概念が今のところありません。
ECS-agentがインストールされた専用のEC2インスタンスを使い、agentがECSの管理サーバデータをロードして制御を行い、agent側でdocker imageのpullや起動停止が行われているようである。(ソースを眺めただけの推測でる）

なお、カスタムAMIにagentインストールして使えるようにする予定もあるらしいです。
現状では、ELBなどの連携等は無い模様。

ということで、図にするとこんな感じ（想像）
![ecs.jpg](https://qiita-image-store.s3.amazonaws.com/0/28157/9cd158b9-91a8-4207-11cb-5be625f2f4b8.jpeg "ecs.jpg")

見て分かる人は分かると思いますが、動作モデルがopsworksに似ている気がします

また、agent自体もdockerコンテナとして動作しています。
専用のEC2インスタンスにログインして、dockerコマンドを叩くと以下のような出力になります。


```
[ec2-user@ip-10-0-1-184 ~]$ docker ps
CONTAINER ID        IMAGE                            COMMAND             CREATED             STATUS              PORTS                        NAMES
d012fb483bea        amazon/amazon-ecs-agent:latest   "/agent"            17 minutes ago      Up 17 minutes       127.0.0.1:51678->51678/tcp   ecs-agent
```

## aws ecsコマンド

aws ecsコマンドで行える操作は以下の通りです
なお、各サブコマンドの後ろにhelpを付けると各コマンドの詳細が表示される(man形式)
また、コマンドは「default」クラスタに向かって制御を送るので、
自分でクラスタを作成している場合には、--clusterをつけて送る必要があります。

| コマンド | 意味 |
|:--|:--|
create-cluster | クラスタを作成 
deregister-container-instance| コンテナに登録されているインスタンスを削除します
deregister-task-definition | タスク削除
describe-clusters | クラスタの詳細を表示する。クラスタの指定は、--clusters
describe-container-instances |  コンテナインスタンスの詳細表示
describe-task-definition | タスクの詳細表示
describe-tasks | タスクの詳細表示
discover-poll-endpoint| エンドポイント表示:{ endpoint": "https://ecs-a-1.us-east-1.amazonaws.com/" }
help |ヘルプ
list-clusters | クラスタの表示
list-container-instances | インスタンス一覧
list-task-definitions | タスク定義一覧
list-tasks | タスク一覧
register-container-instance | agentのみが利用するコマンド. コンテナインスタンスの登録
register-task-definition | タスク定義の登録
run-task | タスクの起動
start-task | タスクの起動？
stop-task| タスクの停止
submit-container-state-change| agentのみが利用するコマンド
submit-task-state-change|agentのみが利用するコマンド

2014.12.22現在以下のコマンドでサポート外のエラーが出る
* deregister-task-definition 

## 動作例

いくつかコマンドを例にして、何が出来るかを見てみます

### クラスタを作る

ECSでいうクラスタとは、dockerコンテナを動作させるEC2インスタンスの塊を指しています。

ユーザがクラスタを作らない場合、「default」をいう名前のクラスタを使っていることになっています。
各コマンドでクラスタ名を指定しない場合、この「default」が使われることになっています

```
aws ecs create-cluster --cluster-name <任意名>
```

作ったクラスタを複数のEC2インスタンスに認識させるためには、EC2のuser-dataに以下を記載

```
#!/bin/bash
echo ECS_CLUSTER=<クラスタ名> >> /etc/ecs/ecs.config
```

### ECSを動かすEC2インスタンスを作成する

2014.12.22現在、ECSからクラスタとして動かせるEC2インスタンスは、AMIID:「 ami-34ddbe5c 」のみです

このEC2インスタンスには、専用のロールを設定しておく必要があります。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "ecs:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
```

それ以外は特に気にする必要もないかなと思います。
Security-groupの設定は適当に。

### コンテナインスタンスを取得する
タスクを実行するための、EC2インスタンスを取得します

```
aws ecs list-container-instances
```

また、コンテナインスタンスの詳細は以下で取得できます。
指定するuuidは、前述のlist-container-instancesで取得したものを指定します

```
aws ecs describe-container-instances --container-instances <uuid>
```

出力された内容から、「ec2InstanceId」を見ると配備されているEC2インスタンスのIDを得ることが出来ます。


### コンテナで動作するタスクを作成・登録を行う。

タスク＝アプリケーションです。
タスク定義の登録にはクラスタが存在しなくても問題ないようです。

kubernetesと同様にjson形式で記述します。
ここでは、wordpressの例を示します。

２コンテナで、APとDBに分かれています。
このjsonは、ECSのTask Definitionのページに記載されています
http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_defintions.html

```
[
  {
    "image": "tutum/wordpress-stackable",
    "name": "wordpress",
    "cpu": 10,
    "memory": 500,
    "essential": true,
    "links": [
      "db"
    ],
    "entryPoint": [
      "/bin/sh",
      "-c"
    ],
    "environment": [
      {
        "name": "DB_USER",
        "value": "root"
      },
      {
        "name": "DB_PASS",
        "value": "pass"
      }
    ],
    "portMappings": [
      {
        "containerPort": 80,
        "hostPort": 80
      }
    ]
  },
  {
    "image": "mysql",
    "name": "db",
    "cpu": 10,
    "memory": 500,
    "essential": true,
    "entryPoint": [
      "/entrypoint.sh"
    ],
    "environment": [
      {
        "name": "MYSQL_ROOT_PASSWORD",
        "value": "pass"
      }
    ],
    "portMappings": []
  }
]
```

実はこのタスク定義、EC2のインスタンスがt2.microだと動作しません。
コンテナが要求するメモリ量が、500mbx2となっているためです。

このまま登録しても、空の配列が返ってくるだけでエラーの詳細が分かりません

t2.microで試される方は、メモリをそれぞれ200くらいに書き換えて試されると良いと思います
（200に設定しても問題なく動作しました）


作成した定義を登録します

```
aws ecs register-task-definition --family <タスク名> --container-definitions file:///sample.json
```

同名のタスク名で登録した場合、versionがカウントアップされ登録される。
登録した定義は、すべてのversionを取り出すことが可能


### 登録されているタスク定義の取得

定義の一覧を取得します

```
aws ecs list-task-definitions
```

定義の詳細を取得します。

```
aws ecs describe-task-definition --task-definition <タスク名:version>
```

### タスクの実行

コンテナインスタンスを起動します

```
aws ecs run-task --task-definition <タスク名:version> --count <インスタンス数>
```

### タスクの停止
コンテナインスタンスを停止します
このとき、停止するためには、list-tasksで止めたいインスタンスのuuidを取得しておく必要があります。

```
aws ecs stop-task --task <uuid>
```

### 実行中タスクの取得
コンテナインスタンスの上で実行されているタスク一覧を取得します

```
aws ecs list-tasks 
```

実行中タスクの詳細を取得します。
指定するuuidは、前述のlist-tasksで取得したものを使います。

```
aws ecs describe-tasks --task <task_uuid>
```

##まとめ

AmazonECSはまだまだこれからなサービスですが、かなりシンプルな作りだということがわかります。
GKEのようにAWSの各種サービスと連携する日も遠くはないでしょう。

kubernetesと同様にコンテナを管理し、サービスを展開するという面では、kubernetes同様に着目していく必要があるのではないでしょうか