Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Запровадження

Нещодавно переді мною поставили завдання розробити відмовостійкий кластер для PostgreSQL, що працює у кількох дата-центрах, об'єднаних оптоволокном у межах одного міста, і здатний витримати відмову (наприклад, знеструмлення) одного дата-центру. Як софт, який відповідає за відмовостійкість, вибрав Кардіостимулятор, тому що це офіційне рішення від RedHat для створення відмовостійких кластерів. Воно добре тим, що RedHat забезпечує його підтримку, і тим, що це універсальне рішення (модульне). З його допомогою можна буде забезпечити стійкість до відмови не тільки PostgreSQL, але і інших сервісів, або використовуючи стандартні модулі, або створюючи їх під конкретні потреби.

До цього рішення виникло резонне питання: наскільки відмовостійким буде відмовостійкий кластер? Щоб це дослідити, я розробив тестовий стенд, який імітує різні відмови на вузлах кластера, чекає відновлення працездатності, відновлює вузол, що відмовив, і продовжує тестування в циклі. Спочатку цей проект називався hapgsql, але згодом мені набридла назва, в якій тільки одна голосна. Тому стійкі до відмови бази даних (і float IP, на них вказують) я став іменувати кроган (персонаж із комп'ютерної гри, у якого всі важливі органи дубльовані), а вузли, кластери та сам проект — tuchanka (Планета, де живуть крогани).

Зараз керівництво дозволило відкрити проект для open source-спільноти під ліцензією MIT. README незабаром буде перекладено англійською мовою (оскільки очікується, що основними споживачами будуть розробники Pacemaker і PostgreSQL), а старий російський варіант README я вирішив оформити (частково) у вигляді цієї статті.

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Кластери розгортаються на віртуалках VirtualBox. Усього буде розгорнуто 12 віртуалок (сумарно 36GiB), які утворюють 4 відмовостійкі кластери (різні варіанти). Перші два кластери складаються з двох серверів PostgreSQL, які розміщені в різних дата-центрах, та загального сервера свідок c quorum device (розміщений на дешевій віртуалці у третьому дата-центрі), що дозволяє невизначеність 50% / 50%, віддаючи свій голос однієї із сторін. Третій кластер у трьох дата-центрах: один майстер, два раби, без quorum device. Четвертий кластер складається з чотирьох серверів PostgreSQL, по два на дата-центр: один майстер, решта реплік, і теж використовує свідок c quorum device. Четвертий витримує відмову двох серверів чи одного дата-центру. Це рішення може бути, за потреби, масштабовано на більшу кількість реплік.

Сервіс точного часу ntpd теж переналаштований для стійкості до відмови, але там використовуються метод самого ntpd (orphan mode). Загальний сервер свідок виконує роль центрального NTP-сервера, роздаючи свій час усім кластерам, тим самим синхронізуючи всі сервери між собою. Якщо свідок вийде з ладу або виявиться ізольованим, тоді свого часу почне роздавати один із серверів кластера (всередині кластера). Допоміжний кешируючий HTTP проксі теж піднятий на свідок, З його допомогою інші віртуалки мають доступ до Yum-репозиторіям. Насправді такі послуги, як точний час і проксі, напевно будуть розміщені на виділених серверах, а в стенді вони розміщені на свідок тільки для економії кількості віртуалок та місця.

Версії

v0. Працює з CentOS 7 та PostgreSQL 11 на VirtualBox 6.1.

Структура кластерів

Усі кластери призначені для розміщення в кількох дата-центрах, об'єднані в одну плоску мережу та повинні витримувати відмову або мережеву ізоляцію одного дата-центру. Тому неможливо використовувати для захисту від split-brain стандартну технологію Pacemaker, яка називається STONITH (Shoot The Other Node In The Head) або фехтування. Її суть: якщо вузли в кластері починають підозрювати, що з якимось вузлом відбувається негаразд, він не відповідає або некоректно поводиться, то вони примусово його відключають через «зовнішні» пристрої, наприклад, керуючу картку IPMI або UPS. Але це спрацює тільки у випадках, коли при одиничній відмові сервера IPMI або UPS продовжують працювати. Тут же планується захист від більш катастрофічної відмови, коли відмовляє (наприклад, знеструмлюється) весь дата-центр. А при такій відмові все stonith-Пристрої (IPMI, UPS і т.д.) теж не будуть працювати.

Натомість в основі системи лежить ідея кворуму. Всі вузли мають голос, і працювати можуть тільки ті, що бачать більше половини всіх вузлів. Ця кількість «половина+1» називається кворум. Якщо кворум не набирається, то вузол вирішує, що він перебуває у мережевий ізоляції і має відключити свої ресурси, тобто. це така захист від split-brain. Якщо софт, який відповідає за таку поведінку, не працює, то повинен буде спрацювати watchdog, наприклад, на базі IPMI.

Якщо кількість вузлів парна (кластер у двох дата-центрах), то може виникнути так звана невизначеність 50% / 50% (фіфті-фіфті), коли мережева ізоляція ділить кластер рівно навпіл. Тому для парної кількості вузлів додається quorum device — невибагливий демон, який може бути запущений на найдешевшій віртуалці у третьому дата-центрі. Він дає свій голос одному з сегментів (який бачить), і цим дозволяє невизначеність 50%/50%. Сервер, на якому буде запущено quorum device, я назвав свідок (Термінологія з repmgr, мені сподобалася).

Ресурси можуть переїжджати з місця на місце, наприклад, з несправних серверів на справні або за командою сисадмінів. Щоб клієнти знали, де потрібні їм ресурси (куди підключатися?), використовуються плаваючі IP (float IP). Це IP, які Pacemaker може переміщати вузлами (все знаходиться в плоскій мережі). Кожен із них символізує ресурс (сервіс) і буде там, куди треба підключатися, щоб отримати доступ до цього сервісу (у нашому випадку БД).

Tuchanka1 (схема з ущільненням)

Структура

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Ідея була в тому, що у нас є багато дрібних баз даних з низьким навантаженням, для яких невигідно утримувати виділений slave-сервер у режимі hot standby для read only-транзакцій (немає необхідності в такій розтраті ресурсів).

У кожному дата центрі по одному серверу. На кожному сервері по два інстанси PostgreSQL (у термінології PostgreSQL вони називаються кластерами, але щоб уникнути плутанини я називатиму їх інстансами (за аналогією з іншими БД), а кластерами називатиму тільки кластери Pacemaker). Один інстанс працює в режимі майстра, і тільки він надає послуги (тільки на нього веде float IP). Другий інстанс працює рабом для другого дата-центру, і надаватиме послуги лише якщо його майстер вийде з ладу. Оскільки більшу частину часу надавати послуги (виконувати запити) буде лише один інстанс із двох (майстер), всі ресурси сервера оптимізуються на майстер (виділяється пам'ять під кеш shared_buffers і т.д.), але так, щоб на другий інстанс теж вистачило ресурсів ( нехай і для неоптимальної роботи через кеш файлової системи) у разі відмови одного з дата-центрів. Раб не надає послуги (не виконує read only-запити) при нормальній роботі кластера, щоб не було війни за ресурси з майстром на тій самій машині.

У випадку з двома вузлами стійкість до відмов можлива тільки при асинхронній реплікації, так як при синхронній відмова раба призведе до зупинки майстра.

Відмова witness

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Відмова witness (quorum device) я розгляну тільки для кластера Tuchanka1, з рештою буде та ж історія. При відмові witness у структурі кластера нічого не зміниться, все продовжить працювати так само, як і працювало. Але кворум дорівнюватиме 2 з 3, і тому будь-яка наступна відмова стане фатальною для кластера. Все одно доведеться терміново лагодити.

Відмова Tuchanka1

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Відмова від одного з дата-центрів для Tuchanka1. В цьому випадку свідок віддає свій голос другому вузлу другого дата-центрі. Там колишній раб перетворюється на майстра, в результаті на одному сервері працюють обидва майстри і на них вказують обидва їх float IP.

Tuchanka2 (класична)

Структура

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Класична схема із двох вузлів. На одному працює майстер, на другому – раб. Обидва можуть виконувати запити (раб лише read only), тому обох вказують float IP: krogan2 — на майстер, krogan2s1 — на раба. Відмовостійкість буде і в майстра, і в раба.

У випадку з двома вузлами стійкість до відмов можлива тільки при асинхронній реплікації, тому що при синхронній відмова раба призведе до зупинки майстра.

Відмова Tuchanka2

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

У разі відмови одного з дата-центрів свідок голосує за другий. На єдиному працюючому дата-центрі буде піднятий майстер, і на нього будуть вказувати обидва float IP: майстерня та рабська. Зрозуміло, інстанс має бути налаштований таким чином, щоб у нього вистачило ресурсів (лімітів під connection і т.д.) одночасно приймати всі підключення та запити від майстерні та рабського float IP. Тобто при нормальній роботі він повинен мати достатній запас по лімітах.

Tuchanka4 (багато рабів)

Структура

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Вже інша крайність. Бувають БД, на які йде багато запитів read-only (типовий випадок високонавантаженого сайту). Tuchanka4 - це ситуація, коли рабів може бути три або більше для обробки таких запитів, але все ж таки не дуже багато. За дуже великої кількості рабів треба буде винаходити ієрархічну систему реплікування. У мінімальному випадку (на малюнку) у кожному з двох дата-центрів знаходиться по два сервери, на кожному з яких за інстансом PostgreSQL.

Ще однією особливістю цієї схеми є те, що тут можна організувати одну синхронну реплікацію. Вона налаштована так, щоб реплікувати, наскільки можна, в інший дата-центр, а чи не на репліку у тому дата-центрі, де й майстер. На майстер і кожен раб вказує float IP. На добре, між рабами треба буде робити балансування запитів якимось SQL proxyнаприклад, на стороні клієнта. Різному типу клієнтів може бути потрібний різний тип SQL proxy, І тільки розробники клієнтів знають, кому який потрібний. Ця функціональність може бути реалізована як зовнішнім демоном, і бібліотекою клієнта (connection pool), тощо. Все це виходить за межі теми відмовостійкого кластера БД (відмовостійкість SQL proxy можна буде реалізувати незалежно, разом із відмовостійкістю клієнта).

Відмова Tuchanka4

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

У разі відмови одного дата-центру (тобто двох серверів) witness голосує за другий. В результаті в другому дата-центрі працюють два сервери: на одному працює майстер, і на нього вказує майстерний float IP (для прийому read-write запитів); а на другому сервері працює раб із синхронною реплікацією, і на нього вказує один з рабських float IP (для read only-запитів).

Перше, що треба відзначити: робітниками рабський float IP будуть не всі, а лише один. І для коректної роботи з ним потрібно буде, щоб SQL proxy перенаправляв усі запити на єдиний float IP, що залишився; а якщо SQL proxy ні, то можна перерахувати всі float IP рабів через кому в URL для підключення. У такому випадку з libpq підключення буде до першого робочого IP, так зроблено у системі автоматичного тестування. Можливо, в інших бібліотеках, наприклад JDBC, так працювати не буде і необхідний SQL proxy. Так зроблено тому, що у float IP для рабів варто заборона одночасно підніматися одному сервері, щоб вони рівномірно розподілялися по рабським серверам, якщо їх працює кілька.

Друге: навіть у разі відмови дата-центру зберігатиметься синхронна реплікація. І навіть якщо відбудеться вторинна відмова, тобто в дата-центрі, що залишився, вийде з ладу один з двох серверів, кластер хоч і перестане надавати послуги, але все ж таки збереже інформацію про всі закоммічені транзакції, на які він дав підтвердження про комітет (не буде втрати інформації при вторинному відмові).

Tuchanka3 (3 дата-центри)

Структура

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Це кластер для ситуації, коли є три повноцінно працюючі дата-центри, у кожному з яких є повноцінно працюючий сервер БД. В цьому випадку quorum device не потрібен. В одному дата-центрі працює майстер, у двох інших – раби. Реплікація синхронна типу ANY (slave1, slave2), тобто клієнту буде приходити підтвердження комміту, коли будь-який з рабів першим відповість, що він прийняв коміт. На ресурси вказує один float IP для майстра та два для рабів. На відміну від Tuchanka4 всі три float IP відмовостійкі. Для балансування read-only SQL-запитів можна використовувати SQL proxy (з окремою стійкістю до відмови), або половині клієнтів призначити один рабський float IP, а іншій половині - другий.

Відмова Tuchanka3

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

У разі відмови одного з дата-центрів залишаються два. В одному піднято майстер і float IP від ​​майстра, у другому — раб і обидва рабські float IP (на інстансі має бути дворазовий запас по ресурсах, щоб прийняти всі підключення з обох рабських float IP). Між майстрами та рабом синхронна реплікація. Також кластер збереже інформацію про закоммічені та підтверджені транзакції (не буде втрати інформації) у разі знищення двох дата-центрів (якщо вони знищені не одночасно).

Детальний опис файлової структури та розгортання я вирішив не вставляти. Хто захоче погратися, можете все це прочитати у README. Я наводжу лише опис автоматичного тестування.

Система автоматичного тестування

Для перевірки стійкості до відмови кластерів з імітацією різних несправностей зроблено систему автоматичного тестування. Запускається скриптом test/failure. Скрипт може приймати як параметри номера кластерів, які хочеться потестувати. Наприклад, ця команда:

test/failure 2 3

буде тестувати лише другий та третій кластер. Якщо параметри не вказані, тестуватимуться всі кластери. Усі кластери тестуються паралельно, а результат виводиться на панелі tmux. Tmux використовує виділений tmux сервер, тому скрипт можна запускати з-під default tmux, вийде вкладений tmux. Рекомендую застосовувати термінал у великому вікні та з маленьким шрифтом. Перед початком тестування всі віртуалки відкочуються на снепшот на момент завершення скрипту. setup.

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Термінал розбитий на колонки за кількістю тестованих кластерів, за замовчуванням (на скріншоті) їх чотири. Зміст колонок я розпишу на прикладі Tuchanka2. Панелі на скріншоті пронумеровані:

  1. Тут виводиться статистика з тестів. Колонки:
    • недостатність - Назва тесту (функції у скрипті), який емулює несправність.
    • реакція — середній арифметичний час за секунди, за який кластер відновив свою працездатність. Вимірюється від початку роботи скрипта, що емулює несправність, і до моменту, коли кластер відновлює свою працездатність і здатний продовжувати надавати послуги. Якщо час дуже маленький, наприклад, шість секунд (так буває в кластерах з кількома рабами (Tuchanka3 і Tuchanka4)), це означає, що несправність виявилася на асинхронному рабі і ніяк не вплинула на працездатність, перемикання стану кластера не було.
    • відхилення - показує розкид (точність) значення реакція методом "стандартна девіація".
    • вважати - Скільки разів був виконаний цей тест.
  2. Короткий журнал дозволяє оцінити, чим кластер займається в поточний момент. Виводиться номер ітерації (тесту), тимчасова мітка та назва операції. Занадто довге виконання (> 5 хвилин) говорить про якусь проблему.
  3. серце (Серце) – поточний час. Для візуальної оцінки працездатності майстра у його таблиці постійно пишеться поточний час з використанням float IP майстра. У разі успіху результат виводиться у цій панелі.
  4. бити (пульс) - "поточний час", який раніше був записаний скриптом серце у майстер, тепер зчитується з раба через його float IP. Дозволяє візуально оцінити працездатність раба та реплікації. У Tuchanka1 немає рабів з float IP (немає рабів, що надають послуги), але там два інстанси (БД), тому тут буде показуватися не бити, а серце другого інстансу.
  5. Моніторинг стану кластера за допомогою утиліти pcs mon. Показує структуру, розподіл ресурсів за вузлами та іншу корисну інформацію.
  6. Тут виводиться системний моніторинг із кожної віртуалки кластера. Таких панелей може бути більше — скільки віртуалок у кластера. Два графіки CPU Load (у віртуалках по два процесори), ім'я віртуалки, Завантаження системи (Названий як Load Average, тому що він усереднений за 5, 10 і 15 хвилин), дані по процесах і розподіл пам'яті.
  7. Трасування скрипта, що виконує тестування. У разі несправності — раптового переривання роботи або нескінченного циклу очікування тут можна буде побачити причину такої поведінки.

Тестування проводиться у два етапи. Спочатку скрипт проходить по всіх різновидах тестів, випадково вибираючи віртуалку, до якої цей тест застосувати. Потім виконується нескінченний цикл тестування, віртуалки та несправність щоразу вибираються випадковим чином. Раптове завершення скрипта тестування (нижня панель) або нескінченний цикл очікування чогось (> 5 хвилин час виконання однієї операції, це видно в трасуванні) говорить про те, що якийсь із тестів на цьому кластері провалився.

Кожен тест складається з наступних операцій:

  1. Запуск функції, що емулює несправність.
  2. Готовий? — очікування на відновлення працездатності кластера (коли надаються всі послуги).
  3. Відображається час очікування відновлення кластера (реакція).
  4. виправляти - Кластер «лагодиться». Після чого він має повернутися до повністю працездатного стану та готовності до наступної несправності.

Ось список тестів з описом, що вони роблять:

  • ForkBomb: створює "Out of memory" за допомогою форк-бомби
  • OutOfSpace: переповнює вінчестер Але тест, скоріше, символічний, при тому незначному навантаженні, яке створюється при тестуванні, при переповненні вінчестера відмови PostgreSQL зазвичай не відбувається.
  • Postgres-KILL: вбиває PostgreSQL командою killall -KILL postgres.
  • Postgres-STOP: підвішує PostgreSQL командою killall -STOP postgres.
  • Вимкнення живлення: «знеструмлює» віртуалку командою VBoxManage controlvm "виртуалка" poweroff.
  • скидання: перевантажує віртуалку командою VBoxManage controlvm "виртуалка" reset.
  • SBD-STOP: підвішує демон SBD командою killall -STOP sbd.
  • Закрити: через SSH посилає на віртуалку команду systemctl poweroffсистема коректно завершує роботу.
  • UnLink: мережна ізоляція, команда VBoxManage controlvm "виртуалка" setlinkstate1 off.

Завершення тестування або за допомогою стандартної команди tmux "kill-window" Ctrl-b &, або командою "detach-client" Ctrl-b d: тестування завершується, tmux закривається, віртуалки вимикаються.

Виявлені під час тестування проблеми

  • На поточний момент watchdog демон sbd відпрацьовує зупинку демонів, що спостерігаються, але не їх зависання. І, як наслідок, некоректно відпрацьовуються несправності, що призводять до зависання лише Corosync и Кардіостимулятор, але при цьому не підвішують sbd. Для перевірки Corosync вже є PR №83 (у GitHub у sbd), прийнятий у гілку майстер. Обіцяли (у PR#83), що і для Pacemaker буде щось подібне, сподіваюся, що до Червоний капелюх 8 зроблять. Але подібні «несправності» умоглядні, легко імітуються штучно за допомогою, наприклад, killall -STOP corosyncале ніколи не зустрічаються в реальному житті.

  • У Кардіостимулятор у версії для 7 CentOS неправильно виставлено sync_timeout у quorum device, в результаті при відмові одного вузла з певною ймовірністю перезавантажувався і другий вузол, на який мав переїхати майстер. Вилікувалося збільшенням sync_timeout у quorum device під час розгортання (у скрипті setup/setup1). Ця поправка не була прийнята розробниками Кардіостимулятор, натомість вони пообіцяли переробити інфраструктуру таким чином (у деякому невизначеному майбутньому), щоб цей тайм-аут обчислювався автоматично.

  • Якщо при конфігуруванні бази даних зазначено, що в LC_MESSAGES (текстові повідомлення) може використовуватися Юнікод, наприклад, ru_RU.UTF-8, то під час запуску постгреси в оточенні, де locale не UTF-8, припустимо, в порожньому оточенні (тут кардіостимулятор+pgsqlms(paf) запускає постгреси), То у лозі замість букв UTF-8 будуть знаки питання. Розробники PostgreSQL так і не домовилися, що робити у цьому випадку. Це обходиться, треба ставити LC_MESSAGES=en_US.UTF-8 при конфігуруванні (створенні) інстансу БД.

  • Якщо виставлений wal_receiver_timeout (за замовчуванням він 60s), то при тесті PostgreSQL-STOP на майстрі кластерів tuchanka3 і tuchanka4 не відбувається перепідключення реплікації до нового майстра. Реплікація там синхронна, тому зупиняється як раб, а й новий майстер. Обходиться установкою wal_receiver_timeout=0 під час налаштування PostgreSQL.

  • Зрідка спостерігав підвисання реплікації у PostgreSQL у тесті ForkBomb (переповнення пам'яті). Після ForkBomb іноді раби можуть не перепідключатися до нового майстра. Я зустрічав таке лише у кластерах tuchanka3 та tuchanka4, де через те, що реплікація синхронна, підвисав майстер. Проблема проходила сама, через якийсь тривалий час (близько двох годин). Потрібне додаткове дослідження, щоб це виправити. За симптомами схоже попередній баг, який викликається іншою причиною, але з однаковими наслідками.

Картинка крогана взята з Deviant Art з дозволу автора:

Моделювання відмовостійких кластерів на базі PostgreSQL та Pacemaker

Джерело: habr.com

Додати коментар або відгук