Привет, всем! В предыдущих статьях мы рассмотрели общую концепцию и составные части платформы, git-сервер и непрерывную интеграцию CI, подсистему непрерывной доставки CD, систему единой аутентификации SSO и приватный репозиторий Docker-образов. В данной статье мы расскажем, как строили кластер высокой доступности Kubernetes для нашей платформы.

Абстрактная постановка задачи

Абстрактно задача была озвучена так - масштабировать кластер Kubernetes на два дата центра и проработать Highly Avalable архитектуру, не имеющую единой точки отказа и позволяющую кластеру Kubernetes пережить падение любого из дата центров.

Highly Available решение из официального руководства

Kubernetes хранит настройки в базе данных etcd. Соответственно Highly Available кластер Kubernetes хранит настройки в кластере etcd, состоящем из нескольких нод etcd. Поэтому построение Highly Avalable кластера Kubernetes сводится к построению кластера etcd. Официальная документация предлагает две топологии: Stacked etcd topology и External etcd topology

Stacked etcd topology
Stacked etcd topology
External etcd topology
External etcd topology

В обоих случаях придется строить кластер etcd, которому требуется n/2+1 ноды etcd в строю, чтобы провести кворум и выбрать лидера, где n-общее количество нод. В противном случае, кластер etcd становится недоступен и падает плоскость управления Kubernetes. Таблицу можно найти в разделе FAQ официального руководства etcd.

Количество нод в кластере

Требуется живых нод

Может упасть

1

1

0

2

2

0

3

2

1

4

3

1

5

3

2

6

4

2

7

4

3

8

5

3

9

5

4

В итоге какое количество нод etcd не размести в двух дата центрах, с падением одного из дата центров падает половина или большинство нод etcd. Оставшиеся в меньшинстве ноды etcd в выжившем дата центре не смогут провести кворум и выбрать лидера, и кластер Kubernetes упадет в обоих дата центрах. Минимальное решение (которое нам удалось найти), способное пережить падение одного из дата центров - это 3 дата центра по 2 ноды etcd в каждом. Но данное решение для нас оказалось избыточным.

Замена etcd на SQL-базу данных

Мы нашли способ заменить базу данных etcd на SQL-базу данных, в которой Kubernetes также может хранить свои настройки - это Kine от проекта K3S. Kine, с одной стороны, реализует интерфейс etcd для Kubernetes, а с другой может хранит настройки кластера Kubernetes в одной из трех SQL-баз данных: SQLite, PostgreSQL или MySQL/MariaDB. Также Kine может использовать для хранения данных брокер NATS, но у нас не получилось настроить NATS без единой точки отказа.

Поэтому решили остановиться на одной из трех предложенных SQL-баз данных. Выбор базы данных дело вкуса. От базы потребуется только Master-Slave репликация. Указанные SQL-базы данных не имеют архитектурных особенностей etcd по связности, приведенных в предыдущем пункте, и позволяют построить Highly Available кластер Kubernetes в двух дата центрах без избыточности и дополнительных затрат.

Архитектура Highly Available кластера Kubernetes

В итоге у нас получилась вот такая архитектура

Highly Available кластер Kubernetes для CI/CD платформы Gitorion
Highly Available кластер Kubernetes для CI/CD платформы Gitorion

Зеркально в двух дата центрах мы разместили Control Plane ноды плоскости управления Kubernetes - Control Plane1 и Control Plane 2. Для запуска компонентов CI/CD платформы и пользовательских приложений в каждом дата центре подключили в кластер Worker ноды - Worker node 1 и Worker node 2. Ingress-nginx принимает запросы из Интернета и перенаправляет их в модули компонентов CI/CD платформы и пользовательских приложений.

В каждом дата центре на Control Plane ноду установили Kine и подключили к SQL-базе данных. Важный нюанс! Все Kine в любой момент времени должны писать в одну и ту же базу данных. Вариант, при котором каждый Kine пишет в базу данных в своем же дата центре, а затем сделать репликацию Master-Master между базами данных не получится. Репликация вскоре развалится из-за дублирующихся записей. Рабочий вариант приведен на рисунке выше - оба Kine пишут в одну и ту же базу данных, являющуюся мастером. А база данных в соседнем дата центре подключается как Slave и реплицирует базу данных, на случай падения дата центра с мастером.

Сценарий падения дата центра со Slave репликой

При падении дата центра в котором располагается Slave реплика SQL-базы данных никаких действий выполнять не требуется. Кластер Kubernetes продолжит работать в выжившем дата центре, а упавшие ноды просто будут помечены плоскостью управления как NotReady.

Падение дата центра со Slave репликой
Падение дата центра со Slave репликой

После возвращения в строй дата центра со Slave репликой нужно восстановить Master-Slave репликацию. Упавшие Control Plane и Worker ноды будут найдены плоскостью управления и переведены в состояние Ready автоматически. Если по какой-то причине ноды в упавшем дата центре не возможно восстановить, их можно установить с нуля и подключить в кластер Kubernetes командой kubeadm.

Сценарий падения дата центра с Master репликой

Если упадет дата центр с Master-репликой, то в выжившем дата центре скрипт liveness-script автоматически выявит падение Master реплики, и API Kubernetes остановит на Slave репликацию и сделает ее мастером. Затем переключит Kine на работу с SQL-базой данных в своем же дата центре.

Падение дата центра с Master репликой
Падение дата центра с Master репликой

После восстановления упавшего дата центра, Control Plane и Worker ноды будут автоматически найдены плоскостью управления и переведены в состояние Ready. Также можно установить ноды с нуля и подключить в кластер командой kubeadm в случае невозможности их восстановления. Далее в поднятом дата центре нужно запустить liveness-script, который подключит SQL-базу данных как Slave реплику к ушедшему вперед мастеру в выжившем дата центре и переключит Kine на мастер в выжившем дата центре.

Кластер после восстановления дата центра с бывшей Master репликой
Кластер после восстановления дата центра с бывшей Master репликой

Заключение

В итоге мы получили распределенный на два дата центра Highly Available кластер Kubernetes, который хранит свои настройки в SQL-базе данных. В каждом дата центре располагается копия настроек кластера Kubernetes, что позволяет ему выжить при падении любого из дата центров. На случай падения обоих дата центров или ошибок в SQL-базе данных, следует сохранять ежедневный бэкап на отчуждаемый носитель. Дамп базы данных занимает несколько мегабайт. В следующих статьях мы рассмотрим Highly Avalable решения для CI/CD компонентов платформы и пользовательских приложений. Спасибо за внимание!

Комментарии (7)


  1. inkvizitor68sl
    31.07.2024 10:54

    А как проблему со splitbrain решаете?
    В статье нет ничего про случай, если оба ДЦ работают, но потеряли связь друг с другом.


    1. gitorion Автор
      31.07.2024 10:54

      Хороший вопрос! В случае потери связи между дата центрами обе реплики SQL-базы данных станут мастерами, и сообщение об этом высылается админам. Чтобы не разъехались данные, админы настраивают балансер HAProxy или DNS Round Robin так, чтобы весь трафик пошел в выбранный ими дата центр. Реплика SQL-базы данных выбранного дата центра становится мастером после восстановления связи между дата центрами.


      1. inkvizitor68sl
        31.07.2024 10:54

        Ну сам по себе старый мастер слейвом же не станет?

        У ДЦ выключается сеть, происходит splitbrain, ДЦ без сети (точнее, база) продолжает считать себя мастером (и переключить её невозможно, т.к. сети нет), haproxy в этом ДЦ продолжает проксировать трафик туда.

        Или есть стопкран/арбитр/etc?


        1. gitorion Автор
          31.07.2024 10:54

          Можно в облаке поставить небольшой VPS, установить в него скрипт, отслеживающий ситуацию, когда оба стали мастерами, и гасить один из дата центров. При этом внешний балансер HAProxy автоматически сделает keep-alive чек и направит трафик в выживший дата центр.


  1. regret
    31.07.2024 10:54

    Благодарю за статью!
    Etcd позиционирует себя как "высокоскоростное" хранилище key-value, и возникает вопрос - а не сравнивали ли случайно производительность API kubernetes с etcd и c kine+pg? Или может kine берет на себя какие-то кеширующие задачи а "исторические" данные закидывает в pg? Сам с kine не работал - очень интересно стало.


    1. gitorion Автор
      31.07.2024 10:54

      Спасибо за фидбек. К сожалению производительность API Kubernetes с etcd и SQL-базой данных не сравнивали. Просто не совсем понятна методика тестирования. Если есть возможность, подскажите методику мы с удовольствием протестируем и отпишемся о результатах. Про кэширование в Kine информации не встречали. Тут только смотреть код


      1. regret
        31.07.2024 10:54

        На самом деле предполагал даже не сколько сам ETCD, сколько его в связке с API Kubernetes на условные чтение-запись, просаживается ли и сильно ли.
        В целом еще раз спасибо за статью, возможно с коллегами тоже пощупаем данный подход и проверим.