「初老丸の独り 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
等)が利用可能
高可用性、耐久性
共有
- リポジトリ内で AWS のリソースタグが利用可能
- リソースレベルのアクセス制限によりアカウントを越えてコンテナイメージを共有することが可能
アクセスコントロール
- IAM によってコンテナイメージへのアクセス制限を設けることが出来る
暗号化
- 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
でイメージを ECR リポジトリに登録する
$ 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 --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
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
$ 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 の連携をしてみる。
教材はいつものように。
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 にて確認。
そして...暫くすると 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 を適切に付与すること。ここだけ気をつければ簡単に連携を試すことが出来ると思う。
以上。