Настройка автоматического деплоя preview-окружений в Kubernetes

Разработчики тратят часы в ожидании деплоя, а тестировщики проверяют не ту версию — staging не справляется с параллельными PR. Мы настраиваем автоматический деплой preview-окружений в Kubernetes: каждый PR получает изолированное пространство, которое живёт только во время ревью. Наша команда реализует проект под ключ — от настройки пайплайнов до поддержки, обеспечивая стабильную работу и масштабирование вместе с вашим бизнесом.
Часто задаваемые вопросы

Представьте: разработчик открывает PR с правками формы оформления заказа. QA ждёт ссылку для проверки. Дизайнер хочет посмотреть на кнопку в контексте. Тимлид не может смержить без живого ревью. Пока preview-окружения нет — все ждут деплой в staging, который кто-то уже занял другой веткой. В типичной команде из 10 разработчиков каждый PR ждет деплоя в staging в среднем 2 часа. С preview environment деплой занимает 3 минуты. Мы — команда DevOps-инженеров с 7+ годами опыта в CI/CD и Kubernetes. За это время мы развернули preview environments для десятков проектов — от стартапов до enterprise. Поможем и вам автоматизировать тестирование PR. Оценим проект — просто напишите нам.

Preview environments решают этот затор: каждый PR получает изолированное окружение автоматически, живёт пока PR открыт, умирает после мержа или закрытия. Это сокращает время ревью на 40%, снижает затраты на облачную инфраструктуру на 30% благодаря автоудалению и исключает конфликты ресурсов. Ниже разберём, как построить систему на Kubernetes и GitHub Actions, и каких ошибок избежать.

Почему staging не подходит для параллельных PR?

Один staging на несколько активных PR — классика. Ветка feature/checkout-v2 затирает bugfix/payment-redirect, тестировщик проверяет не то, разработчик не понимает откуда баг. В итоге staging превращается в вечный конфликт ресурсов.

Вторая проблема — зависимости. Если приложение тянет базу данных, Redis, S3 — для каждого PR нужна изолированная копия этих сервисов или хотя бы отдельная схема/namespace. Без этого тесты из одного PR ломают данные другого.

Третья — время жизни. Отработанные PR копятся, окружения не чистятся, облачный счёт растёт. Нужна автоматическая утилизация по событию closed или merged.

Как развернуть preview environments на Kubernetes?

Типичная реализация на Kubernetes + GitHub Actions: при открытии PR триггерится workflow, который собирает образ, пушит в registry с тегом pr-{number}, применяет Helm-чарт в namespace preview-pr-{number} и комментирует PR со ссылкой на окружение.

Пример workflow
# .github/workflows/preview.yml (фрагмент)
on:
  pull_request:
    types: [opened, synchronize, reopened, closed]

jobs:
  deploy-preview:
    if: github.event.action != 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to preview namespace
        run: |
          helm upgrade --install \
            preview-pr-${{ github.event.number }} ./helm/app \
            --namespace preview-pr-${{ github.event.number }} \
            --create-namespace \
            --set image.tag=pr-${{ github.event.number }} \
            --set ingress.host=pr-${{ github.event.number }}.preview.example.com

  cleanup-preview:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Delete preview namespace
        run: kubectl delete namespace preview-pr-${{ github.event.number }} --ignore-not-found

Для баз данных есть несколько подходов. Самый дешёвый — отдельная схема PostgreSQL на каждый PR: CREATE SCHEMA pr_519 AUTHORIZATION app_user;, применяются миграции, после мержа схема дропается. Не нужны отдельные поды базы. Работает если приложение умеет в search_path.

Если нужна полная изоляция — ephemeral database через оператор (например, CloudNativePG с шаблонами кластеров) или Neon/PlanetScale с branch per PR.

DNS и Ingress

Wildcard-сертификат на *.preview.example.com плюс один wildcard Ingress-правило через nginx-ingress или Traefik:

---
# ingress wildcard rule
host: "*.preview.example.com"
http:
  paths:
    - path: /
      pathType: Prefix
      backend:
        service:
          name: preview-router # роутит по hostname на нужный сервис
---

Либо cert-manager с Let's Encrypt DNS-01 challenge выписывает wildcard автоматически.

Альтернативы Kubernetes

Если кластера нет — Render, Railway, Fly.io умеют preview environments нативно. Vercel и Netlify делают это из коробки для статики и Next.js. Для более тяжёлых приложений — Uffizzi или Namespace (бывший Shipyard): разворачивают окружения в эфемерных кластерах без обслуживания инфраструктуры с вашей стороны.

Docker Compose-based подход: каждый PR запускает docker compose up на выделенном runner-е с проброской порта через Cloudflare Tunnel или ngrok. Дёшево, но не масштабируется выше ~10 одновременных PR.

Как избежать конфликтов баз данных в preview?

Самый надёжный способ — использовать отдельные схемы в PostgreSQL для каждого PR. Приложение должно динамически выбирать схему через переменную окружения SEARCH_PATH. Это даёт изоляцию данных без запуска дополнительных контейнеров. Альтернатива — ephemeral база данных на основе CloudNativePG: каждый PR получает мини-кластер, который живёт ровно столько же, сколько namespace. Такой подход дороже, но обеспечивает полную изоляцию на уровне инстанса.

Что входит в настройку preview environments?

Мы предоставляем полный комплекс работ под ключ:

  • Аудит текущей инфраструктуры и CI/CD пайплайнов.
  • Проектирование архитектуры: выбор стратегии изоляции БД, DNS-схема, политика TTL.
  • Реализация Helm-чартов или Kustomize overlays для preview-окружений.
  • Настройка GitHub Actions / GitLab CI workflow с автоматическим деплоем и очисткой.
  • Интеграция wildcard Ingress и TLS через cert-manager.
  • Тестирование: одновременно открываем 5 PR, проверяем изоляцию данных и чистку.
  • Документация: runbook для дежурного, описание добавления новых зависимостей.
  • Обучение команды и поддержка после внедрения.

Сравнение стратегий изоляции базы данных:

Стратегия Изоляция Стоимость Сложность
Отдельная схема PostgreSQL Средняя Низкая Низкая
Ephemeral база (CloudNativePG) Высокая Средняя Средняя
Внешний сервис (Neon/PlanetScale) Высокая Высокая Низкая

Ориентиры по срокам

Сценарий Срок
Статический сайт / SPA (Vercel/Netlify) 0.5–1 день
Монолит без базы, Docker Compose 1–2 дня
Сервис с PostgreSQL, Kubernetes 3–5 дней
Микросервисы, несколько зависимостей 1–2 недели

Стоимость рассчитывается после аудита: важно понять текущий CI/CD стек и инфраструктуру. Окупается за счёт ускорения разработки — время ревью сокращается с 2 дней до 4 часов.

Типичные ошибки и их предотвращение

Без автоматической очистки через месяц копятся десятки мёртвых namespace'ов, что увеличивает облачный счёт. Решение — настроить TTL или cleanup по событию закрытия PR. Shared база без изоляции приводит к конкуренции за миграции — помогает schema-per-preview. Использование продакшен-секретов в preview-окружении недопустимо: нужен отдельный secrets store. Без ресурсных лимитов один активный PR может занять всю ноду; для preview достаточно 100m CPU и 256Mi memory. Эти меры гарантируют стабильность и экономию.

Готовы внедрить preview environments? Получите консультацию по вашему CI/CD — мы проанализируем текущую инфраструктуру и подберём лучшую стратегию. Свяжитесь с нами для аудита и оценки проекта.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139