Карта доменів відмови і тест передачі, який її доводить
Висока доступність є твердженням, доки її не протестовано. Як відобразити репліки на хости, масиви і шасі, забезпечити anti-affinity і провести тест failover.

На кожній діаграмі платформи є три бокси бази даних, два балансувальники і пара кешів, і кожен з них підписано «висока доступність». Чи так це насправді, залежить від двох документів, яких більшість збірок ніколи не створює: карти того, від яких фізичних речей залежить кожна репліка, і тестового аркуша, який фіксує, що сталося, коли кожну з них забрали. Ось як ми пишемо обидва.
Проблема: три репліки можуть бути однією відмовою
Резервування рахує копії. Доступність залежить від того, чи можуть ці копії відмовляти незалежно. Три вузли бази даних на трьох віртуальних машинах, які планувальник випадково розмістив на двох хостах, є, для відмови хоста, двома вузлами. Три вузли на трьох хостах, диски яких усі живуть на одному масиві storage, є, для відмови масиву, жодним. Ніщо в застосунку чи на дашборді не каже вам цього. Ви маєте це записати.
Крок перший: перелічіть домени відмови
Для типової платформи перелічіть щонайменше:
- Хост: фізичний сервер або блейд.
- Шасі: блейди ділять живлення, охолодження і міжз’єднання.
- Масив storage: і, під ним, шлях storage fabric.
- Мережа: пара top of rack switch, аплінки, межа.
- Сайт: ввід живлення, охолодження, сама будівля.
Потім вирішіть, які з них платформа мусить пережити. Пережити втрату будь-якого одного хоста і будь-якого одного масиву є розумним базовим рівнем; пережити цілий сайт потребує другого сайту і є іншим дизайном.
Крок другий: намалюйте карту
Складіть таблицю з одним рядком на кожного члена кожного резервованого рівня і однією колонкою на кожен домен відмови:
| Рівень | Член | Хост | Шасі | Масив |
|---|---|---|---|---|
| база даних | db-a | хост 1 | шасі 1 | масив A |
| база даних | db-b | хост 2 | шасі 2 | масив B |
| база даних | db-c | хост 3 | шасі 1 | масив C |
| кеш | cache-a | хост 2 | шасі 2 | масив A |
| ... |
Правило просте: у межах одного рівня жоден домен відмови, який ви вирішили пережити, не може містити більшість членів. Читайте вниз по кожній колонці для кожного рівня. Два з трьох членів бази даних у шасі 1 означає, що відмова шасі ламає кворум. Виправте розміщення або прийміть ризик письмово.
Крок третій: правильно порахуйте кворум
Якщо вам треба пережити дві одночасні відмови хостів, як часто повинен рівень storage, вам потрібні п’ять членів у п’яти окремих доменах, а не чотири: четвертий член додає вартість, не додаючи стійкості.
Крок четвертий: змусьте планувальник забезпечувати карту
Карта, яка залежить від того, що хтось правильно розмістить машини, буде неправильною після першого ж обслуговування. Змусьте платформу забезпечувати її.
У менеджері віртуалізації, як-от OLVM, створіть негативну, примусову affinity-групу на кожен рівень, щоб два члени ніколи не могли працювати на одному хості, навіть після того, як хост спорожнили.
У Kubernetes використовуйте обов’язкову pod anti-affinity і PodDisruptionBudget для кожного кворумного навантаження:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
[ { labelSelector: { matchLabels: { app: galera } },
topologyKey: kubernetes.io/hostname } ]
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: galera }
spec:
minAvailable: 2
selector:
matchLabels: { app: galera }
Anti-affinity тримає членів на різних вузлах; промаркуйте вузли за шасі і додайте друге правило за цією міткою, якщо шасі є доменом. Бюджет означає, що поступове оновлення вузлів ніколи не зможе витіснити другого члена, поки один уже лежить. Перевіряйте результат, а не намір:
kubectl get pods -l app=galera -o wide
Крок п’ятий: тестовий аркуш передачі
Тепер доведіть це. Для кожного рівня заберіть одного члена так, як це зробила б справжня відмова, з під’єднаним застосунком і справжнім трафіком, і запишіть, що сталося:
| Дія | Очікується | Виміряно | Що бачили клієнти |
|---|---|---|---|
| зупинити writer бази даних | proxy переносить записи на вцілілого | секунди до відновлення записів | |
| зупинити primary кешу | Sentinel підвищує репліку | секунди до підвищення | |
| вивести з ладу один edge-вузол | плаваюча адреса переходить до пари | секунди, в кожному напрямку | |
| вимкнути живлення одного хоста | його члени відбудовуються деінде, кворум тримається | ||
| від’єднати один шлях до масиву | трафік storage триває іншим шляхом |
Запускайте пробу з мітками часу ззовні під час кожного тесту, щоб «що бачили клієнти» було вимірюванням:
while true; do
printf '%s ' "$(date +%T.%N)"
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://app.example.com/health
sleep 0.2
done | tee failover-$(date +%F).log
Потім відновіть кожного члена і зафіксуйте, що він чисто приєднався назад, як репліка нового primary, а не як його суперник. Тест, який закінчується двома primary, знайшов найважливішу помилку на аркуші.
Крок шостий: нехай перевірить хтось інший
Людина, яка побудувала платформу, перевіряючи її, читає нотатки збірки, а нотатки збірки кажуть те, що було задумано. Нехай другий інженер звірить карту з живою платформою з іншої машини: запитає менеджер віртуалізації про фактичне розміщення, storage про фактичне розташування дисків, кластер про фактичне членство. Розбіжності між картою і реальністю є тими знахідками, що мають значення.
Ваш чекліст
- Домени відмови, які ви переживете, записані.
- Карта кожного члена кожного рівня проти цих доменів, без більшості в одному домені.
- Розміри кворуму обрані арифметикою, лише непарні числа.
- Anti-affinity і бюджети збоїв забезпечені платформою і перевірені.
- Тестовий аркуш передачі з виміряними часами і результатами з боку клієнта для кожного рівня.
- Незалежна перевірка проти живої платформи, а не нотаток.
Якщо ви хочете другу думку про те, наскільки незалежним є ваше резервування насправді, ми радо складемо карту разом з вами.
Related (rows[1])
Пов’язане: Побудова платформ високої доступності · Кластерні бази даних з Percona XtraDB Cluster · Object caching з автоматичним failover
Опубліковано 17 серпня 2026 р..
Усі нотатки з практики