Суть: Legacy-проект на Drupal 10 развёрнут в банковском Kubernetes с соблюдением всех требований безопасности: rootless-контейнеры, многоэтапная сборка, ротация секретов, fail-fast сценарии. Деплой ускорился с 2–3 часов до 8–12 минут.
«Деплой с 2–3 часов ручной работы по SSH сокращён до 8–12 минут: docker build → push → kubectl apply — без простоя через rolling update.»
«Многоэтапная сборка (6 этапов) + L2-кеширование BuildKit сократили образ на 60%. Сборочные инструменты и артефакты CI не попали в production.»
Платформа корпоративной автоматизации (RPA) на Drupal 10, PHP 8.2, PostgreSQL. До контейнеризации разворачивалась вручную на выделенном сервере через SSH.
Как выглядел деплой:
SSH → git pull → rm -rf vendor/ → composer install → drush sql-drop → импорт SQL → drush cr → drush updb → drush migrate → drush cron
Ключевые проблемы:
| Требование | Что означало |
|---|---|
| Rootless-контейнеры | UID 1000+, порты >1024. nginx не мог слушать 80/443 |
| Многоэтапная сборка | Никаких сборочных инструментов в production-образе |
| Секреты — через внешний store | Пароли, ключи — не в env-файлах и образах |
| Read-only корневая ФС | Drupal storage требует запись в файлы — решено через S3 |
| 12-factor app | Вся конфигурация — только через переменные окружения |
| Fail-fast запуск | Если нет БД или секретов — контейнер не должен стартовать |
Сборка разделена на изолированные этапы: apt-подготовка (ключ nginx), composer install, компиляция PHP-расширений (imagick через PIE), npm build для React-дашборда, системный фундамент (nginx + supervisor), финальный образ.
Двухуровневое кэширование BuildKit: L1 — слои Docker, инвалидируются через CACHE_DATE; L2 — персистентные кэши для apt и composer. Образ сокращён на ~60% за счёт исключения сборочных инструментов.
Все сервисы перенесены на порт 8080. Nginx настроен на absolute_redirect off; port_in_redirect off; — иначе rootless-порт 8080 просачивался в URL при редиректах.
Для Drupal, который штатно хранит всё в settings.php, написана библиотека environment-loader — 13 PHP-провайдеров, которые собирают конфигурацию из env-переменных и /run/secrets/. Поддерживается 40+ переменных: от подключения к БД до настроек Keycloak и Prometheus. Fail-fast в каждом провайдере — если нет HASH_SALT или пароля БД, приложение не стартует.
Kubernetes probes на трёх уровнях: liveness (проверка ответа приложения), readiness (готовность принимать трафик), startup (ожидание инициализации). Docker HEALTHCHECK — дублирование на уровне контейнера. Entrypoint-скрипты с set -e — 9 последовательных этапов инициализации, каждый с fail-fast.
Приложение разделено на два сервиса: шлюз (nginx) и бэкенд (PHP-FPM). Файлы хранятся в S3 (MinIO), конфигурация синка — внутри образа. Zero-downtime через rolling update с maintenance mode на время миграций БД.
| Метрика | Было (SSH) | Стало (k8s) | Ускорение |
|---|---|---|---|
| Время деплоя | 2–3 ч ручного SSH | 8–12 мин CI/CD | ~15–20x |
| Восстановление (MTTR) | 4–8 ч (поднятие сервера) | 2–5 мин (kubectl) | ~100x |
| Новое окружение | 1–2 дня | 15 мин (Helm) | ~50x |
| Шагов деплоя | 10+ ручных | 1 команда | ~10x |
Kubernetes Docker multi-stage build rootless
Drupal 10 PHP 8.2 nginx PostgreSQL 14
BuildKit L2 cache Docker Secrets Helm
Azure DevOps 12-factor app
S3 MinIO Keycloak Prometheus
Похожая задача? Свяжитесь с нами →