Блог

Чему AWS научилась о зональных сбоях, запустив Kubernetes в миллионах кластеров

Справиться с очевидными сбоями - это проще простого: сервер вышел из строя - запускаете другой. А вот сбои, которые фактически выводят из строя целые регионы, - это те, которые не так очевидны. Зона, которая работает медленно, но не вышла из строя, пропускает часть трафика, но по-прежнему проходит проверки работоспособности. Регион AWS распределяет инфраструктуру по нескольким зонам доступности с независимыми системами электропитания, охлаждения и сети, поэтому если в одной зоне происходит сбой электропитания, разрыв сети или сбой системы охлаждения, ваше приложение продолжает работать из других зон. На практике это затрудняется тем, что зоны редко выходят из строя, исчезая «чисто». В этой «серой зоне» стандартное поведение большинства автоматизированных систем - обнаруживать неисправности и заменять их - как раз и превращает проблему одной зоны в региональный сбой.

Мы поняли это, внедряя в Amazon EKS зонированную отказоустойчивость в течение многих лет разработки и дорабатывая её на основе реальных инцидентов в производственной среде. Созданная нами в результате система сегодня защищает каждый кластер EKS. В этой статье рассказывается о том, что мы внедрили в плоскость управления Kubernetes, которую EKS использует для каждого кластера, о том, что мы реализовали в плоскости данных, где выполняются ваши рабочие нагрузки, а также о принципах, связывающих эти две плоскости. Самым важным из этих принципов является статическая устойчивость: во время сбоя в зоне самое ценное, что может сделать система, - это перестать реагировать, сохранить имеющиеся ресурсы, перенаправить трафик в обход неработающей зоны и ждать.

Почему плоскости управления нужна зональная отказоустойчивость

Плоскость управления EKS состоит из сервера API (конечной точки, с которой взаимодействуют ваши kubectl и контроллеры) и хранилища данных etcd, в котором хранится полное состояние вашего кластера. Для обеспечения отказоустойчивости эти компоненты распределены по нескольким зонам доступности. Если одна из зон становится недоступной, сохранившиеся экземпляры в других зонах продолжают работать. На бумаге это работает. Причина, по которой зональная отказоустойчивость потребовала не просто схемы, а многих лет инженерных разработок, заключается в том, что происходит в «сером» периоде, прежде чем зона полностью выйдет из строя.

Когда зоны выходят из строя в «сером» режиме

Наиболее распространённый режим сбоя в первые годы нашей работы был связан с проверками работоспособности и автомасштабированием. Экземпляры плоскости управления находятся за сетевым балансировщиком нагрузки, а группа автомасштабирования отслеживает их работоспособность. Логика проверки работоспособности сама по себе разумна: если экземпляр несколько раз не проходит проверку в течение тридцати секунд, его следует пометить как неработоспособный и заменить. 

«Самый важный из этих принципов - статическая устойчивость: во время сбоя в зоне самое ценное, что может сделать система, - это перестать реагировать, сохранить имеющуюся мощность, перенаправить трафик в обход неработающей зоны и ждать».

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

Проверка работоспособности балансировщика нагрузки частично зависит от того, может ли сервер API связаться с etcd, поэтому кратковременный сбой сети между зонами может привести к тому, что исправные экземпляры будут помечены как неработающие. Конечный результат: тридцатисекундный сбой сети может вызвать прекращение работы значительной части парка серверов, привести к очистке «теплых» кэшей, увеличить нагрузку на и без того перегруженные компоненты и затем заблокировать восстановление на тридцать минут после устранения исходной проблемы.

Автоматический перенос в другую зону для плоскости управления

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

Переключение заставляет любой контроллер, лидер которого находится в неработоспособной зоне, передать лидерство работоспособной зоне. Кроме того, сервер API в неработоспособной зоне перестаёт объявлять свой IP-адрес, обеспечивая маршрутизацию запросов подами к работоспособным серверам API в других зонах. Кластер продолжает выполнять планирование и согласование, используя исправную инфраструктуру.

Работу выполняют исправные зоны

Принцип проектирования, лежащий в основе этого механизма, был сформулирован нами на основе первоочередных принципов, а затем подтверждён инцидентами: корректирующие действия должны предприниматься исправными зонами, а не зоной с нарушениями. Существует соблазн построить логику таким образом, чтобы экземпляр в зоне с нарушениями сам обнаруживал свою неисправность и уступал место. 

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

Межзональные зависимости, скрывающиеся внутри зонального сбоя

Сбой, ограниченный одной зоной, всё равно может нанести ущерб исправным зонам из-за зависимостей, о которых вы не подозревали, что они пересекают границы зон. Мы обнаружили это на примере etcd. Серверы API поддерживают клиентские соединения с экземплярами etcd, а etcd автоматически синхронизирует список участников кластера со своими клиентами. 

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

При определённых сбоях клиент в исправной зоне мог получить устаревшую запись о составе кластера, указывающую на изолированный экземпляр etcd в неисправной зоне, попытаться использовать её и не пройти собственные проверки работоспособности. Проблема, физически ограниченная одной зоной, приводила к сбоям серверов API в других зонах.

Общий урок, который мы извлекли из этого, заключается в том, что термин «зональный» описывает местоположение сбоя, но не обязательно его радиус воздействия. Именно в разрыве между этими двумя понятиями таятся самые неприятные сюрпризы, и аудит межзональных путей зависимостей стал неотъемлемой частью нашей процедуры оценки новых компонентов плоскости управления.

Плоскость данных: зональный сдвиг для ваших рабочих нагрузок

Описанная выше работа на уровне управления защищает инфраструктуру, на которой работает EKS, но ваше приложение работает на уровне данных на ваших рабочих узлах и в ваших подах, и событие, связанное с зоной, может затронуть и этот уровень. Рабочие узлы в зоне с нарушенной работоспособностью могут оказаться недоступными, и трафик необходимо перенаправить с них. Применяются те же принципы, но в данном случае право принятия решения принадлежит вам, поскольку только вы знаете пропускную способность вашего приложения, его топологию и степень допустимого риска.

Функция ARC zonal shift для Amazon EKS предоставляет вам эту возможность, основанную на том же механизме переключения зон доступности, который используют другие сервисы AWS через Amazon Application Recovery Controller. После включения этой функции в кластере вы (или AWS от вашего имени) можете указать, что рабочие нагрузки должны быть перенесены из конкретной зоны, и EKS перенастраивает сетевую инфраструктуру внутри кластера, чтобы прекратить использование этой зоны без запуска дополнительных ресурсов или отключения существующих. 

Когда переключение активно, EKS изолирует каждый узел в неработоспособной зоне, не позволяя планировщику Kubernetes размещать там новые поды. Для управляемых групп узлов он приостанавливает перебалансировку групп Auto Scaling между зонами доступности и ограничивает группу, позволяя запускать новые узлы только в исправных зонах. Контроллер EndpointSlice удаляет конечные точки подов из неисправной зоны из EndpointSlices ваших сервисов, благодаря чему трафик «восток-запад» между подами и входящий трафик через ALB или NLB направляется только на поды в исправных зонах. 

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

Не удаляйте, сохраняйте мощность

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

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

Чему нас научили эти инциденты

Наш первый принцип заключается в том, что зональный сдвиг должен быть отказоустойчивым и безопасным для выполнения в любой момент. Мы развертываем инстансы в других зонах, чтобы исправные зоны могли без сбоев принимать трафик, равный объему одной зоны. Чтобы проверить это, мы не ограничиваемся предпроизводственной средой и небольшими регионами. Мы проводим тесты с регулярной периодичностью в наших крупнейших регионах (таких как IAD), чтобы убедиться, что этот принцип работает там, где это наиболее важно. Крупнейшие регионы, где наш масштаб с наибольшей вероятностью может выйти из строя, - это именно те места, где в противном случае мы узнали бы о пробелах в системе только в день реального инцидента.

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

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

Мы также поняли, что проведение тестов зональной изоляции через управляемый сервис, такой как AWS FIS, гораздо проще и реалистичнее, чем настройка правил iptables и eBPF на каждом хосте. Правила на уровне хоста проверяют только тот путь, который мы предполагали заблокировать, и не воспроизводят ситуацию, когда зона действительно отключается. С помощью FIS мы моделируем реальную потерю пакетов и изоляцию зон по всему кластеру, точно так же, как это происходило бы в реальной ситуации. Это выявило проблемы, которые наши самодельные симуляции никогда не обнаруживали, включая ошибку ограничения пропускной способности по зависимостям при вызове контрольной плоскости, которая заблокировала бы восстановление во время сбоя. 

Тот же подход доступен любому, кто использует EKS: FIS может изолировать зону доступности от рабочих узлов и подков в этой зоне, что позволяет команде убедиться, что их рабочие нагрузки выдержат сбой в зоне, а не просто предполагать, что это произойдет.

Как включить эту функцию

Функции ARC zonal shift и zonal autoshift доступны в Amazon EKS без дополнительной платы (вы платите только за запущенные инстансы) и действуют исключительно на плоскости данных Kubernetes; управляемая EKS плоскость управления уже распределена по зонам и продолжает работать независимо от обстоятельств. Включение этой функции осуществляется на уровне настроек отдельного кластера.

Вы также можете включить её при создании кластера или через консоль, eksctl, AWS CloudFormation или Terraform без необходимости пересоздания кластера и без простоев. После включения ваш кластер отображается в ARC как управляемый ресурс с двумя режимами работы. Чтобы самостоятельно отреагировать на сбой, запустите зональный переход из консоли ARC, AWS CLI или API зонального перехода, указав зону и срок действия. 

Перемещения по замыслу являются временными, и вы можете продлить или отменить их. Чтобы передать принятие решения AWS, включите автоматическое перемещение между зонами для данного ресурса. После этого AWS будет отслеживать работоспособность зоны доступности (AZ), автоматически перемещать кластер при обнаружении сбоя и завершать перемещение, когда зона восстановится. Функция «Автоматический переход» также обеспечивает плановые тестовые запуски (примерно раз в неделю), в ходе которых происходит переход из зоны в контролируемых условиях, что позволяет вам выяснить, сможет ли ваш кластер справиться с потерей зоны, прежде чем реальный инцидент вынудит вас это выяснять.

Эта функция поможет только в том случае, если ваш кластер построен так, чтобы выдерживать потерю зоны, и ответственность за это лежит на вас. Распределите рабочие узлы по нескольким зонам доступности (AZ) и запускайте несколько реплик каждой рабочей нагрузки с ограничениями по распределению топологии, включая CoreDNS, чтобы обнаружение служб выдерживало потерю зоны. Заранее масштабируйте и предустанавливайте избыточные ресурсы, чтобы исправные зоны могли принять нагрузку от зоны, которая вышла из строя.

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

«Во время коррелированного сбоя самое ценное, что может сделать автоматизированная система, - это не предпринимать никаких действий».

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

Для пользователей весь этот процесс должен проходить незаметно: во время сбоя в зоне ваш трафик перенаправляется в исправные зоны, ваша плоскость управления продолжает отвечать, а ваша вычислительная мощность сохраняется, а не теряется. Если вы включили функцию автопереключения, оно происходит без каких-либо уведомлений. Именно такая «тишина» и является целью, и она достигается благодаря одному принципу: во время коррелированного сбоя самое ценное, что может сделать автоматизированная система, - это не предпринимать никаких действий.

То, что остается на вашем ведомстве как оператора EKS, - это небольшой объем задач, заслуживающих вашего внимания. Распределите рабочие нагрузки по зонам, обеспечьте такие ресурсы, чтобы работоспособные зоны могли выдерживать полную нагрузку, и проверьте, что ваше приложение действительно справляется с ситуацией, когда одна из зон выходит из строя. Сделайте всё правильно, и отключение зоны станет для вас событием, о котором вы прочитаете позже, а не проблемой, над которой придётся проводить ночь, устраняя неполадки. Чтобы узнать больше о зональном переключении и включить его, ознакомьтесь с нашей документацией AWS.

Читайте также

Подписывайтесь на наш канал в Телеграм

Подписаться
AWS Kubernetes