5 лет масштабирования: от 5 до 500 серверов для ТехноМаркет

С чего всё начиналось

Компания ТехноМаркет — федеральный ритейлер стройматериалов и инструментов — обратилась к нам в 2021 году с задачей, которая на первый взгляд казалась рутинной: «помогите нам не падать в Чёрную пятницу». За кулисами стояла инфраструктура, знакомая любому, кто работал с быстрорастущими проектами:

  • 5 серверов — 2 веб-сервера, 1 БД, 1 поиск, 1 NFS-хранилище
  • MySQL 5.5 с базой ~50 ГБ, единственный инстанс без реплик
  • Nginx + PHP-FPM 7.0 — монолитное приложение
  • Memcache для кэширования, Sphinx для поиска
  • NFS для shared-хранилища изображений и документов
  • Команда из 15 разработчиков, ноль DevOps-инженеров

Деплой выглядел так: разработчик собирал код на своей машине, заходил на сервер по SSH и обновлял файлы вручную. Никакого configuration management, никаких тестов, никакого плана аварийного восстановления. При этом бизнес рос на 40-50% в год.

Мы заключили контракт на постоянное сопровождение и за 5 лет прошли путь, который обычно занимает 7-8 лет. Ниже — хронология трансформации.

Год 1: второй ДЦ и план на случай катастрофы

Первый год мы посвятили задаче, которая не приносила прямой бизнес-ценности, но без которой всё остальное не имело смысла — отказоустойчивости.

Проблема

У ТехноМаркет не было ни резервного ДЦ, ни плана действий при отказе основного. Когда в марте 2021 года в московском ДЦ произошёл пожар на подстанции, сайт был недоступен 14 часов. Потери составили ~8 млн рублей в упущенных заказах.

Решение: cold standby в другом регионе

Мы развернули полную копию инфраструктуры во втором ДЦ (Санкт-Петербург) с VPN-каналом между площадками:

  • MySQL master-slave репликация между ДЦ
  • lsync для синхронизации NFS-хранилища
  • Двойной интернет-канал в каждом ДЦ
# Конфигурация MySQL репликации
# На master (Москва):
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_do_db = technomarket
expire_logs_days = 7

# На slave (СПб):
[mysqld]
server-id = 2
relay_log = /var/log/mysql/relay-bin
read_only = 1
super_read_only = 1

Параметр super_read_only стал нашим спасением — он блокирует любые записи, даже от пользователей с привилегиями SUPER, предотвращая случайные split-brain сценарии при ручном переключении.

Процедура failover была полностью задокументирована и протестирована ежемесячно. Время переключения — 15 минут с деградацией в read-only режим.

Год 2: CI/CD и автоматизация деплоя

Ко второму году количество разработчиков выросло до 40, и ручной деплой стал серьёзным тормозом. Мы выстроили полноценный CI/CD-пайплайн поэтапно:

КварталВнедрениеРезультат
Q1 2022GitLab CI + werf (dapp) для сборкиВремя сборки: 47 мин → 12 мин
Q2 2022Тестовые среды с копией prod-БДБаги на проде: -60%
Q3 2022PHPStan + CodeSniffer в CIКод-ревью ускорилось на 40%
Q4 2022Selenium-тесты + Blackfire профилированиеРегрессии: -75%
# Пример werf.yaml для основного приложения
project: technomarket
configVersion: 1
---
image: app
from: php:8.1-fpm
git:
  - add: /
    to: /var/www/app
    stageDependencies:
      install:
        - composer.lock
      beforeSetup:
        - "**/*.php"
shell:
  install:
    - composer install --no-dev --optimize-autoloader
  beforeSetup:
    - php artisan config:cache
    - php artisan route:cache

Ключевым достижением стало то, что обновление PHP с 7.0 до 7.4, а затем до 8.1 прошло без участия нашей команды — разработчики ТехноМаркет справились самостоятельно благодаря изолированным тестовым средам и возможности мгновенного отката.

Год 3: миграция в Kubernetes

К 2023 году монолитное приложение начало разделяться на микросервисы, и VM-based инфраструктура перестала справляться. Мы приняли решение мигрировать в Kubernetes на базе платформы Deckhouse.

Подготовка приложений по 12-factor methodology

Перед миграцией каждый сервис прошёл чек-лист «12 факторов»:

  • Конфигурация через переменные окружения (не файлы)
  • Stateless-процессы (сессии в Redis, файлы в S3)
  • Логирование в stdout/stderr
  • Graceful shutdown по SIGTERM

Постепенное переключение трафика

Мы не мигрировали всё разом. Каждый сервис переносился поэтапно с переключением через Ingress:

# Ingress для постепенного переключения трафика
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: technomarket-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
  rules:
    - host: technomarket.ru
      http:
        paths:
          - path: /api/catalog
            pathType: Prefix
            backend:
              service:
                name: catalog-svc-k8s
                port:
                  number: 8080

Начинали с 5% трафика, отслеживали метрики в Grafana (ошибки, латентность, CPU/RAM) и за 1-2 недели доводили до 100%. На каждом этапе сохранялась возможность мгновенного отката на VM-версию.

Kubernetes-фишки, которые спасали

Три функции Kubernetes, которые оказались критически важными:

  • PodDisruptionBudget — гарантия минимального количества реплик при обновлениях узлов
  • Liveness/Readiness probes — автоматическое удаление неработающих подов из балансировки
  • HPA с кастомными метриками — автомасштабирование по глубине очередей RabbitMQ
# HPA по метрикам из Prometheus (глубина очереди)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-processor-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-processor
  minReplicas: 3
  maxReplicas: 50
  metrics:
    - type: External
      external:
        metric:
          name: rabbitmq_queue_messages
          selector:
            matchLabels:
              queue: orders
        target:
          type: AverageValue
          averageValue: "100"

Год 4: Active Multi-DC и синхронная репликация

С ростом до 600+ магазинов и миллиона пользователей в день, cold standby перестал удовлетворять требованиям бизнеса: 15 минут даунтайма при переключении — это ~500 тыс. рублей потерь. Мы спроектировали и внедрили active multi-DC архитектуру.

Три активных ДЦ одновременно

Вместо master-slave мы перешли на Percona XtraDB Cluster с синхронной репликацией между тремя площадками:

# Конфигурация Percona XtraDB Cluster (my.cnf)
[mysqld]
wsrep_cluster_name = technomarket-prod
wsrep_cluster_address = gcomm://10.1.1.10,10.2.1.10,10.3.1.10
wsrep_node_address = 10.1.1.10
wsrep_provider = /usr/lib/galera4/libgalera_smm.so
wsrep_sst_method = xtrabackup-v2
wsrep_sync_wait = 1

# ProxySQL для балансировки запросов
# Чтение — ближайший узел, запись — только master
INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight)
VALUES 
  (10, '10.1.1.10', 3306, 1000),  -- writer
  (20, '10.1.1.10', 3306, 500),   -- reader DC1
  (20, '10.2.1.10', 3306, 500),   -- reader DC2
  (20, '10.3.1.10', 3306, 500);   -- reader DC3

Выделенная оптика между ДЦ

Синхронная репликация критически зависит от латентности между узлами. Мы заказали выделенные оптоволоконные каналы между ДЦ с RTT менее 2 мс. Это дало:

  • Синхронная репликация без заметной деградации производительности
  • Возможность покомпонентного failover (отказ одного сервиса — не весь ДЦ)
  • Split DNS для маршрутизации клиентов к ближайшему ДЦ

Год 5: мониторинг, canary и автоматический failover

Последний год проекта мы посвятили автоматизации операционных процессов, чтобы команда ТехноМаркет могла управлять 500-серверной инфраструктурой без нашего постоянного участия.

Стек мониторинга

Мы построили трёхуровневый мониторинг:

  • Инфраструктурный слой: Prometheus + node_exporter + Grafana. USE-метрики (Utilization, Saturation, Errors) на каждый сервер и каждый контейнер
  • Прикладной слой: RED-метрики (Rate, Errors, Duration) по каждому vhost, location и контроллеру. Алерты в Alertmanager с маршрутизацией в Telegram дежурной команде
  • Бизнес-слой: Количество заказов в минуту, средний чек, конверсия. Аномалии детектируются автоматически
# Пример правила алертинга: деградация конверсии
groups:
  - name: business-alerts
    rules:
      - alert: ConversionDropped
        expr: |
          rate(orders_completed_total[10m]) 
          / rate(sessions_started_total[10m]) 
          < 0.02
        for: 15m
        labels:
          severity: critical
        annotations:
          summary: "Конверсия ниже 2% более 15 минут"
          description: "Текущая конверсия: {{ $value | humanizePercentage }}"

Canary-деплои через панель управления

Мы разработали админ-панель, позволяющую управлять процентом трафика на новую версию любого сервиса. Это позволило разработчикам ТехноМаркет самостоятельно выкатывать изменения с минимальным риском:

  1. Новая версия деплоится как отдельный Deployment
  2. Через панель направляется 5% трафика
  3. A/B сравнение метрик в реальном времени
  4. При отсутствии деградации — поэтапное увеличение до 100%
  5. Автоматический rollback при росте ошибок выше порога

API-driven failover

Переключение трафика между ДЦ было полностью автоматизировано через API CDN-провайдера. При обнаружении недоступности основного ДЦ система:

  1. Переводит затронутый ДЦ в read-only режим
  2. Переключает upstream в CDN на резервный ДЦ
  3. Отправляет алерт дежурной команде
  4. Автоматически возвращает трафик после восстановления

Время полного переключения сократилось с 15 минут до 45 секунд.

Итоговая трансформация в цифрах

За 5 лет сотрудничества инфраструктура ТехноМаркет прошла путь, который можно описать следующей таблицей:

Параметр20212026
Серверы5500+
Размер БД50 ГБ500+ ГБ
Трафик~50 RPS~1000 RPS
Пользователей/день~50 0001 000 000+
Разработчиков15170
IT-персонал всего15300
Магазинов~100600+
Время деплоя2-4 часа12 минут
Даунтайм при деплое30-60 мин0
Время failoverНет плана45 секунд
Баги на продеBaseline-80%

Проект ТехноМаркет стал для нас эталонным кейсом долгосрочного сопровождения. Подробнее о нашем подходе к масштабированию инфраструктуры — на itfresh.ru.

Ключевые уроки за 5 лет

Каждый год мы выносили из этого проекта важные уроки, которые влияли на нашу работу с другими клиентами:

  • Год 1: Резервирование — не роскошь. Один пожар на подстанции может стоить бизнесу миллионы
  • Год 2: CI/CD окупается за 3 месяца. Подсчитали: экономия 120 человеко-часов в месяц на деплоях и откатах
  • Год 3: Миграция в Kubernetes — это прежде всего подготовка приложений. 70% времени ушло на refactoring, 30% — на инфраструктуру
  • Год 4: Синхронная репликация работает только с быстрым каналом. Мы попробовали через интернет — split-brain через неделю
  • Год 5: Автоматизация failover критичнее, чем автоматизация деплоя. Инцидент в 3 часа ночи не будет ждать, пока инженер проснётся

Наша рекомендация компаниям, планирующим аналогичную трансформацию: начинайте с мониторинга и CI/CD, затем переходите к отказоустойчивости, и только потом — к миграции на контейнеры. Обратная последовательность многократно увеличивает риски.

Часто задаваемые вопросы

Стандартная async-репликация не гарантирует сохранность данных при отказе master-узла — последние транзакции могут быть потеряны. Для ритейлера с миллионом пользователей и финансовыми операциями это неприемлемо. Percona XtraDB Cluster обеспечивает синхронную репликацию: транзакция считается завершённой только после подтверждения от всех узлов. Это потребовало выделенной оптики между ДЦ (RTT < 2 мс), но дало настоящую консистентность данных.
NFS стал узким местом уже на 50 серверах — блокировки при одновременном доступе, проблемы с производительностью при большом количестве мелких файлов. Мы мигрировали на S3-совместимое объектное хранилище (MinIO) объёмом более 3 ТБ. Для приложений интеграция прозрачна — используются те же URL, но через CDN-слой. Latency чтения снизилась с 15-50 мс до 2-5 мс.
Прямое сравнение некорректно, так как 500 серверов обслуживают в 20 раз больше трафика. Стоимость инфраструктуры на единицу трафика снизилась примерно на 35% благодаря контейнеризации (лучшая утилизация ресурсов), автомасштабированию (сброс неиспользуемых ресурсов ночью) и отказу от дорогих вертикально масштабируемых серверов.
Canary-версия сначала деплоится в одном ДЦ и получает 5% трафика этого ДЦ. Если метрики в норме, процент увеличивается до 50%, затем деплой реплицируется во второй ДЦ. Полный rollout на все три ДЦ занимает около 2 часов, но может быть ускорен до 15 минут для критических исправлений.
Самым сложным оказалась не технология, а организационная трансформация. Научить команду из 170 разработчиков работать с Kubernetes, писать stateless-сервисы и доверять автоматическому failover — это непрерывный процесс обучения. Мы провели более 30 внутренних воркшопов и создали 200 страниц внутренней документации.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#масштабирование инфраструктуры#kubernetes миграция#multi-dc архитектура#percona xtradb cluster#proxysql#canary deployment#CI/CD pipeline#мониторинг prometheus
Комментарии 0

Оставить комментарий

загрузка...