Как соединить кластеры Kubernetes в разных дата-центрах
Добро пожаловать в серию кратких руководств по Kubernetes. Это регулярная колонка с самыми интересными вопросами, которые мы получаем онлайн и на наших тренингах. Отвечает эксперт по Kubernetes.
Сегодняшний эксперт — Даниэль Поленчик (Daniele Polencic). Даниэль работает инструктором и разработчиком ПО в Learnk8s.
Довольно часто инфраструктура реплицируется и распределяется по разным регионам, особенно в контролируемых средах.
Если один регион недоступен, трафик перенаправляется в другой, чтобы избежать перебоев.
С Kubernetes можно использовать схожую стратегию и распределять рабочие нагрузки по разным регионам.
У вас может быть один или несколько кластеров на команду, регион, среду или на комбинацию этих элементов.
Ваши кластеры могут размещаться в различных облаках и в локальной среде.
Но как спланировать инфраструктуру для такого географического разброса?
Нужно создать один большой кластер на несколько облачных сред по единой сети?
Или завести много маленьких кластеров и найти способ контролировать и синхронизировать их?
Один руководящий кластер
Создать один кластер по единой сети не так-то просто.
Представьте, у вас авария, потеряна связность между сегментами кластера.
Если у вас один мастер-сервер, половина ресурсов не смогут получать новые команды, потому что им не удастся связаться с мастером.
И при этим у вас старые таблицы маршрутизации (kube-proxy не может загрузить новые) и никаких дополнительных pod’ов (kubelet не может запрашивать обновления).
Что еще хуже, если Kubernetes не видит узел, он помечает его как потерянный и распределяет отсутствующие pod’ы по существующим узлам.
В итоге pod’ов у вас в два раза больше.
Если вы сделаете по одному мастер-серверу на каждый регион, будут проблемы с алгоритмом достижения консенсуса в базе данных etcd. (прим. ред. — На самом деле база данных etcd не обязательно должна находится на мастер-серверах. Ее можно запустить на отдельной группе серверов в одном регионе. Правда, получив при этом точку отказа кластера. Зато быстро.)
etcd использует алгоритм raft, чтобы согласовать значение, прежде чем записать его на диск.
То есть большинство экземпляров должны достичь консенсуса, прежде чем состояние можно будет записать в etcd.
Если задержка между экземплярами etcd резко вырастает, как в случае с тремя экземплярами etcd в разных регионах, требуется много времени, чтобы согласовать значение и записать его на диск.
Это отражается и на контроллерах Kubernetes.
Менеджеру контроллеров нужно больше времени, чтобы узнать об изменении и записать ответ в базу данных.
А раз контроллер не один, а несколько, получается цепная реакция, и весь кластер начинает работать очень медленно.
Впервые управлять коллекцией кластеров как единым объектом пробовали с помощью инструмента kube federation.
Начало было хорошим, но в итоге kube federation так и не стал популярным, потому что поддерживал не все ресурсы.
Он поддерживал объединенные поставки и сервисы, но, к примеру, не StatefulSets.
А еще конфигурация федерации передавалась в виде аннотаций и не отличалась гибкостью.
Представьте себе, как можно описать разделение реплик для каждого кластера в федерации с помощью одних аннотаций.
Получился полный беспорядок.
SIG-cluster проделали большую работу после kubefed v1 и решили подойти к проблеме с другой стороны.
Вместо аннотаций они решили выпустить контроллер, который устанавливается на кластерах. Его можно настраивать с помощью пользовательских определений ресурсов (Custom Resource Definition, CRD).
Для каждого ресурса, который будет входить в федерацию, у вас есть пользовательское определение CRD из трех разделов:
стандартное определение ресурса, например деплой;
раздел placement, где вы определяете, как ресурс будет распределяться в федерации;
раздел override, где для конкретного ресурса можно переопределить вес и параметры из placement.
Вот пример объединенной поставки с разделами placement и override.
Как видите, поставка распределена по двум кластерам: cluster1 и cluster2.
Первый кластер поставляет три реплики, а у второго указано значение 5.
Если вам нужно больше контроля над количеством реплик, kubefed2 предоставляет новый объект ReplicaSchedulingPreference, где реплики можно распределять по весу:
Вариант 2: объединение кластеров в стиле Booking.com
Разработчики Booking.com не занимались kubefed v2, зато придумали Shipper — оператор для поставки на нескольких кластерах, в нескольких регионах и в нескольких облаках.
Но вместо того, чтобы придумывать новый способ взаимодействия с кластером и оборачивать ресурсы в пользовательские определения, multi-cluster-scheduler внедряется в стандартный жизненный цикл Kubernetes и перехватывает все вызовы, которые создают поды.
Каждый создаваемый под сразу заменяется на пустышку.
multi-cluster-scheduler использует веб-hooks для модификации доступа, чтобы перехватить вызов и создать бездействующий pod-пустышку.
Исходный pod проходит через еще один цикл планирования, где после опроса всей федерации принимается решение о размещении.
Наконец, pod поставляется в целевой кластер.
В итоге у вас лишний pod, который ничего не делает, просто занимает место.
Преимущество в том, что вам не пришлось писать новые ресурсы для объединения поставок.
Каждый ресурс, создающий pod, автоматически готов для объединения.
Это интересно, ведь у вас вдруг появляются поставки, распределенные по нескольким регионам, а вы и не заметили. Впрочем, это довольно рискованно, ведь здесь все держится на магии.
Но если Shipper старается, в основном, смягчить последствия поставок, multi-cluster-scheduler выполняет более общие задачи и, возможно, лучше подходит для пакетных заданий.
У него нет продвинутого механизма постепенных поставок.
Больше о multi-cluster-scheduler можно узнать на странице официального репозитория.
Если хотите прочитать о multi-cluster-scheduler в действии, у Admiralty есть интересный случай применения с Argo — рабочими процессами, событиями, CI и CD Kubernetes.
Другие инструменты и решения
Соединение нескольких кластеров и управление ими — сложная задача, универсального решения не существует.
Если вы хотите подробнее изучить эту тему, вот вам несколько ресурсов:
Submariner от Rancher — инструмент, соединяющий оверлей-сети разных кластеров Kubernetes.
Cilium, плагин интерфейса сети контейнеров, предлагает функцию cluster mesh, которая позволяет сочетать несколько кластеров
Вот и все на сегодня
Спасибо, что дочитали до конца!
Если вы знаете, как эффективнее соединить несколько кластеров, расскажите нам.
Мы добавим ваш способ к ссылкам.
Особая благодарность Крису Несбитту-Смиту (Chris Nesbitt-Smith) и Венсану де Сме (Vincent De Smet) (инженеру по надежности в swatmobile.io) за то, что прочитали статью и поделились полезной информацией о том, как работает федерация.