Два сервера. Два блока питания. Два коммутатора. Кластер из трёх узлов. На схеме всё выглядит отказоустойчиво. Но затем выходит из строя одна СХД — и останавливается весь сервис. Или оба application-сервера подключены к одному коммутатору. Или резервный экземпляр базы существует, но переключение на него никто никогда не проверял. Поэтому:
резервирование компонентов
≠
устранение единственной точки отказа
Что такое SPOF
SPOF — Single Point of Failure, то есть единственная точка отказа.
Это компонент или зависимость, отказ которой способен нарушить работу всей системы, потому что рабочего альтернативного пути нет.
Простейший пример:
users ↓ app01 ↓ database
Если app01 единственный:
app01 FAIL
↓
service unavailable
SPOF очевиден. Но реальные инфраструктуры интереснее.
Два сервера ещё не означают высокую доступность
Добавим второй application server:
┌── app01
users ────┤
└── app02
На первый взгляд SPOF устранён. Но задаём следующий вопрос: как пользователь попадёт на второй сервер при отказе первого? Если оба адреса скрыты за одним reverse proxy:
┌── app01
users → proxy ─┤
└── app02
то теперь SPOF может быть здесь:
proxy
Мы зарезервировали application layer, но не весь путь предоставления сервиса. Именно поэтому SPOF ищут не по количеству серверов Полезнее смотреть на полный пользовательский сценарий:
user ↓ DNS ↓ network ↓ load balancer / proxy ↓ application ↓ database ↓ storage ↓ external dependencies
На каждом уровне задаём один и тот же вопрос: Что произойдёт, если этот компонент полностью исчезнет прямо сейчас? Если ответ: сервис остановится, следующий вопрос: какой подтверждённый механизм продолжит работу вместо него?
1. Вычислительные узлы
Допустим:
app01 app02
Хорошо. Но где они работают? Если:
app01 ─┐
├── hypervisor01
app02 ─┘
то отказ одного hypervisor выключит оба экземпляра. Логическое резервирование есть. Физической независимости — нет. Лучше:
hypervisor01 → app01 hypervisor02 → app02
Но и этого пока недостаточно.
2. Общий кластер тоже может иметь общий домен отказа
Failure domain — область инфраструктуры, компоненты которой могут отказать одновременно из-за одной причины.
Например:
node01 ─┐ node02 ─┼── одна стойка node03 ─┘
Формально узлов три. Но если стойка теряет питание:
node01 FAIL node02 FAIL node03 FAIL
Для анализа отказоустойчивости это один общий домен отказа. То же относится к:
- — одному PDU;
- — одному UPS;
- — одному коммутатору;
- — одной СХД;
- — одному каналу связи;
- — одной серверной комнате;
- — одной availability zone.
3. Storage — классический скрытый SPOF
Очень распространённая архитектура:
hypervisor01 ─┐
├── SAN
hypervisor02 ─┘
Виртуальные машины можно мигрировать между гипервизорами. HA-кластер работает. Но все VM-диски находятся на одной системе хранения. Если эта СХД становится недоступной:
оба hypervisor → работают VM → не работают
Получаем:
compute redundant
≠
service redundant
При этом наличие двух контроллеров внутри СХД ещё не автоматически решает вопрос. Нужно понимать: — контроллеры действительно независимы? — сколько путей до storage? — два ли fabric? — два ли switch? — два ли HBA? — работает ли multipath? — проверялся ли отказ одного пути?
4. Сеть
Представим:
app01 ─┐
├── switch01
app02 ─┘
Два application-сервера зависят от одного коммутатора. SPOF просто переместился. Добавляем второй:
app01 ─── switch01 └───── switch02 app02 ─── switch01 └───── switch02
Уже лучше. Но теперь проверяем дальше:
switch01 ─┐
├── router01
switch02 ─┘
И снова можем найти единственную точку отказа. А затем:
router01 ↓ один ISP
Поиск продолжается до тех пор, пока мы не охватим весь путь сервиса.