Оновіть контейнер служби в Amazon ECS


32

Який підхід рекомендується оновлювати контейнер служби, яка працює в Amazon ECS?

Документація AWS говорить: "Якщо ви оновили зображення Docker для своєї програми, ви можете створити нове визначення завдання з цим зображенням і розгорнути його до своєї служби, по одній задачі." Це майже все, що зараз доступно в документації (13 квітня 2015 року).

Чи правильно я зрозумів, що єдиний спосіб оновити контейнер додатків в Amazon ECS - це створити нове завдання, а потім зупинити стару задачу і запустити нове завдання?

Я успішно використовую тег "найновіший" з Core OS & Fleetctl. Це має перевагу в тому, що не потрібно міняти тег зображення Docker на нові оновлення, оскільки при перезавантаженні сервісу з’являться нові зміни та оновлення контейнера (використовуючи той самий тег «останнє»).

Які підходи ви використовували для оновлення своєї служби оновленим зображенням докера в Amazon ECS?


Також намагаємося розібратися в цьому, оскільки ми сподіваємося використовувати ECS для розгортання різноманітних демонів, які потребують постійного запуску у виробництві.
батько5446

1
Тільки для підтвердження, ви сказали, що перезапуск послуги електронної пошти зніме останню версію зображення? Я шукав документацію з цього приводу і не можу її знайти ніде.
mmilleruva

1
Будь-яке підтвердження на цьому?
Lior Ohana

@LiorOhana На жаль це правда. Детальну інформацію див. У моїй відповіді.
hamx0r

Нижче я розмістив нову детальну відповідь, але для уточнення тут: Ваша служба завжди намагатиметься витягнути свіжу копію вашого контейнера з репо, спираючись на тег, який ви встановили. Якщо завдання вбивається, коли служба знову розгортає його, воно не пригадує те, що було в репо, лише те, що є в репо.
MrDuk

Відповіді:


18

Не впевнений, чи це вважається занедбаним питанням - натрапив на це під час усунення неполадок і тепер додав моє рішення тепер, коли воно вирішено.

Щоб оновити послугу з новим контейнером, вам потрібно:

  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

2
Це змушує мене визначити завдання як файл локально, і якщо я правильно розумію, це єдине місце, де я можу визначити змінні середовища. Чи можливо це зробити, не маючи змінних оточення локально? В ідеалі я хотів би надати команду, щоб вказати на новий тег зображення докера, не надсилаючи іншої інформації про завдання / службу / контейнер / тощо.
rmac

1
Зауваження set "min health/max health" limits to "0%, 100%"золоті. Дуже дякую!
sivabudh

1
Тут висловлюєте обережність, якщо ви встановите своє minзначення 0%, коли ви змінюєте визначення завдання, яке ваша служба розгортає, ви, по суті, надаєте їй повний повноваження одночасно знімати всі завдання для цього розгортання.
MrDuk


1

Я використовую частину сценарію ecs-розгортання зі своїми вдосконаленнями (він бере зображення з кожного опису контейнера і замінює його тегову частину на $ 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"

Рекомендується надати корисну інформацію із посилань у вашій відповіді, надати посилання-гниль. Чи можете ви це зробити, будь ласка?
BE77Y

1
Оновлено мою відповідь
ForeverYoung

1

Після завантаження нового зображення Docker, навіть якщо він має той самий тег, що і тест, який використовується завданням, потрібно скопіювати останнє завдання, а потім налаштувати Сервіс для використання цієї нової задачі. За бажанням, можна просто мати два дублікати завдання та налаштувати Сервіс для обміну між ними щоразу, коли зображення Docker оновлюється.

В основному, для того, щоб викликати створення нового контейнера Docker за допомогою ECS, оновлення Служби повинно запустити її, і єдиний спосіб зробити тригер служби - оновити його певним чином - наприклад, сказавши йому використовувати різний номер завдання.

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


Це насправді не так - завжди можна вручну вбити завдання, а не покладатися на свою послугу. Коли служба виявить, що вона була вбита, вона спробує піднести її знову, змусивши повторно тягнути те самеtag
MrDuk

1

Підхід, який працює для мене, аналогічний вище. Створивши службу та завдання та розпочавши все, відредагуйте, відредагуйте групу автоматичного масштабування та переконайтеся, що мінімум , макс та бажане встановлено на 1 .

Група може бути типовою; якщо ви не впевнені, тоді ви можете дістатись до нього, вибравши вкладку « Екземпляри ECS » у своєму кластері, а потім виберіть зі спадного меню « Дії» виберіть Ресурси кластера» та натисніть посилання внизу діалогового вікна, яке відкриється.

Коли все на своєму місці, будь-коли, коли ви хочете розгорнути оновлене зображення контейнера, перейдіть до області Завдання кластеру та зупиніть завдання . Ви отримаєте попередження, але за умови налаштування автоматичного масштабування сервіс почне його повторно із останнім натисканням.

Не потрібно створювати нові версії або служби, або завдання.

Зауважте, що служба / завдання оновлюються будь-де від миттєвого до протягом хвилини. Якщо ви відчайдушно чекаєте, ви можете просто запустити нове завдання вручну. Сервіс не буде ним володіти, тому він не є ідеальним, але він все одно закрутить новий, якщо він помре.


1

Я знаю, що це стара тема, але рішення набагато простіше, ніж більшість відповідей тут.

Як оновити запущений контейнер у два етапи:

Нижче припущено, що у вас є служба, яка виконує завдання, яке посилається на тег контейнера 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здорових порогів.


приємно, дякую, краще за інші відповіді
Олегзандр Денман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.