Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение

в 6:30, , рубрики: devops, kubernetes, kubernetes operator, postgresql, zalando, Администрирование баз данных, Блог компании Флант, Флант

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 1

На прошлую статью, где мы рассмотрели три оператора PostgreSQL для Kubernetes (Stolon, Crunchy Data и Zalando), поделились своим выбором и опытом эксплуатации, — поступила отличная обратная связь от сообщества*.

Продолжая эту тему, мы добавили в обзор два других решения, на которые нам указали в комментариях: StackGres и KubeDB, — и сделали сводную таблицу сравнения. Также за время эксплуатации оператора от Zalando у нас появились новые интересные кейсы — спешим поделиться и ими.

* Первую часть статьи заметили даже разработчики Zalando, благодаря чему(?) они решили активизироваться в приёме некоторых PR. Это не может не радовать!

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 2

Итак, сначала дополним обзор ещё двумя решениями…

KubeDB

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 3

Оператор KubeDB разрабатывается командой AppsCode c 2017 года и хорошо известен в Kubernetes-сообществе. Он претендует на звание платформы для запуска различных stateful-сервисов в Kubernetes и поддерживает:

  • PostgreSQL;
  • Elasticsearch;
  • MySQL;
  • MongoDB;
  • Redis;
  • Memcache.

Однако в контексте статьи мы рассмотрим только PostgreSQL.

В KubeDB реализован интересный подход с использованием нескольких CRD, которые содержат в себе различные настройки, такие как:

  • версия с образом базы и вспомогательными утилитами — за это отвечает ресурс postgresversions.catalog.kubedb.com;
  • параметры восстановления — ресурс бэкапа <codesnapshots.kubedb.com

собственно, корневой ресурс postgreses.kubedb.com, который собирает в себе все эти ресурсы и запускает кластер PostgreSQL.

Особой кастомизации KubeDB не предоставляет (в отличие от оператора Zalando), но вы всегда можете управлять конфигом PostgreSQL через ConfigMap.

Интересной особенностью является ресурс dormantdatabases.kubedb.com, который предоставляет «защиту от дурака»: все удалённые базы сначала переводятся в такое архивное состояние и могут быть легко восстановлены в случае необходимости. Жизненный цикл БД в KubeDB описывается следующей схемой:

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 4

Что же касается самого технологического стека, то тут используются свои наработки для управления кластерами, а не знакомые всем Patroni или Repmgr. Хотя для полинга соединений используется pgBouncer, который также создается отдельным CRD (pgbouncers.kubedb.com). Кроме того, разработчики предоставляют плагин для kubectl, который позволяет удобно управлять базами через всем привычную утилиту, и это огромный плюс на фоне Stolon или Crunchy Data.

KubeDB интегрируется с другими решениями AppsCode, чем напоминает Crunchy Data. Если вы везде используете решения этого вендора, то KubeDB, безусловно, отличный выбор.

Наконец, хочется отметить отличную документацию этого оператора, которая находится в отдельном репозитории GitHub. В ней есть развернутые примеры использования, включая полные примеры конфигураций CRD.

Есть минусы у KubeDB. Многие возможности: бэкапы, полинг соединений, снапшоты, dormant-базы — доступны только в enterprise-версии, а для её использования требуется купить подписку у AppsCode. Кроме того, самой старшей поддерживаемой версией PostgreSQL «из коробки» является 11.x. Перечеркивают ли эти моменты изящную архитектуру KubeDB — решать вам.

StackGres

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 5

В твиттере и в комментариях к предыдущей статье нам резонно указали на оператор StackGres. Разработка данного оператора началась совсем недавно, в мае 2019 году. В нем используются известные и проверенные технологии: Patroni, PgBouncer, WAL-G и Envoy.

Общая схема оператора выглядит так:

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 6

Кроме того, в комплекте с оператором можно установить:

  • веб-панель, как в Zalando;
  • систему сбора логов;
  • систему мониторинга, аналогичную Crunchy Data, о которой мы говорили в первой части;
  • систему сбора бэкапов на основе MinIO, хотя можно подключить и внешнее хранилище.

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

Вкратце про все CRD:

  • sgbackupconfigs.stackgres.io, sgpgconfigs.stackgres.io, sgpoolconfigs.stackgres.io — описание кастомных конфигов;
  • sginstanceprofiles.stackgres.io — размер инстанса Postgres, который будет использоваться как limit/request для контейнера с PostgreSQL/Patroni. Для остальных контейнеров лимитов нет;
  • sgclusters.stackgres.io — когда есть конфигурации для базы, пула коннектов и бэкапа, можно создать кластер PostgreSQL, который описывается этим CRD;
  • sgbackups.stackgres.io — ресурс, схожий со snapshot у KubeDB и позволяющий обратиться к конкретному бэкапу из кластера K8s.

Однако оператор не позволяет использовать свои кастомные сборки образов или же несколько вспомогательных sidecar для сервера баз данных. Pod c Postgres содержит 5 контейнеров:

Обзор операторов PostgreSQL для Kubernetes. Часть 2: дополнения и итоговое сравнение - 7

Из них мы можем отключить экспортер метрик, пулер коннектов и контейнер со вспомогательными утилитами администратора (psql, pg_dump и так далее). Да, оператор позволяет при инициализации кластера баз данных подключить скрипты с SQL-кодом для инициализации БД или создания пользователей, но не более того. Это сильно ограничивает нас в кастомизации, например, в сравнении с тем же оператором Zalando, где можно добавлять нужные sidecar с Envoy, PgBouncer и любыми другими вспомогательными контейнерами (хороший пример подобной связки будет ниже).

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

Итоговое сравнение

Мы знаем, что наши коллеги нежно любят сводные таблицы, поэтому приводим подобную для Postgres-операторов в Kubernetes.

Забегая вперед: после рассмотрения двух дополнительных кандидатов мы остаёмся при мнении, что решение от Zalando — оптимальный для нашего случая продукт, так как позволяет реализовывать очень гибкие решения, имеет большой простор для кастомизации.

В таблице первая часть посвящена сравнению основных возможностей работы с БД, а вторая — более специфичным особенностям, следуя нашему пониманию об удобстве работы с оператором в Kubernetes.

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

Stolon Crunchy Data Zalando KubeDB StackGres
Текущая версия 0.16.0 4.5.0 1.5.0 0.13 0.9.2
Версии PostgreSQL 9.4—9.6, 10, 11, 12 9.5, 9.6, 10, 11, 12 9.6, 10, 11, 12 9.6, 10, 11 11, 12
Общие возможности
Кластеры PgSQL
Теплый и горячий резерв
Синхронная репликация
Потоковая репликация
Автоматический failover
Непрерывное архивирование
Инициализация: из WAL-архива
Бэкапы: мгновенные, по расписанию
Бэкапы: управляемость из кластера
Инициализация: из снапшота, со скриптами
Специализированные возможности
Встроенная поддержка Prometheus
Кастомная конфигурация
Кастомный Docker-образ
Внешние CLI-утилиты
(kubectl-плагин)
Конфигурация через CRD
Кастомизация Pod'ов
NodeSelector и NodeAffinity
(через патчи)
Tolerations
Pod anti-affinity

Бонусы про оператор от Zalando

Ежедневно пользуясь решением от Zalando, мы столкнулись с некоторыми сложностями, и этим опытом хотелось бы поделиться с сообществом.

1. Приватные репозитории

Недавно нам потребовалось запустить через оператор наряду с PostgreSQL контейнер с SFTP, который позволил бы получать выгрузки из базы в формате CSV. Сам SFTP-сервер со всеми нужными параметрами был собран в закрытом registry.

И тут стало ясно, что оператор не умеет работать с registry secrets. К счастью, с такой проблемой мы были не одни с такой проблемой: все легко решилось коллегами на GitHub. Оказалось, что достаточно добавить в описание ServiceAccount имя с доступами в registry:

pod_service_account_definition: '{ "apiVersion": "v1", "kind": "ServiceAccount", "metadata": { "name": "zalando-postgres-operator" }, "imagePullSecrets": [ { "name": "my-fine-secret" } ] }'

2. Дополнительные хранилища и init-контейнеры

Для работы SFTP нам также требовалось корректно выставлять права на директории, чтобы заработал chroot. Возможно, не все знают, но OpenSSH-сервер требует особых привилегий на директории. Например, чтобы пользователь видел только свой /home/user, необходимо, чтобы /home принадлежал root с правами 755, а уже /home/user был доступен пользователю. Соответственно, мы решили использовать init-контейнер, который исправлял бы права на директории.

Но оператор не умеет пробрасывать дополнительные диски в init-контейнеры! Благо, есть подходящий PR, которым мы и дополнили свою сборку оператора.

3. Перезапуск PgSQL при проблемах с control plane

В процессе эксплуатации кластеров на основе Patroni в Kubernetes мы получили от клиента странную проблему: ровно в 4 часа ночи по Москве обрывались все подключения PostgeSQL. Разбираясь в ситуации, мы обнаружили следующее в логах Spilo:

2020-10-21 01:01:10,538 INFO: Lock owner: production-db-0; I am production-db-0
2020-10-21 01:01:14,759 ERROR: failed to update leader lock
2020-10-21 01:01:15,236 INFO: demoted self because failed to update leader lock in DCS
2020-10-21 01:01:15,238 INFO: closed patroni connection to the postgresql cluster
2020-10-21 01:01:15 UTC [578292]: [1-1] 5f8f885b.8d2f4 0     LOG:  Auto detecting pg_stat_kcache.linux_hz parameter...

Согласно issue на GitHub, это означает, что Patoni не смог обработать ошибку Kubernetes API и упал с ошибкой. А проблемы с API были связаны с тем, что в 4 часа стартовали сразу 50 CronJob, что приводило к проблемам в etcd:

2020-10-21 01:01:14.589198 W | etcdserver: read-only range request "key:"/registry/deployments/staging/db-worker-db1" " with result "range_response_count:1 size:2598" took too long (3.688609392s) to execute

Ситуация исправлена в версии Patroni 2.0. По этой причине мы собрали версию Spilo из мастера. При сборке стоит учитывать, что требуется взять PR с исправлениями сборки, который на данный момент уже принят в мастер.

4. Пересоздание контейнеров

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

time="2020-10-28T20:58:25Z" level=debug msg="spec diff between old and new statefulsets: nTemplate.Spec.Volumes[2].VolumeSource.ConfigMap.DefaultMode: &int32(420) != nilnTemplate.Spec.Volumes[3].VolumeSource.ConfigMap.DefaultMode: &int32(420) != nilnTemplate.Spec.Containers[0].TerminationMessagePath: "/dev/termination-log" != ""nTemplate.Spec.Containers[0].TerminationMessagePolicy: "File" != ""nTemplate.Spec.Containers[1].Ports[0].Protocol: "TCP" != ""nTemplate.Spec.Containers[1].TerminationMessagePath: "/dev/termination-log" != ""nTemplate.Spec.Containers[1].TerminationMessagePolicy: "File" != ""nTemplate.Spec.RestartPolicy: "Always" != ""nTemplate.Spec.DNSPolicy: "ClusterFirst" != ""nTemplate.Spec.DeprecatedServiceAccount: "postgres-pod" != ""nTemplate.Spec.SchedulerName: "default-scheduler" != ""nVolumeClaimTemplates[0].Status.Phase: "Pending" != ""nRevisionHistoryLimit: &int32(10) != niln" cluster-name=test/test-psql pkg=cluster worker=0

Ни для кого не секрет, что при создании контейнера и pod’а добавляются директивы, которые не обязательно описывать. К ним относятся:

  • DNSPolicy;
  • SchedulerName;
  • RestartPolicy;
  • TerminationMessagePolicy;

Логично предположить, чтобы такое поведение учитывалось в операторе, однако, как оказалось, он плохо воспринимает секцию портов:

    ports:
    - name: sftp
      containerPort: 22

При создании pod’а автоматически добавляется протокол TCP, что не учитывается оператором. Итог: чтобы решить проблему, надо или удалить порты, или добавить протокол.

Заключение

Управление PostgreSQL в рамках Kubernetes — нетривиальная задача. Пожалуй, на текущий момент на рынке нет оператора, который покрывал бы все потребности DevOps-инженеров. Однако среди уже существующих инструментов есть продвинутые и довольно зрелые варианты, из которых можно выбрать то, что лучше всего соответствует имеющимся потребностям.

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

Говоря же об операторах, рассмотренных в этой части статьи (KubeDB и StackGres), стоит отметить, что они оснащены уникальными функциями для управления бэкапами из кластера, что может стать одним из факторов роста их популярности в ближайшем будущем.

P.S.

Читайте также в нашем блоге:

Автор: Николай Богданов

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js