← все статьи
15 июня 2026· 9 мин чтения· #reliability · #ha

Как мы строили HA-инфраструктуру для банка

Отказоустойчивость — это не одна галочка в чек-листе, а набор решений на каждом слое. Делюсь тем, что реально держит нагрузку в проде.

Банковская инфраструктура не прощает простоев. Когда сервис обрабатывает платежи, каждая минута недоступности — это не только деньги, но и доверие. За время работы с production-инфраструктурой О!Банка я понял главное: высокая доступность строится снизу вверх, и слабое звено на любом уровне обнуляет всю остальную работу.

Принцип: ни одной единой точки отказа

Первое, что мы сделали — нарисовали карту зависимостей и нашли каждый single point of failure (SPOF). Один балансировщик? SPOF. Одна нода с базой? SPOF. Один аплинк? Тоже. Цель — чтобы выход из строя любого отдельного компонента не приводил к недоступности сервиса.

Правило, которое мы повесили на стену: «Если ты не можешь выдернуть этот сервер из розетки в рабочий день — у тебя нет HA, у тебя есть надежда».

Слой балансировки: Keepalived + HAProxy

На входе мы поставили пару балансировщиков в режиме active-passive с плавающим IP через Keepalived (VRRP). Трафик распределяет HAProxy с активными health-check'ами: нода, не прошедшая проверку, мгновенно выводится из ротации.

frontend fe_api
    bind 10.0.0.10:443 ssl crt /etc/haproxy/certs/api.pem
    default_backend be_api

backend be_api
    balance roundrobin
    option httpchk GET /actuator/health
    http-check expect status 200
    server app-01 10.0.1.11:8443 check ssl verify none inter 2s fall 3 rise 2
    server app-02 10.0.1.12:8443 check ssl verify none inter 2s fall 3 rise 2
    server app-03 10.0.1.13:8443 check ssl verify none inter 2s fall 3 rise 2

Здоровье приложения отдаёт Spring Boot Actuator (/actuator/health), причём health-эндпоинт учитывает доступность зависимостей — БД, очередей. Это важно: сервис, который «жив», но не видит базу, не должен принимать трафик.

Приложения: stateless и горизонтальное масштабирование

Сервисы мы держим stateless — состояние выносится в БД, кэш и очереди. Это даёт два свойства бесплатно: можно масштабироваться горизонтально и можно убивать любой под без последствий. В Kubernetes это выражается простыми, но строгими правилами:

spec:
  replicas: 3
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels: { app: payments-api }
              topologyKey: kubernetes.io/hostname

Данные — самое сложное

Stateless-сервисы масштабировать легко. А вот база — это всегда компромисс между консистентностью и доступностью. Для PostgreSQL мы используем потоковую репликацию с автоматическим failover (Patroni), синхронной репликой для критичных данных и регулярными проверками восстановления из бэкапа.

Отдельно подчеркну: бэкап, который ни разу не восстанавливали, — это не бэкап. Мы регулярно поднимаем копию из бэкапа в отдельном окружении и сверяем целостность. Это сэкономило нам нервы не один раз.

Честный SLA: считаем, а не обещаем

«Четыре девятки» звучит красиво, но 99.99% — это всего ~52 минуты простоя в год. Чтобы реально в это попасть, нужно резервирование на каждом уровне и быстрый MTTR. Мы научились считать доступность не по ощущениям, а по метрикам из Prometheus, и привязали алерты к error budget, а не к отдельным пикам.

Disaster Recovery: план, который проверяют

HA защищает от отказа компонента. DR — от потери целого дата-центра. Мы определили RPO/RTO для каждого критичного сервиса и, главное, периодически проводим учения: руками выводим из строя зону и смотрим, что отвалится. Каждое такое учение находит то, что не учли в схеме.

Итог

Высокая доступность — это не продукт и не одна технология. Это дисциплина: убирать SPOF, проверять предположения, тренировать восстановление. Самые надёжные системы, которые я видел, были не самыми сложными — а самыми проверенными.

HAHAProxyKeepalived KubernetesPostgreSQLSLA