Короткий огляд операторів PostgreSQL для Kubernetes, наш вибір та досвід
Все частіше від клієнтів надходять такі запити: "Хочемо як Amazon RDS, але дешевше"; "Хочемо як RDS, але скрізь, у будь-якій інфраструктурі". Щоб реалізувати подібне managed рішення на Kubernetes, ми подивилися на поточний стан найбільш популярних операторів для PostgreSQL (Stolon, оператори від Crunchy Data і Zalando) і зробили свій вибір.
Ця стаття — набутий нами досвід і з теоретичної точки зору (огляд рішень), і з практичної сторони (що було обрано і що з цього вийшло). Але спочатку давайте визначимося, які взагалі вимоги пред'являються до потенційної заміни RDS…
Що ж таке RDS
Коли люди говорять про RDS, на наш досвід, вони мають на увазі керований (managed) сервіс СУБД, яка:
легко налаштовується;
має можливість роботи зі снапшотами та відновлюватись з них (бажано — з підтримкою PITR);
дозволяє створювати топологію master-slave;
має багатий перелік розширень;
надає аудит та керування користувачами/доступами.
Якщо говорити взагалі, то підходи до реалізації поставленого завдання можуть бути дуже різними, проте шлях з умовним Ansible нам не близький. (До такого висновку дійшли і колеги з 2GIS в результаті своєї спроби створити інструмент для швидкого розгортання відмовостійкого кластера на основі Postgres.
Саме оператори є загальноприйнятим підходом для вирішення подібних завдань в екосистемі Kubernetes. Докладніше про них стосовно баз даних, що запускаються всередині Kubernetes, вже розповідав техдир «Фланта», distol, в
одній зі своїх доповідей.
NB: Для швидкого створення нескладних операторів рекомендуємо звернути увагу на нашу Open Source-утиліту shell-operator. Використовуючи її, можна це робити без знань Go, а звичнішими для сисадмінів способами: на Bash, Python і т.п.
Для PostgreSQL існує декілька популярних K8s-операторів:
Stolon;
Crunchy Data PostgreSQL Operator;
Zalando Postgres Operator.
Подивимося на них уважніше.
вибір оператора
Окрім тих важливих можливостей, що вже були згадані вище, ми, як інженери з експлуатації інфраструктури в Kubernetes, також очікували від операторів наступного:
Не вдаючись у деталі по кожному з пунктів (питайте в коментарях, якщо залишаться питання щодо них після прочитання всієї статті), зазначу загалом, що ці параметри потрібні для більш тонкого опису спеціалізації вузлів кластера для того, щоб замовляти їх під конкретні програми. Так ми можемо досягти оптимального балансу у питаннях продуктивності та вартості.
Тепер - до самих операторів PostgreSQL.
1. Stolon
Столон від італійської компанії Sorint.lab в вже згаданій доповіді розглядався як еталон серед операторів для СУБД. Це досить старий проект: перший його публічний реліз відбувся ще в листопаді 2015 року (!), а GitHub-репозиторій може похвалитися майже 3000 зірками та 40+ контріб'юторами.
Stolon — чудовий приклад продуманої архітектури:
З пристроєм цього оператора у подробицях можна ознайомитись у доповіді або документації проекту. Загалом, досить сказати, що він вміє все описане: failover, проксі для прозорого доступу клієнтів, бекапи… Причому проксі надають доступ через один сервіс endpoint — на відміну від двох інших рішень, розглянутих далі (у них по два сервіси для доступу до базі).
Однак у Stolon ні Custom Resources, через що його не можна так деплоїти, щоб просто і швидко — «як гарячі пиріжки» створювати екземпляри СУБД у Kubernetes. Управління здійснюється через утиліту stolonctl, деплой - через Helm-чарт, а користувачі визначаються задаються в ConfigMap.
З одного боку, виходить, що оператор не є оператором (адже він не використовує CRD). Але з іншого боку - це гнучка система, яка дозволяє налаштовувати ресурси в K8s так, як вам зручно.
Резюмуючи, особисто нам не видався оптимальним шлях заводити окремий чарт під кожну БД. Тому ми почали шукати альтернативи.
2. Crunchy Data PostgreSQL Operator
Оператор від Crunchy Data, молодого американського стартапу, виглядав логічною альтернативою Його публічна історія починається з першого релізу в березні 2017 року, відтоді GitHub-репозиторій отримав трохи менше 1300 зірок та 50+ контріб'юторів. Останній реліз від вересня був протестований на роботу з Kubernetes 1.15-1.18, OpenShift 3.11+ та 4.4+, GKE та VMware Enterprise PKS 1.3+.
Архітектура Crunchy Data PostgreSQL Operator також відповідає заявленим вимогам:
Управління відбувається через утиліту pgo, проте вона у свою чергу генерує Custom Resources для Kubernetes. Тому нас як потенційних користувачів оператор порадував:
є керування через CRD;
зручне керування користувачами (теж через CRD);
інтеграція з іншими компонентами Crunchy Data Container Suite - Спеціалізована колекція образів контейнерів для PostgreSQL і утиліт для роботи з нею (включаючи pgBackRest, pgAudit, розширення з contrib і т.д.).
Проте спроби почати використовувати оператор від Crunchy Data виявили кілька проблем:
Не виявилося можливості tolerations — передбачено лише nodeSelector.
Створювані pod'и були частиною Deployment'а, незважаючи на те, що ми деплоїли stateful-додаток. На відміну від StatefulSet, Deployment'и не вміють створювати диски.
Останній недолік призводить до кумедних моментів: на тестовому середовищі вдалося запустити 3 репліки з одним диском локальне сховищеУ результаті оператор повідомляв, що 3 репліки працюють (хоча це було не так).
Ще однією особливістю цього оператора є готова інтеграція з різними допоміжними системами. Наприклад, легко встановити pgAdmin і pgBounce, а в документації розглядаються передналаштовані Grafana та Prometheus. У недавньому релізі 4.5.0-beta1 окремо відзначається покращена інтеграція з проектом pgMonitor, Завдяки чому оператор пропонує наочну візуалізацію метрик по PgSQL «з коробки».
Проте дивний вибір генерованих Kubernetes-ресурсів привів нас до необхідності знайти інше рішення.
3. Zalando Postgres Operator
Продукти Zalando нам відомі давно: є досвід використання Zalenium і, звісно, ми пробували Патрони — їхнє популярне HA-рішення для PostgreSQL. Про підхід компанії до створення Postgres Operator розповідав один із його авторів — Олексій Клюкін — в ефірі Postgres-вівторка №5, і нам він сподобався.
Це наймолодше рішення з тих, що розглядаються у статті: перший реліз відбувся в серпні 2018 року. Однак, навіть незважаючи на невелику кількість формальних релізів, проект пройшов великий шлях, вже випередивши за популярністю рішення від Crunchy Data з 1300+ зірками на GitHub та максимальною кількістю контриб'юторів (70+).
Під капотом цього оператора використовуються рішення, перевірені часом:
Ось як представлена архітектура оператора від Zalando:
Оператор повністю управляється через Custom Resources, автоматично створює StatefulSet з контейнерів, які потім можна кастомізувати, додаючи в pod різні sidecar'и. Все це значний плюс у порівнянні з оператором від Crunchy Data.
Оскільки саме рішення від Zalando ми вибрали серед 3 варіантів, подальший опис його можливостей буде представлений нижче, відразу разом з практикою застосування.
Практика з Postgres Operator від Zalando
Деплой оператора відбувається дуже просто: достатньо завантажити актуальний реліз з GitHub та застосувати YAML-файли з директорії маніфести. Як варіант, можна також скористатися OperatorHub.
Після встановлення варто подбати про налаштування сховищ для логів та бекапів. Вона провадиться через ConfigMap postgres-operator у просторі імен, куди ви встановили оператор. Коли сховища налаштовані, можна розгорнути перший кластер PostgreSQL.
Даний маніфест деплоїть кластер з 3 екземплярів з sidecar у вигляді postgres_exporterз якого ми знімаємо метрики програми. Як бачите, все дуже просто, і за бажання можна зробити буквально необмежену кількість кластерів.
Варто звернути увагу і на веб-панель для адміністрування - postgres-operator-ui. Вона поставляється разом з оператором і дозволяє створювати та видаляти кластери, а також працювати з бекапами, які робить оператор.
Список кластерів PostgreSQL
Управління бекапами
Іншою цікавою особливістю є підтримка API команд. Цей механізм автоматично створює ролі в PostgreSQL, виходячи з отриманого списку імен користувачів. Після цього API дає змогу повернути список користувачів, для яких автоматично створюються ролі.
Проблеми та їх вирішення
Однак використання оператора незабаром виявило кілька вагомих недоліків:
відсутність підтримки nodeSelector;
неможливість вимкнути бекапи;
при використанні функції створення баз не з'являються стандартні привілеї;
періодично не вистачає документації або вона перебуває в неактуальному стані.
На щастя, багато хто з них може бути вирішений. Почнемо з кінця - проблем з документацією.
Швидше за все, ви зіткнетеся з тим, що не завжди ясно, як прописати бекап і як підключити бекапний бакет до Operator UI. Про це в документації йдеться побіжно, а реальний опис є в PR:
потрібно зробити секрет;
передати його оператору в параметр pod_environment_secret_name у CRD з налаштуваннями оператора або ConfigMap (залежить від того, як ви вирішили встановлювати оператор).
Однак, як виявилось, на даний момент це неможливо. Саме тому ми зібрали свою версію оператора з деякими додатковими сторонніми напрацюваннями. Докладніше про неї див. нижче.
Якщо передавати оператору параметри для бекапу, а саме — wal_s3_bucket та ключі доступу в AWS S3, то він буде бекапит все: не лише бази в production, а й staging. Нас це не влаштувало.
В описі параметрів Spilo, що є базовою Docker-оберткою для PgSQL при використанні оператора, з'ясувалося: можна передати параметр WAL_S3_BUCKET порожнім, тим самим відключивши бекапи. Більше того, на велику радість знайшовся і готовий PR, який ми одразу прийняли у свій форк. Тепер досить просто додати enableWALArchiving: false ресурс кластера PostgreSQL.
Так, була можливість зробити інакше, запустивши 2 оператори: один для staging (без бекапів), а другий для production. Але так ми змогли обійтися одним.
Ок, ми навчилися передавати бази доступ для S3 і бекапи почали потрапляти в сховище. Як змусити працювати сторінки бекапів у Operator UI?
У Operator UI потрібно додати 3 змінні:
SPILO_S3_BACKUP_BUCKET
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
Після цього управління бекапами стане доступним, що в нашому випадку спростить роботу зі staging, дозволивши доставляти туди зрізи з production без додаткових скриптів.
Як ще один плюс називалася робота з Teams API і широкі можливості для створення баз і ролей засобами оператора. Проте створювані ролі не мали прав за умовчанням. Відповідно, користувач із правами читання було читати нові таблиці.
Чому так? Незважаючи на те, що в коді є необхідні GRANTВони застосовуються далеко не завжди. Є 2 методи: syncPreparedDatabases и syncDatabases. У syncPreparedDatabases — незважаючи на те, що у секції preparedDatabasesє є умова defaultRoles и defaultUsers для створення ролей — права за замовчуванням не застосовуються. Ми в процесі підготовки патчу, щоб ці права автоматично застосовувалися.
І останній момент в актуальних для нас доробках. патч, що додає Node Affinity у створюваний StatefulSet. Наші клієнти часто вважають за краще скорочувати витрати, використовуючи spot-інстанси, а на них явно не варто розміщувати послуги БД. Це питання можна було б вирішити і через tolerations, але наявність Node Affinity дає більшу впевненість.
Що вийшло?
За підсумками вирішення перерахованих проблем ми форкнули Postgres Operator від Zalando в свій репозиторійде він збирається з настільки корисними патчами. А для більшої зручності зібрали і Docker-образ.
Буде чудово, якщо спільнота підтримає ці PR, щоб вони потрапили до upstream з наступною версією оператора (1.6).
Бонус! Історія успіху з міграцією production
Якщо ви використовуєте Patroni, оператор може мігрувати живий production з мінімальним простоєм.
Spilo дозволяє робити standby-кластери через S3-сховища з Wal-Eколи бінарний лог PgSQL спочатку зберігається в S3, а потім викачується реплікою. Але що робити, якщо у вас НЕ використовується Wal-E у старій інфраструктурі? Вирішення цієї проблеми вже було запропоновано на хабрі.
На допомогу приходить логічна реплікація PostgreSQL. Однак не вдаватимемося до деталей, як створювати публікації та підписки, бо… наш план зазнав фіаско.
Справа в тому, що в БД було кілька навантажених таблиць з мільйонами рядків, які до того ж постійно поповнювалися і видалялися. Проста передплата с copy_dataКоли нова репліка копіює весь вміст з майстра, просто не встигала за майстром. Копіювання контенту працювало тиждень, але так і не наздогнало майстер. У результаті розібратися з проблемою допомогла стаття колег з Avito: можна перенести дані, використовуючи pg_dump. Опишу наш (трохи доопрацьований) варіант цього алгоритму.
Ідея полягає в тому, що можна зробити вимкнену передплату, прив'язану до конкретного слота реплікації, а потім виправити номер транзакції. В наявності були репліки для роботи production'а. Це важливо, тому що репліка допоможе створити консистентний dump та продовжити отримувати зміни з майстра.
У наступних командах, що описують процес міграції, будуть використовуватися такі позначення для хостів:
майстер - Вихідний сервер;
репліка1 - Потокова репліка на старому production;
репліка2 - Нова логічна репліка.
План міграції
1. Створимо на майстрі передплату на всі таблиці у схемі public бази dbname:
psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"
Завдяки такому плану перемикання пройшло із мінімальними затримками.
Висновок
Оператори Kubernetes дозволяють спростити різні дії, звівши їх до створення K8s-ресурсів. Проте, домігшись чудової автоматизації з їх допомогою, варто пам'ятати, що вона може принести й низку несподіваних нюансів, тому підходьте до вибору операторів з розумом.
Розглянувши три найпопулярніші Kubernetes-оператори для PostgreSQL, ми зупинили свій вибір на проекті від Zalando. І з ним довелося подолати певні труднощі, але результат справді порадував, тому ми плануємо розширити цей досвід і на деякі інші інсталяції PgSQL. Якщо у вас є досвід використання подібних рішень - будемо раді побачити подробиці у коментарях!