ようへいの日々精進XP

よかろうもん

(ショロカレ 23 日目)Amazon ECR をもう一時間使ってみた(aws-cli による操作と ECS との連携を試す)

「初老丸の独り Advent calendar 2015」の二十三日目の記事です。

追記

コンテナインスタンスに付ける IAM role のポリシーを Amazon Managed Policy に変更した。

inokara.hateblo.jp

助言を頂いた @riywo さん、有難う御座いました!


tl;dr

inokara.hateblo.jp

では、触ってみただけだったので、少しうんちくを参考資料などから拝借する。


うんちくとか

なんぼ?

Amazon ECR って利用するのになんぼくらいするの?(現在はヴァージニア料金)

  • ストレージ使用料 0.10 USD/GB/月
  • Amazon ECR からのデータ転送量が発生

お楽しみの無料枠は...

  • 500MB/月
  • 翌月繰り越しは出来ないとの(携帯電話みたい)

ECR の特徴

こちらからの抜粋。

ECS との連携

  • ECS で稼働しているコンテナイメージを管理することが出来る
  • タスク定義で ECR を指定してイメージを取得することが出来る

Docker 互換

  • Docker Registry HTTP API V2 がサポートされている
  • Docker コマンド(push / pull / list / tag 等)が利用可能

高可用性、耐久性

  • コンテナイメージは S3 に保存される

共有

  • リポジトリ内で AWS のリソースタグが利用可能
  • リソースレベルのアクセス制限によりアカウントを越えてコンテナイメージを共有することが可能

アクセスコントロール

  • IAM によってコンテナイメージへのアクセス制限を設けることが出来る

暗号化

  • コンテナイメージの送受信は HTTPS 経由で行われる
  • 保存されたイメージは Amazon S3 のサーバー側で自動的に暗号化される

モニタリング

  • CloudWatch を利用してモニタリングされる
  • コンテナイメージサイズ、ストレージ、データ転送などのリソース消費状況を確認することが出来る

制限事項

こちらを抜粋。

以下は申請により変更が可能(と思われる)。

Resource Default Limit
1 アカウントあたりの最大リポジトリ 1,000
1 リポジトリあたりの最大イメージ数 500

以下は変更不可。

Resource Default Limit
1 イメージあたりの最大 layer 数 127 (this is the current Docker limit)
最大 layer part サイズ 10 MiB
最小 layer part サイズ 5 MiB (except the final layer part in an upload)
最大 layer parts 1,000 MiB

もう一時間くらい

awscli と docker コマンドだけで操作してみる

$ aws --region us-east-1 ecr create-repository --repository-name oreno-docker-repo
{
    "repository": {
        "registryId": "xxxxxxxxxxxxx",
        "repositoryName": "oreno-docker-repo",
        "repositoryArn": "arn:aws:ecr:us-east-1:xxxxxxxxxxxxx:repository/oreno-docker-repo"
    }
}
$ aws --region us-east-1 ecr describe-repositories
{
    "repositories": [
        {
            "registryId": "xxxxxxxxxxxxx0",
            "repositoryName": "oreno-docker-repo",
            "repositoryArn": "arn:aws:ecr:us-east-1:xxxxxxxxxxxxx:repository/oreno-docker-repo"
        },
        {
            "registryId": "xxxxxxxxxxxxx",
            "repositoryName": "oreno-registory",
            "repositoryArn": "arn:aws:ecr:us-east-1:xxxxxxxxxxxxx:repository/oreno-registory"
        }
    ]
}
$ aws --region us-east-1 ecr list-images --repository-name oreno-registory
{
    "imageIds": [
        {
            "imageTag": "latest",
            "imageDigest": "sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        }
    ]
}
  • ECR にログインする為の情報を取得(docker login する為の情報を取得)
$ aws --region us-east-1 ecr get-login

以下のようにログイン情報が出力される。

docker login -u AWS -p xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e none https://xxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
  • docker login を利用して ECR にログインする
$ docker login -u AWS -p xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e none https://xxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com

以下のように出力される。

WARNING: login credentials saved in ${HOME}/.docker/config.json
Login Succeeded

尚、${HOME}/.docker/config.json の中身は以下の通り。

$ cat /home/vagrant/.docker/config.json
{
        "auths": {
                "https://xxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com": {
                        "auth": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "email": "none"
                }
        }
}
  • docker build でオリジナルコンテナをビルド
$ docker build -t inokappa/oreno-jenkins .
$ docker tag inokappa/oreno-jenkins xxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo
$ docker push xxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo

The push refers to a repository [xxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo] (len: 1)
0d3bf9ffe6f6: Pushed
4bb741cb567f: Pushing 1.024 kB

(snip)

3375effa7f2a: Pushed
latest: digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx size: 24325
  • イメージを確認
$ aws --region us-east-1 ecr list-images --repository-name oreno-docker-repo
{
    "imageIds": [
        {
            "imageTag": "latest",
            "imageDigest": "sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        }
    ]
}
  • docker run してみる
#
# docker run
#
$ docker run --name jenkins -d -p 8080 xxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo
Unable to find image 'xxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo:latest' locally
latest: Pulling from oreno-docker-repo
Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Status: Downloaded newer image for xxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo:latest
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

#
# docker ps
#
$ docker ps
CONTAINER ID        IMAGE                                                            COMMAND                  CREATED             STATUS              PORTS                     NAMES
aa3ef49191c9        xxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo   "/usr/bin/java -jar /"   46 seconds ago      Up 45 seconds       0.0.0.0:32772->8080/tcp   jenkins

#
# Jenkins コンテナを確認
# 
$ curl -s localhost:32772/api/json | jq .
{
  "views": [
    {
      "url": "http://localhost:32772/",
      "name": "All"
    }
  ],
  "useSecurity": false,
  "useCrumbs": false,
  "unlabeledLoad": {},
  "slaveAgentPort": 0,
  "quietingDown": false,
  "primaryView": {
    "url": "http://localhost:32772/",
    "name": "All"
  },
  "assignedLabels": [
    {}
  ],
  "mode": "NORMAL",
  "nodeDescription": "the master Jenkins node",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs": [],
  "overallLoad": {}
}

ECS との連携を試してみる

やっと本番

以下のように ECS と ECR の連携をしてみる。

f:id:inokara:20151223024101p:plain

教材はいつものように。

github.com

ドキュメントによると ECR との連携については以下の条件を満たす必要がありそう。

  • ECS Container agent のバージョンは 1.7 以上
  • latest バージョンの Amazon ECS-optimized AMI で起動したコンテナインスタンス

但し、今回は Docker 1.9 をインストールした Ubuntu 14.04 で試すことにした。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"

$ sudo docker version
sudo: unable to resolve host ip-10-0-0-93
Client:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 13:12:04 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 13:12:04 UTC 2015
 OS/Arch:      linux/amd64
$ 

ECS コンテナインスタンスに付与する IAM ポリシー

以下をコンテナインスタンスに付与する IAM role に追加する。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:BatchCheckLayerAvailability",
                "ecr:BatchGetImage",
                "ecr:GetDownloadUrlForLayer",
                "ecr:GetAuthorizationToken"
            ],
            "Resource": "*"
        }
    ]
}

terraform のテンプレートは以下のように

terraform のテンプレートは以下のように修正する。

#
# Create ECS cluster
#
resource "aws_ecs_cluster" "oreno-cluster" {
  name = "oreno-cluster"
}

#
# Define task
#
resource "aws_ecs_task_definition" "sample01" {
  family = "sample01"
  container_definitions = <<EOS
[
  {
    "environment": [],
    "name": "oreno-jenkins",
    "image": "xxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo",
    "cpu": 0,
    "memory": 256,
    "portMappings": [
      {
          "containerPort": 8080,
          "hostPort": 8080
      }
    ],
    "command": [
    ],
    "essential": true
  }
]
EOS
}
#
# Define Service(as container start)
#
resource "aws_ecs_service" "sample01" {
  name = "sample01"
  cluster = "${aws_ecs_cluster.oreno-cluster.id}"
  task_definition = "${aws_ecs_task_definition.sample01.arn}"
  desired_count = 1
}

コンテナイメージを指定する際に ECR のリポジトリを指定する。

apply

apply すると以下のように。

$ make tf-apply

(snip)

Outputs:

  CloudWatch Logs Log Group Name = docker-logging
  EC2 IP address                 = xxx.xxx.xxx.xxx
  EC2 Instance ID                = i-xxxxxxxx
  ECS Cluster Name               = oreno-cluster

terraform apply で適用する。

確認

マネジメントコンソールの Task Definitions にて確認。

f:id:inokara:20151223021010p:plain

そして...暫くすると Task に登録された Jenkins コンテナが起動しているはずなので確認する。

$ curl -s xx.xx.xxx.xx:8080/api/json | jq .
{
  "views": [
    {
      "url": "http://xx.xx.xxx.xx:8080/",
      "name": "All"
    }
  ],
  "useSecurity": false,
  "useCrumbs": false,
  "unlabeledLoad": {},
  "slaveAgentPort": 0,
  "quietingDown": false,
  "primaryView": {
    "url": "http://xx.xx.xxx.xx:8080/",
    "name": "All"
  },
  "assignedLabels": [
    {}
  ],
  "mode": "NORMAL",
  "nodeDescription": "the master Jenkins node",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs": [],
  "overallLoad": {}
}

念のため、ECS Container Agent のログを見てみる。

$ sudo docker logs ecs-agent

(snip)

2015-12-22T16:56:40Z [INFO] Creating container module="TaskEngine" task="sample01:3 arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/4a5bf09f-cc8e-4908-b351-d2451201a051, Status: (NONE->RUNNING) Containers: [oreno-jenkins (PULLED->RUNNING),]" container="oreno-jenkins(xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo:latest) (PULLED->RUNNING)"
2015-12-22T16:56:40Z [INFO] Created container name mapping for task sample01:3 arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/4a5bf09f-cc8e-4908-b351-d2451201a051, Status: (NONE->RUNNING) Containers: [oreno-jenkins (PULLED->RUNNING),] - oreno-jenkins(xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-docker-repo:latest) (PULLED->RUNNING) -> ecs-sample01-3-oreno-jenkins-ead1bcfd81ba9fe91400

ECR から docker pull してきているのがなんとなく判る。


以上

ECR と ECS の連携を試してみた。ポイントは IAM Policy を適切に付与すること。ここだけ気をつければ簡単に連携を試すことが出来ると思う。

以上。