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

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

Для CI/CD платформы Gitorion разработать вариант размещения в двух дата центрах - ведущем и ведомом. В штатном режиме модули разрабатываемого приложения и самой платформы (Forgejo, Jenkins, Harbor, Keycloak) размещаются в ведущем дата центре. При аварии ведущего дата центра все модули запускаются и продолжают работать в ведомом дата центре.

Схема Highly Available исполнения

На рисунке приведена общая схема. Платформа размещается в двух дата центрах - ведущем "Дата центр 1" и ведомом "Дата центр 2". Ниже под рисунком приведено краткое описание и назначение нод.

Схема Highly Available исполнения
Схема Highly Available исполнения

Ноды ведущего дата центра "Дата центр 1":

  • dc1-db - Master-нода базы данных платформы;

  • dc1-nas - Primary-нода сетевого файлового хранилища платформы;

  • dc1-plane - Control-plane нода кластера Kubernetes, на которой запущены модули плоскости управления Kubernetes;

  • dc1-worker - Worker-нода, на которой запущены модули самой платформы (Forgejo, Jenkins, Keycloak, Docker-registry) и модули разрабатываемого на платформе проекта.

Ноды ведомого дата центра "Дата центр 2":

  • dc2-db - Slave-нода базы данных платформы;

  • dc2-nas - Secondary-нода сетевого файлового хранилища платформы;

  • dc2-plane - Control-plane нода кластера Kubernetes, на которой запущены модули плоскости управления Kubernetes;

  • dc2-worker - Worker-нода, на которой запущен Ingress-nginx, реализующий дополнительную точку входа.

Highly Available кластер Kubernetes

Все компоненты платформы и проекта, разрабатываемого с помощью платформы, запускаются в Docker-контейнерах в кластере Kubernetes. Поэтому первым делом мы развернули Highly Available кластер Kubernetes. Решение, предложенное на официальном сайте Kubernetes, позволяет построить кластер высокой доступности только в 3х дата центрах. Кластер etcd падает, если большинство нод etcd недоступны, и невозможно провести кворум, и следом падает кластер Kubernetes. Мы нашли способ развернуть Highly Available кластер Kubernetes в 2х дата центрах, заменив штатную базу данных Kubernetes etcd на SQL-базу данных с помощью Kine от K3S. Чтобы не перегружать данный материал, все тонкости реализации мы вынесли в отдельную статью CI/CD Kubernetes платформа Gitorion. Highly Available кластер Kubernetes.

Реплицируемый NAS для HA кластера Kubernetes

Далее потребовалось спроектировать систему хранения файлов и директорий для модулей, запускаемых в Highly Available кластере Kubernetes. В каждом из дата центров мы выделили отдельный узел под сетевой NAS, к которому подключили необходимое количество жестких дисков. С помощью LVM cоздали Volume Group и требуемое количество LV разделов. Реплицировали с помощью DRBD разделы LV из ведущего дата центра в ведомый. В ведущем дата центре подключили модули Kubernetes к NAS с помощью PersistentVolume по сетевому протоколу NFS. NAS в ведомом дата центре на подхвате и содержит реплики LVM разделов. Тонкости реализации мы также вынесли в отдельную статью CI/CD Kubernetes платформа Gitorion. Реплицируемый NAS для Highly Available кластера Kubernetes.

База данных CI/CD платформы Gitorion

В платформе установлены несколько приложений, которым требуется база данных, - это Kine, Git-сервер Forgejo, приватный репозиторий Docker-образов Harbor и Keycloak. В ведущем дата центре мы выделили отдельный узел и установили на него PostgreSQL, в котором создали базы данных для перечисленных выше приложений. В ведомом дата центре так же на отдельном узле установили PostgreSQL и настроили логическую Master-Slave репликацию. В штатном режиме модули Kubernetes запущены в ведущем дата центре и подключаются к Master-реплике PostgreSQL. Slave-реплика PostgreSQL в ведомом дата центре на подхвате. Модули Kubernetes подключили к внешней базе данных при помощи сервисов Service без селекторов, в Endpoints-которых задали IP-адреc БД PostgreSQL. Для примера приведем спецификации Service и Endpoints для подключения модуля Forgejo.

apiVersion: v1
kind: Endpoints
metadata:
  name: db
  namespace: forgejo
subsets:
  - addresses:
    - ip: 3.3.3.3
    ports:
    - port: 5432
---
apiVersion: v1
kind: Service
metadata:
  name: db
  namespace: forgejo
spec:
  ports:
  - port: 5432

Модуль Forgejo подключается к внешней базе данных PostgreSQL, используя имя сервиса db.forgejo.svc.cluster.local

Сценарий падения ведомого дата центра

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

Падение ведомого дата центра
Падение ведомого дата центра

После восстановления упавшего дата центра нужно подключить Slave-реплику PostgresSQL к Master-реплике и восстановить логическую репликацию. Подключить Secondary DRBD ноду к Primary DRBD ноде и тоже настроить репликацию.

Сценарий падения ведущего дата центра

Падение ведущего дата центра
Падение ведущего дата центра

В случае падения ведущего дата центра, в ведомом дата центре следует выполнить следующие действия:

  • подключить Kine к PostgreSQL в ведомом дата центре и перезапустить модули плоскости управления Kubernetes на Plane-ноде dc2-plane;

  • перевести DRBD в Primary StandAlone режим и смонтировать разделы LVM для томов PersistentVolume. Перезапустить NFS-сервер;

  • в Endpoint-ах служб без селекторов заменить IP-адрес PostgreSQL ведущего дата центра на IP-адрес PostgreSQL в выжившем. Например для Forgejo:

apiVersion: v1
kind: Endpoints
metadata:
  name: db
  namespace: forgejo
subsets:
  - addresses:
    - ip: 4.4.4.4
    ports:
    - port: 5432
  • в спецификациях Deployment и StatelulSet компонентов платформы в affinity привязать модули Kubernetes к worker-ноде ведомого дата центра;

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - "dc2-worker"
  • удалить модули Kubernetes в упавшем дата центре, и плоскость управления Kubernetes автоматически запустит их на worker-ноде в выжившем дата центре.

В итоге Kubernetes запустит модули приложений на worker-ноде в выжившем дата центре, согласно affinity в спецификациях. Модули приложений подключатся к своим базам данных в PostgreSQL в ведомом дата центре. Также модули подключатся но NFS к NAS в ведомом дата центре. Разработчики смогут продолжить вносить правки в ПО и выполнять непрерывную доставку. Модули разрабатываемого приложения также продолжат работать в выжившем дата центре.

Восстановление упавшего дата центра

Далее следует восстановить узлы в упавшем дата центре или заново развернуть в другом дата центре и подключить к выжившему дата центру, как показано на картинке ниже.

Восстановление упавшего дата центра
Восстановление упавшего дата центра

Базу данных PostgreSQL в поднятом дата центре следует подключить как Slave-реплику к Master-реплике в выжившем дата центе и настроить логическую репликацию. DRBD ноду в поднятом дата центре следует подключить как Secondary реплику к Primary DRBD реплике в выжившем дата центре и реплицировать LVM разделы. Теперь восстановленный дата центр будет на подхвате, на случай падения ведущего дата центра.

Заключение

На этом мы завершаем наш мини-цикл статей про высокую доступность CI/DC платформы Gitorion. Будем рады конструктивной критике и замечаниям. Спасибо за внимание!

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


  1. chupasaurus
    18.11.2024 06:21

    В случае падения ведущего дата центра, в ведомом дата центре следует выполнить следующие действия

    На этом слово Highly можно удалять.


    1. gitorion Автор
      18.11.2024 06:21

      Все действия по переключению в выживший дата центр автоматизированы в скриптах и происходят довольно быстро. Какое же слово нам использовать вместо Highly? )


      1. gitorion Автор
        18.11.2024 06:21

        Пришлось пойти на небольшой downtime в пользу снижения затрат на инфраструктуру, чтобы построить решение на два дата центра вместо трех. Если мы не ошибаемся, Highly Available это все-таки минимизация времени незапланированных простоев.


      1. chupasaurus
        18.11.2024 06:21

        Время на реакцию и действия умножить на 2 потенциальных инцидента в год (а их легко может быть больше) и вот уже в 4 девятки вписаться вряд ли получится. Даже если скрипты отрабатывают за секунду, наличие необходимости реагировать сотруднику очень быстро понижает доступность.


        1. gitorion Автор
          18.11.2024 06:21

          Все верно! Мы используем DRBD без кластерных файловых систем для синхронизации NAS и побоялись, что при каких то кратковременных переключенияx автоматикой словим split-brain. Поэтому оставили аварийные переключения под присмотром человека.


  1. brownbrown
    18.11.2024 06:21

    >...модули плоскости управления Kubernetes.

    Подскажите, что такое плоскость управления?


    1. gitorion Автор
      18.11.2024 06:21

      Компоненты Kubernetes | Kubernetes модули в пунктирном прямоугольнике Kubernetes Control Plane


      1. shurup
        18.11.2024 06:21

        Это не самый удачный перевод control plane, который был когда-то давно принесён в русскоязычную версию документации Kubernetes, но мы от него отказались (в пользу «управляющего слоя»). Хотя вижу, что осталось ещё [как минимум] одно упоминание по приведённой ссылке — пройдусь ещё раз grep'ом, чтобы избавиться от этого.


        1. gitorion Автор
          18.11.2024 06:21

          Спасибо, что поправили! Теперь будем использовать термин "управляющий слой" вместо "плоскость управления". Похоже еще одно упоминание в документации осталось вот тут Компоненты Kubernetes | Kubernetes


  1. eigrad
    18.11.2024 06:21

    PV над NFS... Ну допустим, хотя применимость весьма ограничена, не знаю что там ваши компоненты делают. Отказоустойчивость NFS через DRBD? Тут уже стоит хорошенько задуматься. DRBD между ДЦ - а вы проверяли как хорошо это работает? Обычно это ужасная идея.

    2 зоны для отказоустойчивой системы? Окей, раз переключение вручную. Но если переключение вручную, то может это уже disaster recovery и стоит рассмотреть более простые и надёжные инструменты с чуть худшим RPO? Насколько это критично для CI/CD?

    Почему не запустить три копии системы в разных ДЦ, и не реализовать масштабируемость и отказоустойчивость на прикладном уровне, а не на уровне платформы?