Pull to refresh

DevOps в локальных облаках: как строить высоконагруженные системы с CI/CD, Kubernetes и Grafana

Reading time7 min
Views3.1K

Введение: DevOps в условиях локальных ограничений

Когда мы начали разворачивать высоконагруженную fintech-платформу в локальном облаке, задача казалась выполнимой: привычные инструменты, знакомые процессы, только с местной спецификой. Однако реальность оказалась сложнее. Ограниченные дата-центры, нестабильные сети, строгие требования по хранению данных внутри страны и команда, скептически настроенная к новым практикам вроде GitLab CI, превратили проект в настоящий вызов. За два года мы построили систему, способную обрабатывать 10 000 транзакций в секунду (TPS), деплоиться за 12 минут и выдерживать пиковые нагрузки, такие как «черная пятница». В этой статье я расскажу, как мы оптимизировали DevOps-процессы в локальном облаке, какие трудности преодолели и какие решения помогли добиться успеха. Если вы работаете в регионе, где глобальные облака недоступны, наш опыт будет полезен.

1. Локальный контекст: особенности облачной инфраструктуры

1.1. Почему локальные облака?

Законодательство ряда стран, включая нашу, требует хранить персональные данные граждан в местных дата-центрах, часто в определенных городах. Это вынудило нас использовать локальную инфраструктуру. Помимо соответствия требованиям, локальные облака оказались экономичнее: по нашим расчетам, они на 30–40% дешевле глобальных аналогов для сопоставимых ресурсов.

Ресурс

Локальное облако ($/мес)

Глобальное облако ($/мес)

10 нод (16 vCPU, 64 ГБ RAM)

5000

8000

Однако экономия сопряжена с ограничениями. Локальные облака не предоставляют готовых решений, таких как managed Kubernetes или базы данных. Все — от настройки кластеров до тюнинга PostgreSQL - пришлось делать вручную. Сетевые задержки в регионах, порой достигающие 100 мс, добавляли сложностей.

1.2. Что такое высокая нагрузка?

Высоконагруженные системы в нашем регионе - это не только крупные банки или государственные порталы. Это стремительно растущие маркетплейсы, системы онлайн-банкинга, логистические платформы и даже игровые стартапы. Наш проект - платформа для микрокредитования с миллионом пользователей - должен был выдерживать 10 000 TPS в пике, деплоить обновления еженедельно и восстанавливаться после сбоев за 5 минут. И все это на инфраструктуре, где сетевые задержки иногда напоминали эпоху dial-up.

2. Технические вызовы и решения

2.1. CI/CD: от ручного копирования к автоматизации

На старте наш процесс CI/CD был примитивным: разработчики пушат код в GitLab, администраторы копируют build.tar.gz на сервер через scp, а затем все надеются, что ничего не сломается. Некоторые в команде считали GitLab CI избыточным, утверждая, что «раньше и scp хватало». Мы решили это изменить.

Мы внедрили пайплайн в GitLab CI для автоматизации сборки Docker-образов, тестирования и деплоя в Kubernetes. Вот упрощенный .gitlab-ci.yml:

stages:
  - build
  - test
  - scan
  - deploy

variables:
  REGISTRY: "registry.localcloud/myapp"
  TAG: "$CI_COMMIT_SHA"

build:
  stage: build
  script:
    - echo "Собираем Docker-образ..."
    - docker build --cache-from $REGISTRY:latest -t $REGISTRY:$TAG .
    - docker push $REGISTRY:$TAG
  only:
    - main

test:
  stage: test
  parallel:
    matrix:
      - TEST_TYPE: [unit, integration]
  script:
    - echo "Запускаем $TEST_TYPE тесты..."
    - docker run $REGISTRY:$TAG pytest --cov=app tests/$TEST_TYPE
  only:
    - main

scan:
  stage: scan
  script:
    - echo "Проверяем образ на уязвимости..."
    - docker run aquasec/trivy image $REGISTRY:$TAG
  only:
    - main

deploy:
  stage: deploy
  script:
    - echo "Деплоим в Kubernetes..."
    - sed -i "s|TAG|$TAG|g" k8s/deployment.yaml
    - kubectl apply -f k8s/deployment.yaml
  environment:
    name: production
  only:
    - main

Проблемы:

  • Локальный реестр «зависал» при пушах образов объемом более 1 ГБ из-за сетевых ограничений.

  • Тесты занимали 40 минут из-за последовательного выполнения.

Решения:

  • Настроили локальный кэш Docker-образов, сократив время сборки на 60%.

  • Разделили тесты на юнит- и интеграционные, запустив их параллельно с помощью parallel: matrix, что уменьшило время на 20%.

  • Оптимизировали сеть между runners и реестром, выделив VLAN.

Результат: время деплоя сократилось с 2 часов до 12 минут. Пайплайн стал стабильно проходить даже в пиковые релизы.

CI/CD пайплайн
CI/CD пайплайн

2.2. Kubernetes: собираем кластер с нуля

Без managed Kubernetes мы подняли кластер через kubeadm. Основные шаги:

  1. Установили kubeadm, kubelet и kubectl на ноды (16 vCPU, 64 ГБ RAM).

  2. Настроили Calico для сетей:

    kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
    
  3. Оптимизировали параметры kubelet:

    --max-pods=150
    --kube-reserved=cpu=500m,memory=1Gi
    

Проблемы:

  • Ноды перегружались на 90% из-за ограниченных ресурсов.

  • Сеть добавляла 50 мс задержки между pod’ами.

Решения:

  • Настроили Horizontal Pod Autoscaler (HPA) с кастомными метриками:

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: myapp-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: myapp
      minReplicas: 3
      maxReplicas: 12
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 70
      - type: Pods
        pods:
          metric:
            name: http_requests
          target:
            type: AverageValue
            averageValue: 1000
    
  • Разработали скрипт для Cluster Autoscaler, запрашивающий новые ноды через API облака.

  • Увеличили MTU до 9000 для оптимизации сети.

Результат: кластер выдерживал 10 000 RPS, масштабирование занимало 2 минуты.

HPA автошкалирование
HPA автошкалирование

2.3. PostgreSQL: справляемся с транзакциями

Для базы данных мы выбрали PostgreSQL с репликацией, подняв Patroni для высокой доступности (HA). Основные оптимизации:

  • Партиционирование таблиц по user_id:

    CREATE TABLE transactions (
        id BIGSERIAL,
        user_id BIGINT,
        amount DECIMAL,
        created_at TIMESTAMP
    ) PARTITION BY RANGE (user_id);
    
    CREATE TABLE transactions_0 PARTITION OF transactions
        FOR VALUES FROM (0) TO (1000000);
    CREATE TABLE transactions_1 PARTITION OF transactions
        FOR VALUES FROM (1000000) TO (2000000);
    
  • Настройки postgresql.conf:

    work_mem = 16MB
    max_connections = 500
    shared_buffers = 8GB
    effective_cache_size = 24GB
    
  • Репликация через Patroni с двумя read-only репликами, балансировка через PgBouncer.

Проблемы:

  • Изначально max_connections=100 приводило к отказам в пике.

  • Отсутствие индексов по created_at замедляло аналитические запросы.

Решения:

  • Увеличили max_connections до 500 и внедрили PgBouncer.

  • Добавили индексы:

    CREATE INDEX transactions_created_at_idx ON transactions (created_at);
    

Результат: время обработки запросов (P99) сократилось с 200 мс до 30 мс.

PostgreSQL архитектура
PostgreSQL архитектура

2.4. Мониторинг: опережаем проблемы

Мы собрали стек из Prometheus, Grafana и Alertmanager. Пример конфигурации Prometheus:

scrape_configs:
  - job_name: 'myapp'
    static_configs:
      - targets: ['myapp.localcloud:8080']
    metrics_path: /metrics

Кастомные метрики:

  • Отслеживали HTTP-ошибки:

    rate(http_requests_total{status="500"}[5m]) > 0.1
    
  • Мониторили задержки API:

    histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
    

Проблемы:

  • Prometheus перегружался при 500+ pod’ах.

  • Сетевые задержки замедляли сбор метрик.

Решения:

  • Внедрили Thanos для долгосрочного хранения метрик:

    thanos:
      store:
        enabled: true
    
  • Увеличили интервал сбора до 30 секунд для некритичных сервисов.

  • Настроили алерты в Telegram:

    route:
      receiver: 'telegram'
    receivers:
      - name: 'telegram'
        telegram_configs:
          - bot_token: 'YOUR_BOT_TOKEN'
            chat_id: '-123456789'
    

Результат: MTTR сократился до 2 минут, доля 500-х ошибок упала с 1% до 0.01%.

Grafana - падение 500-х ошибок
Grafana - падение 500-х ошибок

3. Безопасность и оптимизация затрат

3.1. Безопасность

Управление секретами:

  • Изначально использовали kubectl create secret, что было небезопасно. Перешли на HashiCorp Vault:

    vault kv put secret/myapp db_password=supersecret
    
  • Интегрировали Vault с Kubernetes через sidecar-контейнеры.

Сканирование образов:

  • Внедрили Trivy в CI/CD для проверки уязвимостей (см. этап scan).

  • Обнаружили CVE в старой версии Nginx и обновили образ.

Проблемы:

  • Разработчики хранили токены в .env.

  • Trivy замедлял пайплайн на 5 минут.

Решения:

  • Провели обучение по безопасным практикам.

  • Настроили кэширование для Trivy.

3.2. Контроль затрат

Локальные облака дешевле на 30–40%, но наш кластер из 10 нод ($5000/мес) требовал максимальной загрузки. Отсутствие managed-решений увеличивало административные расходы - около 20 часов в месяц.

Решения:

  • Оптимизировали ресурсы с помощью kube-reserved и HPA.

  • Запланировали пилот ArgoCD для автоматизации деплоев.

4. Формирование DevOps-культуры: от скептицизма к вовлеченности

Когда мы предложили внедрить CI/CD и Kubernetes, команда встретила это в штыки. Разработчики утверждали, что у них нет времени на «эти новомодные штуки», а администраторы считали Kubernetes ненужным усложнением. Чтобы преодолеть сопротивление, мы решили показать ценность новых подходов на практике.

Мы организовали серию внутренних митапов, где продемонстрировали, как CI/CD сокращает ручную работу, а Kubernetes упрощает масштабирование. Например, мы показали, как автоматизация деплоев экономит часы, которые раньше тратились на scp. Затем мы внедрили DORA-метрики (Deploy Frequency, Lead Time for Changes), чтобы команда видела прогресс: частота деплоев выросла с одного в месяц до трех в неделю. Доступ к дашбордам Grafana помог разработчикам понять, как их код влияет на продакшен - от ошибок до задержек API.

Со временем команда начала писать тесты и активно использовать мониторинг. Это не только улучшило качество кода, но и укрепило доверие между разработчиками и администраторами. Теперь DevOps для нас - это не просто инструменты, а общий подход к созданию надежных систем.

5. Кейс: как мы спасли fintech-платформу

Наша платформа для микрокредитования с миллионом пользователей должна была обрабатывать 10 000 TPS, деплоиться раз в неделю и восстанавливаться после сбоев за 5 минут. На старте проект страдал от долгих деплоев (2 часа), нестабильной базы данных и отсутствия мониторинга.

Архитектура:

  • Микросервисы на Go, развернутые в Kubernetes.

  • PostgreSQL с Patroni и PgBouncer для высокой доступности и балансировки.

  • CI/CD через GitLab CI с автоматизацией сборки, тестирования и деплоя.

  • Мониторинг с Prometheus, Grafana и Alertmanager.

Что мы сделали:

  • Партиционировали таблицы PostgreSQL по user_id, чтобы ускорить обработку транзакций.

  • Внедрили Redis для кэширования 80% запросов, снизив нагрузку на базу.

  • Настроили HPA для автоматического масштабирования подов и алерты по кастомным метрикам (например, HTTP-запросы и задержки).

  • Оптимизировали CI/CD-пайплайн, добавив параллельное тестирование и кэширование.

Результаты:

  • Время деплоя сократилось с 2 часов до 12 минут.

  • Задержка запросов (P99) уменьшилась до 30 мс.

  • MTTR (Mean Time to Recovery) достиг 2 минут.

Этот кейс показал, что даже в условиях локального облака можно построить систему, не уступающую по надежности решениям на глобальных платформах.

6. Перспективы развития

Мы продолжаем развивать DevOps-процессы:

  • ИИ в мониторинге: тестируем ELK с машинным обучением для анализа логов и предсказания сбоев.

  • Edge Computing: изучаем возможности локальных облаков для IoT-приложений в регионах.

  • Open Source инструменты: планируем внедрить ArgoCD для управления деплоями и Tekton для CI/CD.

Заключение: DevOps в локальных облаках — это реально

Работа в локальном облаке - как ремонт машины на полном ходу: сложно, но возможно. Сетевые ограничения, законодательные требования и отсутствие готовых решений создают вызовы, но с правильными инструментами - Kubernetes, Prometheus, Vault - и сплоченной командой можно построить надежную и масштабируемую систему.

Примечание: Названия облачных платформ скрыты по условиям NDA. Все технические конфигурации представлены исключительно в образовательных целях.

Tags:
Hubs:
+6
Comments0

Articles