РАЗБОР #05: Как искать Single Point of Failure

Мы разбираем инфраструктуру по фактам: Linux, Zabbix, мониторинг, диагностика и архитектура. От симптома — к проверяемому выводу: что именно доказывает метрика, какие гипотезы остаются и как подтвердить решение. Без догадок там, где можно проверить. Если нужно понимать не только что сделать, но и почему — вам сюда.

single point of failurespofинфраструктура

Два сервера. Два блока питания. Два коммутатора. Кластер из трёх узлов. На схеме всё выглядит отказоустойчиво. Но затем выходит из строя одна СХД — и останавливается весь сервис. Или оба 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

Поиск продолжается до тех пор, пока мы не охватим весь путь сервиса.

Читайте так же