Монолитные приложения, написанные на Laravel или Django, часто становятся узким местом при росте нагрузки, команды и требований к масштабируемости. Перенос части бизнес‑логики в отдельные микросервисы позволяет решить эти проблемы, но требует грамотного подхода к контейнеризации и оркестрации.
Зачем мигрировать?
- Масштабируемость: каждый сервис можно масштабировать независимо от остальных.
- Изоляция отказов: сбой одного микросервиса не приводит к падению всей системы.
- Технологическая гибкость: разные сервисы могут быть реализованы на разных языках и фреймворках.
- Ускорение разработки: небольшие команды работают над отдельными доменами.
Подготовка монолита к контейнеризации
Первый шаг – упаковать существующее приложение в Docker‑образ. Ниже представлены минимальные Dockerfile‑ы для Laravel и Django.
# Dockerfile для Laravel (PHP 8.2)
FROM php:8.2-fpm-alpine
# Установка системных зависимостей
RUN apk add --no-cache \
git \
curl \
libpng-dev \
libjpeg-turbo-dev \
freetype-dev \
zip \
unzip \
icu-dev \
oniguruma-dev
# Расширения PHP
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \
docker-php-ext-install pdo_mysql gd intl opcache bcmath
# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Рабочая директория
WORKDIR /var/www/html
# Копируем файлы проекта
COPY . .
# Устанавливаем зависимости
RUN composer install --no-dev --optimize-autoloader
# Права
RUN chown -R www-data:www-data /var/www/html
EXPOSE 9000
CMD ["php-fpm"]
# Dockerfile для Django (Python 3.11)
FROM python:3.11-slim
# Установка системных зависимостей
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
libssl-dev \
curl && \
rm -rf /var/lib/apt/lists/
# Рабочая директория
WORKDIR /app
# Копируем файлы проекта
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Сборка статических файлов (если используется)
# RUN python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
Стратегии декомпозиции монолита
Выбор границ сервисов – ключевой момент. Наиболее популярные подходы:
- Domain‑Driven Design (DDD): разбиваем систему по бизнес‑доменам (например, Payments, Catalog, User Management).
- Функциональная декомпозиция: каждый микросервис отвечает за одну задачу (CRUD‑операции, отчётность, интеграцию с внешними API).
- Технологическая декомпозиция: отдельные сервисы для тяжёлых задач (обработка изображений, аналитика) могут быть реализованы на Python, даже если основной стек – PHP.
Для взаимодействия микросервисов рекомендуется использовать API‑gateway (например, Traefik или NGINX Ingress Controller) и протоколы HTTP/REST или gRPC.
Оркестрация с Kubernetes
После создания Docker‑образов их необходимо разместить в Kubernetes‑кластер. Ниже – примеры манифестов Deployment и Service для Laravel и Django.
# kubernetes/deployment-laravel.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: laravel-app
labels:
app: laravel
spec:
replicas: 3
selector:
matchLabels:
app: laravel
template:
metadata:
labels:
app: laravel
spec:
containers:
- name: php-fpm
image: registry.example.com/laravel:latest
ports:
- containerPort: 9000
env:
- name: APP_ENV
value: "production"
- name: DB_HOST
value: "postgres-service"
resources:
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: laravel-service
spec:
selector:
app: laravel
ports:
- protocol: TCP
port: 80
targetPort: 9000
type: ClusterIP
# kubernetes/deployment-django.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: django-app
labels:
app: django
spec:
replicas: 2
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: gunicorn
image: registry.example.com/django:latest
ports:
- containerPort: 8000
env:
- name: DJANGO_SETTINGS_MODULE
value: "myproject.settings.production"
- name: DATABASE_URL
value: "postgres://user:pass@postgres-service:5432/dbname"
resources:
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: django-service
spec:
selector:
app: django
ports:
- protocol: TCP
port: 80
targetPort: 8000
type: ClusterIP
Для внешнего доступа к сервисам удобно использовать Ingress‑контроллер. Пример простого Ingress‑правила:
# kubernetes/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: api.example.com
http:
paths:
- path: /laravel/(.)
pathType: Prefix
backend:
service:
name: laravel-service
port:
number: 80
- path: /django/(.*)
pathType: Prefix
backend:
service:
name: django-service
port:
number: 80
CI/CD и автоматизация
Для быстрой поставки образов в кластер рекомендуется построить pipeline в GitLab CI, GitHub Actions или Jenkins:
# .gitlab-ci.yml (пример для Laravel)
stages:
- build
- push
- deploy
build_laravel:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t registry.example.com/laravel:$CI_COMMIT_SHORT_SHA .
push_laravel:
stage: push
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push registry.example.com/laravel:$CI_COMMIT_SHORT_SHA
deploy_laravel:
stage: deploy
script:
- kubectl set image deployment/laravel-app php-fpm=registry.example.com/laravel:$CI_COMMIT_SHORT_SHA --record
only:
- master
Мониторинг, логирование и трассировка
Для микросервисной среды критично собрать метрики и логи в единую систему. Популярный стек:
- Prometheus + Grafana – сбор метрик из Exporter‑ов (php-fpm‑exporter, django‑exporter).
- EFK (Elasticsearch, Fluentd, Kibana) – централизованное логирование.
- Jaeger или Zipkin – распределённая трассировка запросов через API‑gateway.
Распространённые ошибки и как их избежать
- Слишком ранняя декомпозиция: разбивать монолит без чёткого понимания границ приводит к «сервисному спагетти».
- Отсутствие схемы данных: каждый микросервис должен иметь собственную базу или схему, иначе возникнут конфликты.
- Неправильная конфигурация ресурсов: слишком маленькие лимиты в k8s вызывают OOM‑kill.
- Отсутствие health‑checks: без readiness/liveness проб сервисы могут быть недоступны.
Заключение
Миграция от монолита к микросервисам с использованием Docker и Kubernetes позволяет повысить гибкость, масштабируемость и надёжность приложений на Laravel и Django. Ключ к успешному переходу – чёткое планирование границ сервисов, автоматизация сборки и развёртывания, а также продуманный мониторинг.
Если вы ищете партнёра, способного провести анализ, спроектировать микросервисную архитектуру и реализовать её в Kubernetes‑кластер, команда RybinskLab готова помочь. Мы предоставляем комплексные услуги по разработке, контейнеризации и поддержке решений на PHP и Python.