Kubernetes Stateful set, утверждения AZ и Volume: что происходит, когда отказывает AZ

Рассмотрим Statefulset (Cassandra на официальном примере K8S) в 3 зонах доступности:

  • Кассандра-0 -> зона А
  • Кассандра-1 -> зона б
  • Кассандра-2 -> зона с

Каждый модуль Cassandra использует том EBS. Так что автоматически возникает сродство. Например, cassandra-0 не может перейти в "зону-b", потому что его объем находится в "зоне-a". Все хорошо.

Если некоторые узлы / рабочие Kubernetes выходят из строя, они будут заменены. Стручки снова начнут работать на новом узле и будут повторно присоединены к их тому EBS. Похоже, ничего не случилось.

Теперь, если вся AZ "зона-а" выходит из строя и в течение некоторого времени недоступна (то есть cassandra-0 больше не может запускаться из-за сродства к EBS в той же зоне). Вы остались с:

  • Кассандра-1 -> зона б
  • Кассандра-2 -> зона с

Kubernetes никогда не сможет запустить cassandra-0 до тех пор, пока "зона-a" недоступна. Это все хорошо, потому что cassandra-1 и cassandra-2 могут обслуживать запросы.

Теперь, если к тому же другой узел K8S выйдет из строя или у вас настроено автоматическое масштабирование вашей инфраструктуры, вы можете получить cassandra-1 или cassandra-2, необходимые для перехода на другой узел K8S. Это не должно быть проблемой.

Однако, как показал мой тест, K8S не сделает этого, потому что pod cassandra-0 находится в автономном режиме. Он никогда не будет самовосстанавливать Кассандру-1 или Кассандру-2 (или любую Кассандру-X), потому что он хочет, чтобы Кассандра-0 вернулась первой. И Cassandra-0 не может запуститься, потому что его громкость находится в зоне, которая не работает и не восстанавливается.

Поэтому, если вы используете Statefulset + VolumeClaim + в разных зонах И у вас возникла ошибка AZ, и у вас произошел сбой EC2 в другой AZ или у вас есть автоматическое масштабирование вашей инфраструктуры

=> тогда вы потеряете все свои стручки Кассандры. До тех пор, пока зона А не вернется в онлайн

Это похоже на опасную ситуацию. Есть ли способ для состояния с набором состояний не заботиться о порядке и при этом самовосстановиться или начать больше стручков на Кассандре-3, 4, 5, X?

3 ответа

Два варианта:

Вариант 1: используйте podManagementPolicy и установите для него значение Parallel. Pod-1 и pod-2 будут аварийно завершать работу несколько раз, пока начальный узел (pod-0) не станет доступен. Это происходит при первом создании Statefulset. Также обратите внимание, что документация Cassandra использовалась, чтобы рекомендовать НЕ создавать несколько узлов параллельно, но, похоже, недавние обновления делают это неправдой. Несколько узлов могут быть добавлены в кластер одновременно

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

Вариант 1 b: используйте podManagementPolicy, установите для него значение Parallel и используйте ContainerInit. То же, что и в варианте 1, но используйте initContainer https://kubernetes.io/docs/concepts/workloads/pods/init-containers/. Контейнер init - это недолговечный контейнер, роль которого заключается в проверке доступности начального узла перед запуском фактического контейнера. Это не требуется, если мы рады, что модуль потерпел крах до тех пор, пока начальный узел снова не станет доступен. Проблема в том, что Init Container всегда будет работать, что не требуется. Мы хотим, чтобы кластер Cassandra был правильно сформирован при первом создании. После этого это не имеет значения

Вариант 2: создать 3 разных statefulets.

1 набор состояния на каждый AZ/Rack. Каждый набор состояний имеет ограничения, поэтому он может работать только на узлах в определенном AZ. У меня также есть 3 класса хранения (опять же ограничение для конкретной зоны), чтобы убедиться, что набор состояний не предоставляет EBS в неправильной зоне (набор состояний еще не обрабатывает это динамически) В каждом наборе состояний у меня есть начальный узел Cassandra (определяется как переменная окружения CASSANDRA_SEEDS, которая заполняет SEED_PROVIDER во время выполнения). Это делает 3 семени, что достаточно. Моя установка может выдержать полное отключение зоны благодаря коэффициенту репликации =3

Подсказки:

  • список начальных узлов содержит все 3 узла, разделенных запятыми: "cassandra-a-0.cassandra.MYNAMESPACE.svc.cluster.local, cassandra-b-0.cassandra.MYNAMESPACE.svc.cluster.local, cassandra-c-0.cassandra.MYNAMESPACE.svc.cluster.local"
  • Подождите, пока первое семя (cassandra-a-0) будет готово, прежде чем создавать 2 других набора состояний. В противном случае вы получите расколотый мозг. Это проблема только при создании кластера. После этого вы можете потерять один или два начальных узла без последствий, так как третий знает обо всех остальных.

Начиная с Kubernetes 1.7, вы можете попросить Kubernetes ослабить гарантии заказа StatefulSet, используя podManagementPolicy вариант ( документация). Установив эту опцию на Parallel Kubernetes больше не гарантирует порядок при запуске или остановке модулей и их запуске параллельно. Это может повлиять на обнаружение вашего сервиса, но должно решить проблему, о которой вы говорите.

Я думаю, что если вы можете контролировать развертывание каждого модуля (cassandra-0, cassandra-1, cassandra-2 с тремя разными файлами развертывания yaml), вы можете использовать podAffinity, установленный для определенной зоны для каждого модуля.

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

Например, вы можете создать кластер Kubernetes с тремя разными управляемыми узлами, по одной для каждой зоны (метка «зона»: «a», «b», «c» для каждой группы), по крайней мере с двумя узлами для каждой группы и используйте podAffinity.

Примечание. Не используйте для узлов машины x1.32xlarge :-)

Другие вопросы по тегам