Обновите контейнер сервиса в Amazon ECS

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

В документации AWS говорится: "При обновлении изображения Докера приложения можно создать новое определение задачи с тем изображением и развернуть его на сервисе, одна задача за один раз". Это - в значительной степени все, что в настоящее время доступно в документации в настоящее время (13-го апреля 2015).

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

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

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

32
задан 14 July 2015 в 17:57
7 ответов

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

8
ответ дан 28 November 2019 в 19:56

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

Чтобы обновить службу с новым контейнером, вам необходимо:

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

Если служебная задача не обновлена ​​до последней версии, проверьте вкладку «События» на наличие ошибок. Например, возможно, ECS не удалось запустить новую версию вашего сервиса: у вас только один экземпляр ec2 в кластере, а порт приложения уже используется на хосте. В этом случае установите ограничения «минимальное / максимальное здоровье» на «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
18
ответ дан 28 November 2019 в 19:56

Я использую часть из сценария 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
ответ дан 28 November 2019 в 19:56

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

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

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

1
ответ дан 28 November 2019 в 19:56

Подход, который мне подходит, аналогичен описанному выше. После создания службы и задачи и начала работы отредактируйте Auto-Scaling Group и убедитесь, что min , max и желаемые ) установить на 1 .

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

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

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

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

1
ответ дан 28 November 2019 в 19:56

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

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

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

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

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

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


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


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

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

1
ответ дан 28 November 2019 в 19:56

Вы можете использовать параметр --force-new-deployment при вызове API ecs update-service. Обновление для самого сервиса не требуется. Из docs:

Необходимо ли принудительно новое развертывание службы. По умолчанию развертывания не принудительны. Вы можете использовать этот параметр для запуска нового развертывания без изменения определения службы. Например, вы можете обновить задачи службы, чтобы использовать более новый образ Docker с той же комбинацией образа/тега (my_image:latest) или перенести задачи Fargate на более новую версию платформы.

Это так же просто, как и с aws-cli:

aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment
3
ответ дан 12 December 2019 в 09:29

Теги

Похожие вопросы