Вопрос: Обновите контейнер службы в Amazon ECS


Какой подход рекомендуется для обновления контейнера службы, работающей в ECS Amazon?

Документация AWS говорит: «Если вы обновили образ Docker вашего приложения, вы можете создать новое определение задачи с этим изображением и развернуть его на свою службу, одновременно за одну задачу». Это почти все, что в настоящее время доступно в документации (13 апреля 2015 г.).

Правильно ли я понял, что единственный способ обновить контейнер приложения в Amazon ECS - это создать новую задачу, затем остановить старую задачу и запустить новую задачу?

Я успешно использовал тег «новейший» с Core OS & Fleetctl. Это позволяет не менять метку изображения Docker для новых обновлений, так как при перезагрузке службы будут видны новые изменения и обновление контейнера (с использованием того же тега «последний»).

Какие подходы вы использовали для обновления вашего сервиса с обновленным изображением докеров в Amazon ECS?


30
2018-04-13 13:33


Источник


Также пытаясь понять это, так как мы надеемся использовать ECS для развертывания множества демонов, которые необходимо постоянно запускать в производство. - parent5446
Просто для подтверждения, вы сказали, что перезапуск службы ecs приведет к удалению последней версии изображения? Я искал документацию об этом и не могу найти его нигде. - mmilleruva
Любое подтверждение по этому поводу? - Lior Ohana
@LiorOhana К сожалению, это правда. См. Мой ответ для деталей. - hamx0r
Я опубликовал новый подробный ответ ниже, но пояснить здесь: ваш сервис всегда будет пытаться вытащить новую копию вашего контейнера из репо на основе установленного вами тега. Если задача убита, когда служба разворачивает ее снова, она не помнит, что был в репо, только то, что является в репо. - MrDuk


Ответы:


Не уверен, что это считается заброшенным вопросом, - наткнулся на это, устраняя мою проблему и теперь добавляя мое решение, когда оно разрешено.

Чтобы обновить сервис с помощью нового контейнера, вам необходимо:

  1. загрузить новый контейнер в репозиторий;
  2. обновить определение задачи триггера;
  3. обновление контейнера триггера;
  4. Важно: убедитесь, что правила обслуживания позволяют запускать новую версию задачи.

Если служебная задача не обновлена ​​до последней версии, установите флажок «События» на наличие ошибок. Например, возможно, ECS не смог запустить новую версию вашей службы: у вас есть только один экземпляр ec2 в кластере, а порт приложения уже используется на хосте. В этом случае установите ограничения «min health / max health» на «0%, 100%» - таким образом, ECS решит убить старый контейнер перед развертыванием нового. Это также происходит в течение нескольких минут - не спешите, если вы не увидите немедленную обратную связь.

Ниже приведен пример сценария развертывания для обновления контейнера в предварительно сконфигурированном кластере и службе. Обратите внимание: нет необходимости указывать версии, если вы просто имеете в виду «использовать последние из семейства».

awsRegion=us-east-1
containerName=..
containerRepository=..
taskDefinitionFile=...
taskDefinitionName=...
serviceName=...


echo 'build docker image...'
docker build -t $containerName .

echo 'upload docker image...'
docker tag $containerName:latest $containerRepository:$containerName
docker push $containerRepository:$containerName

echo 'update task definition...'
aws ecs register-task-definition --cli-input-json file://$taskDefinitionFile --region $awsRegion > /dev/null

echo 'update our service with that last task..'
aws ecs update-service --service $serviceName --task-definition $taskDefinitionName --region $awsRegion  > /dev/null

15
2018-05-03 15:22



Это заставляет меня определять задачу как файл локально, и если я правильно понимаю, это единственное место, где я могу определить переменные среды. Есть ли способ сделать это без наличия переменных окружения локально? В идеале я хотел бы отправить команду, чтобы указать на новый тег изображения докеров, не отправляя никакой другой информации о задаче / службе / контейнере / etc. - rmac
Комментарии к set "min health/max health" limits to "0%, 100%" золотой. Спасибо огромное! - sivabudh
Здесь следует соблюдать осторожность, если вы установите min в 0%, когда вы меняете определение задачи, которое развертывает ваш сервис, вы, по сути, предоставляете ему все полномочия, чтобы сбить все задачи одновременно для этого развертывания. - MrDuk


Чтобы обновить приложение, обновите определение задачи и затем обновите службу. Видеть http://docs.aws.amazon.com/AmazonECS/latest/developerguide/update-service.html


8
2017-08-27 14:47





Я использую часть из скрипт ecs-deploy с моими улучшениями (он берет изображения из описания каждого контейнера и заменяет его часть тега на $ TAG_PURE): https://gist.github.com/Forever-Young/e939d9cc41bc7a105cdcf8cd7ab9d714

# based on ecs-deploy script
TASK_DEFINITION_NAME=$(aws ecs describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition)
TASK_DEFINITION=$(aws ecs describe-task-definition --task-def "$TASK_DEFINITION_NAME" | jq '.taskDefinition')
NEW_CONTAINER_DEFINITIONS=$(echo "$TASK_DEFINITION" | jq --arg NEW_TAG $TAG_PURE 'def replace_tag: if . | test("[a-zA-Z0-9.]+/[a-zA-Z0-9]+:[a-zA-Z0-9]+") then sub("(?<s>[a-zA-Z0-9.]+/[a-zA-Z0-9]+:)[a-zA-Z0-9]+"; "\(.s)" + $NEW_TAG) else . end ; .containerDefinitions | [.[] | .+{image: .image | replace_tag}]')
TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq ".+{containerDefinitions: $NEW_CONTAINER_DEFINITIONS}")
# Default JQ filter for new task definition
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions"
# Some options in task definition should only be included in new definition if present in
# current definition. If found in current definition, append to JQ filter.
CONDITIONAL_OPTIONS=(networkMode taskRoleArn)
for i in "${CONDITIONAL_OPTIONS[@]}"; do
  re=".*${i}.*"
  if [[ "$TASK_DEFINITION" =~ $re ]]; then
    NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
  fi
done

# Build new DEF with jq filter
NEW_DEF=$(echo $TASK_DEFINITION | jq "{${NEW_DEF_JQ_FILTER}}")
NEW_TASKDEF=`aws ecs register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`

echo "New task definition registered, $NEW_TASKDEF"

aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition "$NEW_TASKDEF" > /dev/null

echo "Service updated"

1
2017-10-06 11:08



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


После загрузки нового изображения Docker, даже если он имеет тот же тег, что и один, используемый Task, необходимо скопировать последнюю задачу, а затем настроить службу для использования этой новой задачи. При желании можно было бы просто иметь две повторяющиеся задачи и настроить службу для обмена между ними каждый раз при обновлении образа Docker.

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

Обратите внимание, что существующие запущенные контейнеры не могут автоматически останавливаться только потому, что Служба была обновлена ​​- вам может потребоваться просмотреть список задач и остановить их вручную.


1
2017-11-23 16:51



На самом деле это не так - вы всегда можете вручную убейте задачу вместо того, чтобы полагаться на вашу службу, чтобы сделать это. Когда служба обнаруживает, что она была убита, она попытается снова поднять ее, заставив повторить попытку tag - MrDuk


Подход, который работает для меня, аналогичен приведенному выше. После создания службы и задачи и начала всего, отредактируйте Группа автомасштабирования и обеспечить мин, Максимум а также желательно установлены на 1,

Группа может быть по умолчанию; если вы не уверены, вы можете добраться до него, выбрав Экземпляры ECS в вашем кластере, затем из действия выпадающий список Ресурсы кластера и нажмите ссылку в нижней части диалогового окна, которое открывается.

Когда это все на месте, в любое время, когда вы хотите развернуть обновленный образ контейнера, перейдите к задача области кластера и Стоп задание, Вы получите предупреждение, но при условии, что будет установлено автоматическое масштабирование, служба запустит его снова с последним нажатием.

Нет необходимости создавать новые версии службы или задачи.

Обратите внимание, что обновление службы / задачи происходит от моментально до минуты или около того. Если вы отчаянно ожидаете, вы можете просто запустить новую задачу вручную. Сервис не будет владеть им, поэтому он не идеален, но он все равно будет разворачиваться, если он умрет.


1
2018-05-01 21:14





Я знаю, что это старая тема, но решение намного проще, чем большинство ответов здесь.

Как обновить запущенный контейнер в два этапа:

В приведенном ниже примере предполагается, что у вас есть служба, выполняющая задачу, которая ссылается на контейнер с тегами latest (или любой другой статический тег, который не изменяется при обновлении контейнера).

  1. Загрузите новый контейнер в репозиторий
  2. Вручную убить свои задачи

Если цель состоит в том, чтобы мы получили новое построение в дикой природе, нам действительно не нужно полагаться на наш сервис для этого (и я бы утверждал, что мы не должен полагайтесь на это). Если вы убьете свою задачу, служба узнает, что она не имеет Desired Count запущенных задач и просто развернуть новый. Это приведет к повторному извлечению вашего контейнера на основе одного и того же тега.

Службы ECS представляют собой сеть безопасности HA, не замена вашего конвейера CD / CI.


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


Как развернуть новые теги в три этапа:

  1. Загрузите новый container:tag в хранилище
  2. Создайте новое определение задачи, ссылаясь на новое tag
  3. Обновите свою службу, чтобы ссылаться на определение новой задачи
    • Осторожно! Если у вас есть minimum healthy установлен в 0% как утверждают некоторые другие ответы, вы предоставляете AWS полный доступ, чтобы убить всю вашу службу, чтобы развернуть новое определение задачи. Если вы предпочитаете скользящее / постепенное развертывание, установите свой минимум на что-то >0%,
    • Кроме того, установите minimum healthy в 100% и ваш maximum healthy к чему-то >100% чтобы ваша служба развертывала новый перед тем, как убить старых (сводя к минимуму воздействие на ваших пользователей).

С этого момента ваша служба автоматически распознает, что вы указали новую задачу, и работаете над ее развертыванием на основе minimum/maximum которые вы настроили.


0
2018-03-23 16:13