Простые контейнеры CI / CD в AWS

14

Я использую AWS Code Pipeline, Code Build для создания нового контейнера Docker и отправки его в ECR.

Мое приложение представляет собой простой простой контейнер на основе одного контейнера. Что было бы менее трогательным подходом для снятия текущего работающего Контейнера и перезапуска нового Контейнера из реестра ECS (вывод Code Build через Code Pipeline).

Я попробовал CloudFormation с пользовательскими данными EC2, пользовательскими сценариями с одной стороны и CloudFormation с ECS с определением задачи с другой стороны (пока не удалось). Я твердо считаю, что должен быть более очевидный и простой подход.

Навин Виджай
источник

Ответы:

16

Я хотел бы сохранить экземпляры контейнера ECS (я говорю о хостах Docker - мне здесь не нравится терминология AWS) и развертывание как две отдельные вещи.

Получите ваш ECS стек и работает. Вы можете управлять им через группы CloudFormation и Auto-scaling, это нормально. Просто подумайте о кластере в качестве платформы , где будет развернуто на , а не то , что вам нужно повторное развёртывание .

Затем для компакт-диска самый простой способ на сегодняшний день - обновить определение службы, чтобы использовать новое определение задачи, и позволить ECS обновлять контейнеры для вас.

Каждый раз, когда он запускает задачу, ECS будет запускать docker pull image: tag, даже если у него есть изображение локально, чтобы удостовериться, что у него есть последняя версия этого image: tag. Таким образом, тег изображения, который вы используете, действительно не имеет значения (нет необходимости менять тег при каждой сборке).

Это означает, что вы можете создавать myimage: последние снова и снова, чтобы его можно было легко развернуть.

Что вам нужно, так это определение задачи, где image = myimage: latest. Создайте сервис с этим определением задачи, и каждый раз, когда ECS запускает задачу (экземпляр вашей службы), это будет самое последнее «myimage: latest», которое вы создали.

Оттуда вам не хватает только одной части головоломки, из CodeDeploy вы можете вызвать что-то, возможно, лямбда-функцию, чтобы создать новую ревизию определения вашей задачи и обновить службу, а ECS автоматически создаст новые задачи для этой ревизии и удалить старые задачи.

Пример:

Предположим, вы создали сервис MyService. Что вы настроили эту службу для запуска 2 задач для определения задачи MyTaskDefinition: 1 (редакция 1). В этом определении задачи у вас есть одно определение контейнера, изображение которого установлено как «myimage: latest».

  1. Вчера вы собрали myimage: последний, у которого был ID (SHA) 365d8f7bf565.
  2. Ваш экземпляр ABC контейнера выполняет задачу с именем MyTaskDefinition- 1 -containerName-someLongId. когда вы проверяете этот контейнер, он запускает образ "sha256: 365d8f7bf565 .........."
  3. Ваш другой экземпляр контейнера DEF выполняет другую задачу. У него похожее имя (различаются только идентификаторы), но работает тот же образ.
  4. Вы вносите изменения в свой репо.
  5. CodePipeline подхватывает это изменение, создает и публикует изображение в ECR.
  6. Это новое изображение Docker также myimage: последнее, но его ID (SHA) - f7ec5e54ac96
  7. Теперь вам нужно добавить шаг в ваш конвейер, чтобы использовать функции Lambda и AWS NodeJS SDK для выполнения некоторых вызовов вашего кластера:
    1. Создайте новое определение задачи (которое будет точно таким же, как и раньше). Это будет MyTaskDefinition: 2
    2. Обновите MyService для использования MyTaskDefinition: 2 (вместо 1)
  8. ECS создаст новые задачи. Имена контейнеров будут MyTaskDefinition- 2 -containerName-someLongId. При проверке этих контейнеров вы увидите, что они будут работать "sha256: f7ec5e54ac96 .......". Возможно, у вас будет 2 задачи на экземпляре контейнера ABC, возможно, они будут распылены (это зависит от конфигурации вашего сервиса)
  9. Через некоторое время ECS удалит старую задачу MyTaskDefinition-1-containerName-someLongId из ABC и DEF.

Примечание. На самом деле вам не нужно создавать новое определение задачи. Если вы хотите, вы можете вместо этого получить список задач службы и вручную остановить их одну за другой. Вам следует подождать, пока ECS перезапустит задачу, прежде чем остановить новую (то есть: остановить первый контейнер, подождать, пока ECS заменит его, остановить второй контейнер). Когда ECS перезапустит контейнер, он получит самое последнее изображение: последнее построенное, как описано выше. Я просто думаю, что создание нового определения задачи проще и менее подвержено ошибкам (логика не требуется, чтобы ждать и проверять, ECS будет обрабатывать непрерывное обновление для вас, если у вас есть новое определение задачи).

Александр
источник
Удивительно - я бы назвал ваш ответ отсутствующим руководством по CI / CD для докера. Спасибо.
Навин Виджей
3

Для описанного простого варианта использования я бы предложил проверить Elastic Beanstalk для Docker, это не минимальное решение, как использование чистого ECS, но вы можете воспользоваться автоматически управляемыми и настроенными сервисами, такими как ELB, EC2 AutoScale, мониторинг работоспособности и многое другое.

Резюме высокого уровня:

  1. Сконфигурируйте Elastic Beanstalk для использования определенного тега myimage: проверено
  2. Используйте Code Pipeline / Build для создания, тестирования и продвижения тега «проверено»
  3. Триггерное развертывание Elastic Beanstalk, которое извлекает продвигаемое изображение: протестировано для всех экземпляров, доступны различные стратегии развертывания.

Этот подход, основанный на повторном использовании одного и того же тега, альтернативный подход будет генерировать тег с идентификатором сборки, например, myimage: test-42, для этого потребуется каждый раз обновлять Elastic Beanstalk с новым тегом, но он дает более детальный контроль над развернутой ревизией.

rombob
источник
0

Я второй эластичный бобовый стебель за его простоту; это очень легко настроить и развернуть.

Если вы знакомы с docker-compose, другой подход заключается в определении docker-compose.yml и непосредственном развертывании в ECS с помощью ecs-cli.

AnthonyC
источник