Amazon EC2 Container Service (Amazon ECS) – масштабируемый сервис для запуска, остановки и управления Docker-контейнерами в кластере Amazon Elastic Compute Cloud (EC2) инстансов.
В этом посте – обзор ECS, его основных компонентов, и пример создания кластера и запуска задачи в нём с помощью AWS CLI.
Содержание
ECS CLI
Установка
При желании – установим ECS CLI. Дальше в посте использоваться не будет, но в будущем всё-равно пригодится.
Для Linux – выполняем:
$ sudo curl -o /usr/local/bin/ecs-cli https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-linux-amd64-latest $ sudo chmod +x /usr/local/bin/ecs-cli
Проверяем:
$ ecs-cli --version ecs-cli version 0.4.4 (7e1376e)
Настройка
Файл конфигурации ECS CLI – ~/.ecs/config
.
При первом запуске – CLI требуется настроить параметры доступа к AWS аккаунту с помощью опции configure
. Для его вызова – требуется задать параметры доступа, что можно сделать несколькими способами:
- С помощью переменных
AWS_ACCESS_KEY_ID
иAWS_SECRET_ACCESS_KEY
. - При помощи опции
--profile
, указав имя профиля из файла~/.aws/credentials
(см. AWS: именованные профили доступа). - Испольуя опции
--access-key
и--secret-key
самого ESC CLI.
Выполняем:
$ ecs-cli configure --profile default --cluster rtfm-example INFO[0000] Saved ECS CLI configuration for cluster (rtfm-example)
Проверяем:
$ cat ~/.ecs/config [ecs] cluster = rtfm-example aws_profile = default region = aws_access_key_id = aws_secret_access_key = compose-project-name-prefix = ecscompose- compose-service-name-prefix = ecscompose-service- cfn-stack-name-prefix = amazon-ecs-cli-setup-
ESC
Описание
Amazon ECS – сервис по управлению контейнерами в кластере из нескольких Availability Zones в регионе.
Кластер ECS должен работать в AWS VPC, а после запуска кластера – вы должны сконфигурировать EC2 инстансы (ECS Container Instacnes) с Docker, которые будут работать в этом кластере.
Образы Docker хранятся в Docker registry, которые могут быть развернуты в вашем AWS – либо вы можете использовать такие сервисы, как Docker Hub или AWS ECR (Amazon EC2 Container Registry).
Общая схема ECS выглядит так:
Task Definitions
Для запуска вашего приложения в AWS ECS – вы должны создать task definition (“описание задачи”), который представляет собой JSON-файл с описанием одного или более контейнеров. В нём описываются образ, репозиторий, порты, диски, которые будут использоваться контейнерами и т.д.
Пример task definition для запуска одного контейнера с NGINX сервером:
{ "family": "webserver", "containerDefinitions": [ { "name": "web", "image": "nginx", "cpu": 99, "memory": 100, "portMappings": [{ "containerPort": 80, "hostPort": 80 }] }] }
Больше примеров можно найти тут>>>, а описание параметров, используемых в task defenitions – тут>>>.
Вы можете думать о файлах с описанием task defnitions как о docker-compose
или даже Dockerfile
-файлах для ваших сервисов, суть практически та же – описание контейнеров.
Tasks и Scheduling
Task (“задача”) – это выполнение task definition в вашем кластере. Вы можете менять количество задач, запущенных для каждой имеющейся task definition.
Amazon ECS task scheduler – планировщик, отвечающий за размещение задач на ваших инстансах, который имеет несколько опций.
Например – вы можете указать service, который будет запускать и обслуживать несколько задач одновременно.
Подробнее – см тут>>>.
Task можно представлять себе как уже запущенный контейнер, который использует task defenition (“Dockerfile“) для запуска сервиса в нём.
Cluster
Когда вы запускаете выполнение задач в вашем AWS ECS – они выполняются в кластере, который представляет собой логическую группу EC2 инстансов. AWS ECS загружает ваши Docker образы, и запускает соответствующие контейнеры в в кластере.
Подробнее о кластерах – тут>>>, а про ECS Container Instances – тут>>>.
Container Agent
Container Agent работает на каждом инстансе кластера, и отправляет информацию о запущенных на инстансе задачах и используемых ресурсах инстанса непосредственно AWS ECS, а так же выполняет запуск и остановку задач по запросу от ECS.
Сам агент запущен в контейнере, так же, как будут запущены сервисы на этом интансе:
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c74d0ac426af amazon/amazon-ecs-agent:latest "/agent" 2 minutes ago Up 2 minutes ecs-agent
А его настройки хранятся в файле /etc/ecs/ecs.config
:
# cat /etc/ecs/ecs.config ECS_CLUSTER=rtfm-example
Подробнее – см. тут>>>.
Пример создания ECS
Кластер
Далее с помощью AWS CLI мы создадим кластер, поднимем EC2 интанс с ECS-агентом, создадим task defention и запустим сервис с NGINX.
Вы можете использовать кластер по умолчанию (default), либо создать свой с помощью create-cluster
:
$ aws ecs create-cluster --cluster-name rtfm-example { "cluster": { "registeredContainerInstancesCount": 1, "pendingTasksCount": 0, "status": "ACTIVE", "clusterName": "rtfm-example", "clusterArn": "arn:aws:ecs:eu-west-1:264418146286:cluster/rtfm-example", "activeServicesCount": 0, "runningTasksCount": 3 } }
Используя list-clusters
– проверяем:
$ aws ecs list-clusters { "clusterArns": [ "arn:aws:ecs:eu-west-1:264418146286:cluster/rtfm-example", "arn:aws:ecs:eu-west-1:264418146286:cluster/default" ] }
ECS Container Instance
Далее – вы должны создать EC2 инстанс в кластере, на котором будут выполняться задачи.
Ниже представлен список AMI ID для использования в различных регионах:
Region | AMI Name | AMI ID |
---|---|---|
us-east-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-6df8fe7a |
us-east-2 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-c6b5efa3 |
us-west-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-1eda8d7e |
us-west-2 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-a2ca61c2 |
eu-west-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-ba346ec9 |
eu-central-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-e012d48f |
ap-northeast-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-08f7956f |
ap-southeast-1 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-f4832f97 |
ap-southeast-2 |
amzn-ami-2016.09.c-amazon-ecs-optimized | ami-774b7314 |
Можно использовать любой другой AMI, в таком случае – потребуется ручная установка ECS агента.
Для того, что бы ECS агент мог выполнять API запросы к ECS сервису – ему требуется IAM роль ecsInstanceRole.
Проверяем её наличие:
$ aws iam list-roles | grep ecsInstanceRole "Arn": "arn:aws:iam::264418146286:role/ecsInstanceRole", "RoleName": "ecsInstanceRole"
Подробнее про IAM для ECS – тут>>>, а про запуск EC2 для ECS – тут>>>.
По умолчанию – EC2-инстансы, запущенные с этой ролью будут подключены к кластеру default.
Что бы изменить это – создаём файл для user-data
:
$ cat rtfm-cluster.sh #!/bin/bash echo ECS_CLUSTER=rtfm-example >> /etc/ecs/ecs.config
Запускаем AMI ami-ba346ec9, передав ему IAM роль ecsInstanceRole
и файл rtfm-cluster.sh
для user-data
:
$ aws ec2 run-instances --image-id ami-ba346ec9 --key-name my-cluster --instance-type t2.nano --iam-instance-profile Name=ecsInstanceRole --user-data file://rtfm-cluster.sh
При проблемах с подключением – смотрим лог агента на запущенном инстансе:
[ec2-user@ip-172-31-34-31 ~]$ cat /var/log/ecs/ecs-agent.log.2017-01-06-12 2017-01-06T12:29:42Z [INFO] Starting Agent: Amazon ECS Agent - v1.13.1 (efe53c6) 2017-01-06T12:29:42Z [INFO] Loading configuration ... 2017-01-06T12:29:42Z [INFO] Registering Instance with ECS 2017-01-06T12:29:42Z [INFO] Registered! module="api client" 2017-01-06T12:29:42Z [INFO] Registration completed successfully. I am running as 'arn:aws:ecs:eu-west-1:264418146286:container-instance/94953bf4-d74b-479d-aad6-89790befe978' in cluster 'rtfm-example' ...
Проверяем:
$ aws ecs list-container-instances --cluster rtfm-example { "containerInstanceArns": [ "arn:aws:ecs:eu-west-1:264418146286:container-instance/94953bf4-d74b-479d-aad6-89790befe978" ] }
Просмотреть детали самого инстанса можно с помощью describe-container-instances
:
$ aws ecs describe-container-instances --cluster rtfm-example --container-instances 94953bf4-d74b-479d-aad6-89790befe978 { "containerInstances": [ { "runningTasksCount": 0, "ec2InstanceId": "i-0350dce3645f6c77d", "version": 3, "pendingTasksCount": 0, "agentConnected": true, "attributes": [ { "name": "ecs.availability-zone", "value": "eu-west-1b" ...
Task definition
Создаём task definition:
{ "containerDefinitions": [ { "name": "rtfm-nginx", "image": "nginx", "cpu": 10, "command": [], "memory": 10, "essential": true } ], "family": "nginx" }
Подключаем его:
$ aws ecs register-task-definition --cli-input-json file://rtfm-task-def.json
Проверяем:
$ aws ecs list-task-definitions { "taskDefinitionArns": [ "arn:aws:ecs:eu-west-1:264418146286:task-definition/nginx:1" ] }
Task
Теперь, когда есть кластер, инстанс и task defenition – с помощью run-task
можно запустить задачу:
$ aws ecs run-task --cluster rtfm-example --task-definition nginx:1 { "tasks": [ { "desiredStatus": "RUNNING", "group": "family:nginx", "taskDefinitionArn": "arn:aws:ecs:eu-west-1:264418146286:task-definition/nginx:1", "clusterArn": "arn:aws:ecs:eu-west-1:264418146286:cluster/rtfm-example", "createdAt": 1483706916.493, "containers": [ { "containerArn": "arn:aws:ecs:eu-west-1:264418146286:container/f54b4ffb-c3ff-412c-80ee-7d8a8de24b1b", "name": "rtfm-nginx", "lastStatus": "PENDING", "taskArn": "arn:aws:ecs:eu-west-1:264418146286:task/0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d" } ], "version": 1, "overrides": { "containerOverrides": [ { "name": "rtfm-nginx" } ] }, "containerInstanceArn": "arn:aws:ecs:eu-west-1:264418146286:container-instance/94953bf4-d74b-479d-aad6-89790befe978", "lastStatus": "PENDING", "taskArn": "arn:aws:ecs:eu-west-1:264418146286:task/0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d" } ], "failures": [] }
Проверяем:
$ aws ecs list-tasks --cluster rtfm-example { "taskArns": [ "arn:aws:ecs:eu-west-1:264418146286:task/0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d" ] }
Просмотреть информацию о запущенной задаче можно с помощью describe-tasks
:
$ aws ecs describe-tasks --cluster rtfm-example --task 0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d { "tasks": [ { "taskArn": "arn:aws:ecs:eu-west-1:264418146286:task/0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d", "createdAt": 1483706916.493, "desiredStatus": "RUNNING", "startedAt": 1483706928.403, "clusterArn": "arn:aws:ecs:eu-west-1:264418146286:cluster/rtfm-example", "containers": [ { "taskArn": "arn:aws:ecs:eu-west-1:264418146286:task/0d66808f-6b8c-4ec2-9cd4-84fb0fd3a84d", "networkBindings": [], "containerArn": "arn:aws:ecs:eu-west-1:264418146286:container/f54b4ffb-c3ff-412c-80ee-7d8a8de24b1b", "name": "rtfm-nginx", "lastStatus": "RUNNING" } ], "lastStatus": "RUNNING", "taskDefinitionArn": "arn:aws:ecs:eu-west-1:264418146286:task-definition/nginx:1", "overrides": { "containerOverrides": [ { "name": "rtfm-nginx" } ...
При проверке сейчас – NGINX не сможет ответить, т.к. не были указаны порты.
Обновляем шаблон task definition, добавляем порт 80 на хосте (EC2 инстансе) и самом контейнере:
{ "containerDefinitions": [ { "name": "rtfm-nginx", "image": "nginx", "cpu": 10, "command": [], "memory": 10, "essential": true, "portMappings":[ { "containerPort":80, "hostPort": 80 } ] } ], "family": "nginx" }
Добавляем:
$ aws ecs register-task-definition --cli-input-json file://rtfm-task-def.json
Проверяем имеющиеся описания задач:
$ aws ecs list-task-definitions { "taskDefinitionArns": [ "arn:aws:ecs:eu-west-1:264418146286:task-definition/nginx:1", "arn:aws:ecs:eu-west-1:264418146286:task-definition/nginx:2" ] }
Теперь есть задача nginx
версии 2.
Находим запущенную задачу:
$ aws ecs list-tasks --cluster rtfm-example { "taskArns": [ "arn:aws:ecs:eu-west-1:264418146286:task/e04a14fc-2278-4dcf-8349-f46a81507e49" ] }
Стопаем её:
$ aws ecs stop-task --cluster rtfm-example --task e04a14fc-2278-4dcf-8349-f46a81507e49 { "task": { "group": "family:nginx", "desiredStatus": "STOPPED", ...
Запускаем таску со второй ревизии:
$ aws ecs run-task --cluster rtfm-example --task-definition nginx:2
Проверяем:
$ curl 52.214.206.108 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
Контейнер с NGINX на EC2-интансе:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7c541ec81758 nginx "nginx -g 'daemon off" 23 seconds ago Up 22 seconds 0.0.0.0:80->80/tcp, 443/tcp ecs-nginx-4-rtfm-nginx-8ab8b9ee9fb0a0bbc201 c74d0ac426af amazon/amazon-ecs-agent:latest "/agent" 14 minutes ago Up 14 minutes ecs-agent
Выводы
Первый раз меня документация AWS приводит в такое уныние.
Например, в одном документе – portmappings, в другом – portMappings, в третьм – PortMappings.
Указание кластера через user-data
– тоже выглядит… Как будто AWS не закончил разработку интерфейса в портале. Ну и привязка через IAM смотрится не слишком логичным решением. Тем не менее – ECS показался сервисом весьма приятным, хотя по началу и немного “замороченным”.