Для современных микросервисных архитектур критически важна возможность выкатывать новые версии без простоя. Zero‑downtime деплой подразумевает, что пользователь всегда обслуживается актуальной (или предыдущей) версией, пока новые контейнеры проходят проверку и становятся частью кластера. В статье рассматриваются два популярных оркестратора – Docker‑Swarm и Kubernetes – и сравниваются подходы к миграциям и откатам баз данных в проектах на Laravel 11 и FastAPI 0.110.
Zero‑downtime деплой в Docker‑Swarm
Docker‑Swarm сохраняет совместимость с Docker‑CLI, поэтому переход от одиночного контейнера к кластеру происходит без изменения Docker‑file. Ключевой механизм – rolling update сервисов.
- Стратегия обновления: задаём
--update-parallelism(кол‑во одновременно обновляемых задач) и--update-delay(задержка между обновлениями). Это позволяет постепенно заменять старые реплики новыми, проверяя их готовность. - Health‑check: контейнеры должны отвечать на
HEALTHCHECKв Docker‑file. Сервис считается готовым только после успешного прохода проверки, что исключает попадание в кластер неисправных экземпляров. - Трафик‑шардинг: при использовании
mode=globalилиmode=replicatedможно задать отдельныйpublishпорт, а роутер (Traefik, Nginx) будет балансировать запросы между готовыми репликами.
Пример создания сервиса с rolling update:
docker service create \
--name api \
--replicas 4 \
--update-parallelism 1 \
--update-delay 10s \
--publish published=80,target=8000 \
myregistry.com/project/api:1.2.3Zero‑downtime деплой в Kubernetes
Kubernetes предоставляет более гибкие механизмы: Deployment с strategy: RollingUpdate, ReadinessProbe и HorizontalPodAutoscaler. По умолчанию контроллер следит за тем, чтобы в любой момент количество готовых подов соответствовало spec.replicas.
- RollingUpdate параметры:
maxSurge(сколько дополнительных подов может быть запущено) иmaxUnavailable(сколько подов может быть недоступно). При значенияхmaxSurge: 25%,maxUnavailable: 0достигается полное покрытие без простоя. - ReadinessProbe: проверка готовности (HTTP, TCP, Exec). Под считается готовым только после успешного прохождения, что гарантирует, что сервис будет принимать трафик только от здоровых экземпляров.
- Canary и Blue‑Green: с помощью
Ingressи аннотаций (например, в Traefik) можно направлять часть трафика на новую версию, проверяя её в проде без полного переключения.
Пример Deployment с RollingUpdate:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myregistry.com/project/api:1.2.3
ports:
- containerPort: 8000
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10Миграции и откаты БД для Laravel 11
Laravel 11 использует встроенный механизм миграций php artisan migrate. Для zero‑downtime необходимо обеспечить обратную совместимость схемы и данных.
- Feature‑toggle в коде: новые колонки объявляются nullable, а новые бизнес‑логики – за флагом, который включается после полного развертывания.
- Пошаговые миграции: сначала добавляем колонку, потом в отдельном коммите начинаем её заполнять, и только после заполнения делаем её NOT NULL.
- Откат: каждая миграция должна иметь
down‑метод, который удаляет только то, что было добавлено, без потери данных (например, копировать данные в временную таблицу).
Пример миграции с поддержкой zero‑downtime:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
// 1. Добавляем nullable колонку
Schema::table('orders', function (Blueprint $table) {
$table->string('external_id')->nullable();
});
// 2. Фоновый скрипт заполняет колонку (можно в queue)
}
public function down(): void {
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn('external_id');
});
}
};Для отката в продакшн рекомендуется использовать php artisan migrate:rollback --step=1 только после подтверждения, что новая версия работает стабильно.
Миграции и откаты БД для FastAPI 0.110
FastAPI обычно использует Alembic в связке с SQLAlchemy. Стратегия аналогична Laravel, но требует отдельного скрипта для «online‑migration».
- Версионирование: каждый файл миграции хранит
revisionиdown_revision, что упрощает откаты. - Операции без блокировок: используйте
ALTER TABLE … ADD COLUMN … NULLи только после заполнения делайтеALTER TABLE … ALTER COLUMN … SET NOT NULL. PostgreSQL поддерживаетCONCURRENTLYдля создания индексов без блокировки. - Транзакционный откат: Alembic выполняет миграцию в транзакции (если СУБД поддерживает), позволяя откатить изменения в случае ошибки.
Пример миграции Alembic:
"""add external_id to orders"""
revision = "1234abcd"
down_revision = "abcd1234"
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
# 1. Добавляем nullable колонку
op.add_column('orders', sa.Column('external_id', sa.String(), nullable=True))
# 2. Фоновый процесс заполняет колонку
def downgrade():
op.drop_column('orders', 'external_id')
Откат выполняется командой alembic downgrade -1. При необходимости можно добавить «offline‑migration» скрипт, который будет запускаться в CI перед релизом.
Сравнительный анализ подходов
Оба оркестратора предоставляют надёжные механизмы rolling update, однако различаются в уровне абстракции и гибкости:
- Docker‑Swarm проще в настройке, требует меньше манифестов и подходит для небольших кластеров. Ограничения – отсутствие нативных CRD и меньший набор средств для canary‑деплоев.
- Kubernetes предлагает полноценный API, поддерживает canary, blue‑green и progressive delivery через инструменты (Argo Rollouts, Flagger). Цена – более высокая сложность управления и необходимость отдельного etcd.
- Миграции: Laravel использует миграции PHP‑скриптов, что удобно в CI, но требует дополнительного шага в пайплайне. Alembic в FastAPI более декларативен и лучше интегрируется с типизированным кодом.
- Откаты: в обоих случаях откат возможен, но в Kubernetes рекомендуется использовать
kubectl rollout undoсовместно с хранением предыдущих образов, а в Swarm –docker service update --rollback.
Практический пример CI/CD pipeline
Ниже – упрощённый GitLab CI файл, который покрывает оба стека и обеспечивает zero‑downtime деплой.
stages:
- build
- test
- migrate
- deploy
build_image:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
phpunit:
stage: test
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA composer test
pytest:
stage: test
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA pytest
migrate_laravel:
stage: migrate
only:
- master
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA php artisan migrate --force
migrate_alembic:
stage: migrate
only:
- master
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA alembic upgrade head
deploy_swarm:
stage: deploy
when: manual
script:
- docker service update --image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA api
- docker service rollback api || true
deploy_k8s:
stage: deploy
when: manual
script:
- kubectl set image deployment/api api=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/api
- kubectl rollout undo deployment/api --to-revision=1 || true
Обратите внимание, что миграции выполняются до обновления сервиса, а откаты доступны через rollback в случае неудачи.
Заключение
Zero‑downtime деплой – это сочетание правильно настроенного оркестратора, health‑checks и продуманной стратегии миграций. Docker‑Swarm подойдёт для небольших проектов с быстрым запуском, а Kubernetes предоставит максимум гибкости для крупных систем, требующих canary‑ и progressive‑delivery. При работе с Laravel 11 и FastAPI 0.110 важно писать миграции, которые не ломают схему в продакшн, и использовать откаты как часть CI/CD.
Если вам нужен надёжный дизайн и реализация сложных веб‑проекта с нулевым простоем, обращайтесь к Усачёву Денису (RybinskLab) – мы поможем построить масштабируемую инфраструктуру и автоматизировать деплой.