При использовании Amazon Web Services (AWS) Elastic Container Service (ECS) вы можете столкнуться с ситуацией, когда ECS пытается развернуть одну из ваших служб ECS, но ваши задачи оказываются нездоровыми, поэтому он пытается снова.
И снова. И снова. И снова. И снова.
ECS очень решительно настроен запустить для вас здоровые задачи, и если вы не будете осторожны, он может продолжать неустанные попытки в течение дней, недель, месяцев.
В процессе он может создавать потоки журналов, выделять эластичные сетевые интерфейсы, загружать образы контейнеров из Интернета, взимать плату за NAT-шлюз, делать записи конфигурации AWS, регистрировать события CloudTrail и EventBridge.
В крайнем случае, это может вызвать довольно сильный всплеск биллинга, на отслеживание которого могут уйти часы.
Я собираюсь написать несколько способов избежать циклов перезапуска ECS и обнаружить их, чтобы вы могли вмешаться, в следующих двух постах, но если вам это незнакомо, я начну с определений и демонстрации.
Определения
Amazon Web Services (AWS) имеет ряд подходов для развертывания и запуска программных приложений в контейнерной модели. Elastic Container Service (ECS) — один из самых старых и простых сервисов AWS для запуска программного обеспечения в контейнере, и именно его я обычно рекомендую тем, кто впервые знакомится с контейнерами на AWS.
Когда вы хотите, чтобы ECS запускал контейнеры, вы определяете задачу ECS Task: по сути, это развертываемая единица с метаданными о контейнере (контейнерах), который нужно запустить, как они должны быть объединены в сеть, какие ресурсы им нужны.
В этот момент вы можете попросить ECS создать задачу, используя это определение, на экземпляре ECS/EC2, которым вы управляете, или на AWS Fargate, но обычно вы скорее всего обернете эту задачу ECS в ECS Service, что позволит легко запускать несколько задач параллельно, часто в разных зонах доступности, балансировать нагрузку, перезапускать их, если они не прошли проверку здоровья, и так далее.
В документации AWS ECS есть раздел Amazon ECS Components, в котором описаны элементы ECS, если вы новичок во всем этом.
Одной из возможностей, которые добавляют службы ECS, является отказоустойчивость. Что произойдет, если экземпляр EC2, на котором выполняется ваша задача, перестанет отвечать на запросы или будет завершен? ECS может обнаружить это и заменить задачу на другую, выполняющуюся на другом экземпляре. Что если у вашей задачи произойдет утечка памяти и произойдет сбой? ECS может определить, что ваша задача нездорова, выключить ее и запустить другую. Многие способы вмешательства ECS для поддержания работоспособности и надежности вашей службы связаны с выключением и запуском определенных вами контейнерных задач.
Но ECS не знает внутренностей вашего приложения. Он не знает, почему ваша задача выключается или не проходит проверку работоспособности. Поэтому, если он запускает задачу и та тоже не справляется, все, что он может сделать, это продолжать попытки. Если он повторяет попытки, и задачи снова и снова терпят неудачу, это цикл перезапуска.
Петля перезапуска
Почему и когда может произойти сбой задачи? Существует множество сценариев:
- Кластер может не иметь необходимых ресурсов для запуска задачи, в результате чего задача может потерпеть неудачу во время запуска, так и не достигнув состояния
RUNNING
. - Контейнер может содержать ошибку, приводящую к завершению процесса при запуске.
- Контейнер может содержать ошибку сбоя, для возникновения которой требуется время или определенный сценарий, в результате чего процесс завершается после того, как он был здоров и функционировал в течение некоторого времени.
- Контейнер может быть здоров, но содержать ошибочную проверку здоровья, заставляющую ECS считать, что задача нездорова. Это позволит запустить задачу, но ECS завершит ее после выполнения начальных проверок здоровья.
- Контейнер может быть здоров, и проверка здоровья может быть правильно определена, но группа безопасности может препятствовать тому, чтобы проверка здоровья достигла контейнера, что заставит ECS завершить задачу после проверки здоровья.
- Проверка здоровья контейнера может зависеть от внешнего ресурса, который недоступен. Это может произойти в любой момент, что заставит ECS завершить задачу. (Кстати, это хорошая причина изолировать проверки здоровья от среды).
- Что-то в окружении (VPC, сеть, группы безопасности и т.д.) может измениться таким образом, что контейнер или проверка работоспособности окажутся неудачными. Это может произойти в любое время.
А что ECS должен делать, когда задача терпит неудачу? Если задача является частью сервиса, ECS должен поддерживать определенное количество здоровых задач (как настроено в параметре desiredTasks
). Если задача завершается, она должна быть заменена запуском новой задачи. Если задача не прошла проверку работоспособности, она должна быть завершена и заменена.
Но что, если задача заменяется, и замена также сразу же заканчивается неудачей? Должен ли ECS продолжать попытки? В течение какого времени? Здесь нет единственно правильного ответа:
- Если есть проблема с контейнером или проверкой работоспособности, задача никогда не будет успешной, и ECS тратит ресурсы облака, пытаясь «починить» службу, которая в корне не работает.
- Если существует временная проблема с окружением или зависимостью, перезапуск задачи может не помочь, но служба может восстановиться, когда временная проблема закончится.
- Если задача нестабильна (периодические сбои, утечка памяти и т.д.), перезапуск задачи при каждом сбое, вероятно, будет лучшим выбором.
Но должен ли ECS обнаружить, что замена задач не работает, и изменить свое поведение? Возможно. До недавнего времени ECS просто продолжал попытки, прерывая и заменяя задачи бесконечно.
Всегда существовал способ ручного вмешательства — даже если вы не знаете, что вызывает цикл перезапуска, вы можете решить, что перезапуски не помогают. Если вы хотите, чтобы это прекратилось, вы можете установить desiredTasks
в 0
. Это означает, что при сбое задачи ECS не нужно будет заменять эту задачу, прекращая цикл перезапусков.
Демонстрация
На что похоже, когда служба ECS входит в цикл перезапуска? Если вы посмотрите на службу ECS в цикле перезапуска, вы увидите серию событий:
- запуск / остановка задач
- регистрация / дерегистрация целей с балансировщика нагрузки.
Если сбой произошел во время развертывания, вы также можете увидеть, что развертывание находится в процессе.
Что дальше?
Итак, если у вас возникла проблема с тем, что службы ECS переходят в цикл перезапуска, или вы просто задаетесь вопросом, как защитить себя от этого, что вам следует делать?
Во втором посте я расскажу о некоторых новых функциях, добавленных в ECS за последние несколько лет, которые могут помочь справиться с перезапуском служб, в том числе:
- дросселирование услуг
- прерыватели цепи
А в третьем посте я расскажу о некоторых вариантах мониторинга ECS для обнаружения перезапусков служб.