не сталкивался с aws и в целом не занимался настройкой инфраструктуры
Какие есть устоявшиеся паттерны, подходы чтобы гарантировать, что EC2 нода, которая должна быть убита при scale-in не будет выполнять какую либо работу?
Я могу разбить задачу на две части:
- перестать роутить трафик к ноде, которая будет убита
- дать ноде время завершить текущую работу и потом убить
Допустим, что на проекте есть два архитектурных подхода:
- ноды стоят за лоад балансером
- ноды стоят за очередью и сами от туда таскают таски
Из доков становится понятно, что есть следующие инструменты:
- scale-in protection
- custom termination policy
- lifecycle hooks
В случае, когда ноды стоят за Load Balancer, как будто имеет смысл использовать хуки, так как нода помеченая на терменацию дерегистрируется из автоскейл группы(следовательно трафик перестает к ней идти) и далее можно дать время ноде, чтобы она спокойно завершила работу
Сработает ли такой подход если ноды стоят за очередью? Иными словами, будет ли нода пытаться что-то выгребать из очереди, когда автоскелер решить ее грохнуть?
Если использовать scale-in protection или custom termination policy, то получается, что сначала нужно будет заставить ноду не брать задачи из очереди(что подразумевает написание какой то логики в самом приложении) или дерегистрировать ее из автоскейлинг группы, чтобы прекратить к ней роутинг трафика? Затем дать ей время завершить задачи и отключить scale-in protection/вернут ее id в респонсе кастомной termination policy?
Есть ли какие нибудь гайд лайны для решения таких задач? Ибо в доках новичку достаточно сложно разобраться и выстроить в голове более менее цельную картину , а примеры которые там есть к сожалению далеко не полные
Насчет лоадбалансера вроде верно пишешь, а насчет очереди, так ноды не "за очередью" они вообще не при делах. У тебя логика должна быть такая: взял сообщение, потом обработал и удалил. Пока оно обрабатывается оно невидимое для других консьюмеров сколько то времени ( не помню как называется настройка), если у тебя нода сдохла не обработав сообщение то оно станет видимым и другой консьюмер его схавает
в любом случае нужно использовать хуки. На каждом инстансе должен крутиться скрипт, который периодически чекает состоянии инстанса через метадату и если обнаруживает, что инстанс в “Terminating:Wait”, то ждет завершения задач и завершает хук, после чего инстанс тушится автоскейлинг группой
Какой смысл в таком подходе? Скажем, завяжемся мы на длину очереди для ASG, ну грохнется у нас один инстанс, так другой прочитает сразу после таймаута.
Смысл может быть в зависимости от условий. Например, может быть существенно дешевле дождаться завершения джобы, чем рестартовать ее.
Блин, там темя с очередями появилась из за отсутсвия понимания, как равномерно распределить гаррузку между нодами с помощью ЛБ Ситуация такая, что ЛБ не имеет подходящих для нас алгоритмов(услоыный least outs request не подходит так как ноды асинхронно процесят реквесты/задачи следовательно кол-во завершенных реквестов != кол-во завершенных задач) И логика была такая, что чтобы перестать роутить трафик к ноде, нужно чтобы она возвращала UNHEALTHY, но в таком случае ASG/ECS будут рестартовать ноду/контейнер, что нам не нужно. Но и полностью отключать такое поведение нам не надо, так как все таки есть кейсы, когда при респонсе UNHEALTHY нам все таки бы хотелось, чтобы контейнер/нода рестартанулась В итоге, как я понял, можно иметь кастомный хелф чек ендпоинт, который условная лямбда будет чекать и если от туда возвращается респонос "на мне большая нагрузка", дерегистрировать такую ноду, что остановит роутинг трафика к ней и затем когда нода вернет "я справилась с нагрузкой готова страдать дальше" возвращать ее в группу И я даже нашел примеры и статьи, как люди примерно так и поступают С другой стороны можно попробовать зайти со стороны очередей и позволить ноде самой решать, когда ей нужно брать таски, а когда нет. Но там такие таски, что очень желательно гарантировать их выполнение, если нода взяла их в работу Вообще все это конечно взрываем мне мозг, так как я впервые с этим сталкиваюсь И мне казалось, что это все достаточно распрастранненые кейсы и для них должны быть предусмотренны какие то типичные решения(или даже built-in решения), но как будто это не так..
может тебе попробовать автоскейлинг хелфчек привязать не к ЛБ, а просто к EC2 instance status? Тогда статус ноды с точки зрения балансера никак не будет влиять на то, будет нода убита или нет
то решает проблему "убийства" ноды но есть еще ECS, который мониторит состояние контейнеров(получая инфу от ЛБ и от докера если прописана конфигурация для этого) Соответсвенно как только он получает от ЛБ, что нода не здорова, он рестартует контейнеры на ней (В нашем случае на одной ноде один контейнер) Можно заставить ECS игнорировать ЛБ, но в таком случае, когда нам реально нужно будет чтобы контейнер рестартанулся, этого не произойдет, так как ECS игнорит хелф чеки ЛБ И тут казалось бы можно сказать ECS, чтобы он игнрил хелф чеи ЛБ, но не игнорил хелф чеки самого докера(как я писал выгше, можно включить такие хелф чеки), но видимо нет.. - ты либо игноришь все хелф чеки, либо не игноришь их вообще "тут должны быть ссылка на открытый тикет под это дело, но я хз, как тут делиться сслыками"
если нода нездорова, то как рестарт контейнеров на ней поможет делу? Это я просто по опыту кубера спрашиваю. Если у ноды проблемы, то надо наоборот с нее контейнеры выгонять
Насколько я знаю, ЛБ чекает состояние самой аппликации в ноде(условный /actuator/health ендпоинт) На этот хелф чек может ориентироваться ASG(но допустим наш ASG ориентируется на хелф чек непосредственно ноды, то есть EC2 хелф чек) Также на этот хелф чек смотрит и ECS и в случае если респонс на хелф чек был UNHEALTHY - рестарутет контейнер/контейнеры на ноде
Помимо алгоритмов скейлинга есть еще куча возможных сценариев когда нода/контейнер умрет не завершив выполнение. Чтобы именно гарантировать выполнение работы проще всего: 1. Если таски короткие по времени (миллисекунды) - то ждать респонса или повторять в случае таймаута на клиенте 2. Если длинные по времени - класть в очередь. sqs и подобные гарантируют выполнение тем что сообщения нужно явно удалять из очереди после выполнения
там таски представляют из себя сложные и простые сценарии взаимодействия с пользователем.. и таски эти стейтфул(то есть нода которая взялась за выполнения такой задачи имеет некоторый стейт для нее и это отдельная проблема..)
ну да, это понятно. ECS не такой гибкий как кубер, в нем нет readiness check
опять же в данный момент мы не используем для этого очередь, а используем обычные рест запросы, чтобы стригерить начала такой коммуникации с пользователем (очереди просто как вариант балансировки нагрузки между нодами) в целом проблемиа такая: при пиках, jvm на нодах начинает помирать с out of memory ex и нужно что то с этим сделать при более детальном взгляде на проблему стало понятно, что такое случается в частности из за того, что нагрузка между нодами распределяется совсем не равномерно, так как ЛБ не имеет подходящего алгоритма для роутинга трафика поэтому нужно каким то образом сделать распределение нагрузки более ровным ну и попытаться внедрить автоскейлинг
Обычно это не проблема. Стейт выносят в центральную базу (если стейт сравнительно небольшой), s3 (если большой), EFS (если нужно POSIX) и т.д.
да, скорее всего будем это делать но в любом случае если нода в данный момент выполняет какую либо работу, нужно не дать scale-in убить ее до завершения этой работы(и работа может исполняться как 30 секунд, так и несколько часов)
ну и конечно нужно чтобы такая нода не брала доп задачи/не принимала новые реквесты
ой да идите на кубер уже, кубер умеет защищать контейнер и не давать ноде схлопнуться если надо дождаться результата
А вы используете что то нативное для jvm для батч джобов? Типа spring batch и т.д.?
один из девопсов в компани сегодня такое несколько раз предлагал, хаха возможно сотрудники компании все таки должны к нему прислушаться
У вас уже докер образ есть, просто зачем вы в ECS лезете, когда EKS есть?
сорри, я что то не подумал, что я слово "работа" и "таска" очень фривольно использую, что может затруднять понимание в данный момент флоу такой: - пользователь инициирует сессию - запрос уходит на бек через некоторую цепочку микросервисов и начинает обрабатываться -обработка запроса под самой подразумевает, что: 1. возвращается респонс на запрос 2. запрос имеет информацию о скрипте который необходимо исполнить в некотором рантайме 3. скрипт начинает исполняться(агрегируются разные штуки из других сервисов) 4. в какой то момент по веб сокету пользователю возвращается промежуточный результат и n-e кол-во вариантов продолжения развития событий 5. пользователь выбирает один из вариантов(ин-фа об этом уходит через рест запрос на бек, где некоторый сервис А понимает какая нода рантайма хранит стейт/контекст исполнения данного скрипта) - крипт продолжает исполняться 6. пункт 4 и 5 может повторяться n-e кол-во раз(так же пользователь может в течение долгого времени не взимдействовать со скриптом через UI - мы должны держать конекст и быть готовыми, что пользователь продолжит взаимодействие) Микросервис, который отечает за исполнение скриптов может помирать с Out Of Memory, так как LB который перед ним стоит неравномерно нагружает ноды этого сервиса, так как исполнение скрипта происходит асинхроно Под таской/работой я имею в виду процесс исполнения скрипта для инициации которого микросервис бы тянул сообщения из очереди(в отличии от текущей ситуации, когда ЛБ просто дарует ему запрос от пользователя невзирая на текущую нагрузку ноды) Сорри, что сразу не дал контекст - не думал, что такое бурное обсуждение может произойти) (думал, что мне просто кинут пару ссылок на доки, если это что то обыденное и я просто по незнанию не могу допереть, куда глядеть или забьют, если окажется, что то менее тривиальное)
5. пользователь выбирает один из вариантов(ин-фа об этом уходит через рест запрос на бек, где некоторый сервис А понимает какая нода рантайма хранит стейт/контекст исполнения данного скрипта) - крипт продолжает исполняться*
Да это больше похоже на стейт машину, чем на батч. Вряд ли удастся найти что-то готовое что удовлетворит на сто процентов. Но на вскидку да, придется собирать вариант с очередями и промежуточными хранилищами стейта. Задача не выглядит тривиальной)
да, большая стейт машина это все еще и в оффлайне может работать и можно после выполнения скрипта поэтапно его повторить(прям на UI чтоб красивенько все действия пользователя отобразились с разной доп инфой и возможностью выбрать льтернатиный вариант), хаха
Обсуждают сегодня