У першій частині ми підняли авторитативний DNS на PowerDNS 5.1 з бекендом MariaDB і REST API. Він працює, але він один: впаде сервер - зникне весь DNS. Робимо його відмовостійким - додаємо другий сервер на репліці MariaDB.
Хитрість підходу в тому, що реплікацію робить база даних, а не сам PowerDNS. Обидва pdns читають зі свого локального MariaDB, а master-slave тримає бази синхронними. Жодних AXFR, also-notify чи налаштувань вторинних зон у самому PowerDNS - DNS-ноди «тупі», уся синхронізація живе в MariaDB.
Що потрібно зробити?#
Налаштувати MariaDB master-slave між двома серверами: майстер (ns1 з частини 1) приймає зміни, репліка (ns2) отримує їх автоматично. Реплікаційний трафік пустимо окремою приватною мережею, а не тією, якою ходять DNS-запити. На репліці підніму другий pdns, що читає локальну копію бази, і покажу головне: зміна зони на майстрі з’являється на репліці сама. Усе записав наживо у двох панелях - ліворуч майстер, праворуч репліка.
З чим працюю?#
Дві машини Debian 13, кожна з двома інтерфейсами:
| |
- eth0 - «публічна» мережа, якою ходять DNS-запити й керування (на реальному VPS це публічні IP).
- eth1 - окрема приватна мережа
10.20.0.0/24тільки для реплікації MariaDB. Так реплікаційний трафік (і відкритий порт3306) не світиться там, де DNS.
На реальних серверах замість приватної SDN-мережі це буде приватна мережа провайдера між вашими VPS (або VPN). Логіка та сама.
Далі те саме, що в записі, тільки вже можна копіювати.
Майстер: вмикаємо бінлог#
На ns1 (майстрі) створюємо /etc/mysql/mariadb.conf.d/60-replication.cnf:
| |
bind-address = 10.20.0.1 - MariaDB слухатиме лише на приватному інтерфейсі. Локальний pdns це не зачіпає: він ходить до бази через unix-сокет (gmysql-host=localhost), а не TCP.
| |
Створюємо користувача реплікації - дозволяємо підключатися тільки з приватної адреси репліки:
| |
REPLICATION SLAVEпотрібен для самої реплікації, аSELECT, SHOW VIEW ON pdns.*- щоб цим же користувачем зручно залити початковий знімок бази (нижче). У проді seed-дамп можна робити й окремим користувачем.
Репліка: server-id і read-only#
На ns2 (репліці) - свій 60-replication.cnf. Головне: інший server-id і read_only, щоб ніхто випадково не писав у репліку повз майстра:
| |
| |
Репліка: початковий знімок бази#
Реплікація переносить лише нові зміни - тож спершу треба залити поточний стан бази pdns. Робимо це прямо з репліки, потоком по приватній мережі, без проміжних файлів:
| |
--gtid додає в дамп позицію GTID, з якої репліка почне доганяти майстра, а --single-transaction знімає узгоджений знімок без блокувань.
Користувачів MariaDB реплікація не переносить (вони в системній базі mysql), тож локального користувача pdns на репліці створюємо руками - з тим самим паролем, що й на майстрі:
| |
read_onlyблокує записи для звичайних користувачів, алеrootчерез сокет (він з привілеєм SUPER) - і потік реплікації - пишуть попри нього. Тому і seed, і створення користувача спокійно проходять.
Запускаємо реплікацію#
Вказуємо репліці на майстра по GTID і стартуємо:
| |
Маємо побачити:
| |
Два Yes і нуль відставання - реплікація жива.
pdns на репліці#
Залишилось сказати другому pdns читати локальну базу. Конфіг - той самий, що й на майстрі в частині 1 (прибираємо дефолтний bind-бекенд, вмикаємо gmysql):
| |
/etc/powerdns/pdns.d/gmysql.conf:
| |
| |
Зону example.com на репліці ми не заводили - вона приїхала з майстра реплікацією. pdns просто читає локальну базу й роздає її.
Головне: зміна на майстрі - сама на репліці#
Додаємо новий запис на майстрі через API (як у частині 1):
| |
І одразу питаємо репліку:
| |
Запис з’явився на репліці сам, за долю секунди - ми його туди не заводили. Ось заради чого вся схема: керуєте зонами в одному місці (на майстрі, через API), а репліка підхоплює зміни автоматично.
Писати - тільки на майстрі#
Спроба змінити зону на репліці очікувано відбивається:
| |
Це правильно: master-slave - односторонній. Усі зміни йдуть на майстер, репліка лише роздає. Про зворотний бік (що буде, якщо впаде майстер) - нижче.
А відмовостійкість?#
Тепер у вас дві ноди з однаковими даними. Як це вмикає HA для authoritative DNS:
- Делегування на два NS. У реєстратора / батьківській зоні вказуєте обидва сервери:
ns1.example.comіns2.example.comз їхніми IP. Резолвери самі перебирають їх - не відповів один, питають інший. Це і є головний механізм відмовостійкості authoritative DNS, і він тут працює «безкоштовно». - Репліка роздає, навіть якщо майстер лежить. Поки живий ns2, запити обслуговуються - дані ж у нього вже є.
- Чого ще немає. Master-slave односторонній: якщо впаде майстер, репліка сама писати не почне (зони тимчасово не можна змінювати, доки не піднімете майстер або не підвищите репліку вручну). Для authoritative DNS це зазвичай не біда - зони міняють рідко. Автоматичний failover запису - це вже інша історія (Galera чи ручний promote).
Граблі#
- Seed-дамп треба з
--databases.mysqldump pdnsбез--databasesне міститьCREATE DATABASE/USE, і імпорт падає зNo database selected. З--databases pdnsусе на місці, а--gtidще й виставляє стартову позицію реплікації. - Користувачів реплікація не переносить. Вони в системній базі
mysql. Локальногоpdns@localhostна репліці створюйте руками, тим самим паролем, що на майстрі - інакше pdns на репліці не підключиться до бази. read_onlyне заважає seed і реплікації.rootчерез сокет і потік реплікації мають привілей SUPER і пишуть поприread_only. Блокуються лише звичайні користувачі - саме те, що треба.- Прив’язуйте реплікацію до приватної мережі.
bind-addressMariaDB на приватну адресу +'repl'@'<приватний IP>'тримають порт3306і реплікаційний трафік подалі від публічної мережі. Локальний pdns це не зачіпає - він через сокет.
Що далі#
Дані тепер надійні, але вхід - ще ні: DNS-запити йдуть прямо в pdns, без балансування й захисту. У наступній частині ставимо dnsdist спереду на кожній ноді: балансування на локальний pdns із резервом на сусіда, health-check і вимкнення хворої ноди з ротації. А потім - тюнинг проти флуду.
Підсумок#
Відмовостійкий DNS вийшов простим, бо синхронізацію ми віддали базі. MariaDB master-slave з GTID по приватній мережі тримає дві копії зон; pdns на кожній ноді просто читає локальну базу. Керуємо з одного місця через API на майстрі, репліка підхоплює зміни сама, а два NS-записи дають резолверам запасний сервер. Далі зробимо надійним і сам вхід.



