Деплой и инфра
Compose против Kubernetes: выбор правильного веса оркестрации
Команда из трёх человек выкатывает API и в первый же день берёт managed Kubernetes-кластер — «чтобы быть готовыми масштабироваться». Через полгода у них одна нода, одиннадцать сервисов, в которых никто не разбирается, и директория с YAML больше самого приложения. Кривой drain ноды роняет весь продукт на сорок минут, потому что никто не понял pod disruption budgets. Проблемы масштаба у них не было — они импортировали будущую и платили налог дежурства без трафика, который бы это оправдывал.
Два инструмента, две задачи
Docker Compose и Kubernetes оба «запускают контейнеры», и этот общий глагол прячет, насколько они разные. Compose — менеджер процессов на одном хосте: один docker-compose.yml объявляет сервисы, сети и тома, а docker compose up запускает их все на этой машине. Его быстро освоить, быстро запустить и тривиально дебажить — весь стек это один файл и docker compose logs. Накладные расходы крошечные, порядка ~50MB, потому что нет кластера, который надо держать.
Kubernetes — зверь другого вида: распределённый control plane, работающий поверх машин. Ты не запускаешь контейнеры; ты объявляешь желаемое состояние (3 реплики этого образа, за этим сервисом, с этими проверками здоровья), а control plane непрерывно работает, чтобы реальность совпала с ним. Это непрерывное совпадение и есть весь продукт, и оно стоит тебе настоящего control plane — примерно ~2GB резидентных накладных расходов до того, как твоё приложение поднимет хоть один контейнер.
Цикл согласования — это то, за что ты платишь
Единственный механизм, отделяющий Kubernetes от Compose, — это цикл согласования (reconciliation loop). Контроллеры наблюдают за кластером, сравнивают фактическое состояние с желаемым, хранящимся в etcd, и закрывают разрыв — непрерывно, по событиям, вечно. Единственная задача контроллера ReplicaSet — «держать N подов запущенными»: убей под, и он это заметит и заменит; потеряй целую ноду, и планировщик перепланирует её поды на здоровые ноды. Это самовосстановление (self-healing), и у Compose его попросту нет. restart: always у Compose перезапускает контейнер на том же хосте; если хост умирает, всё на нём умирает вместе с ним.
Тот же цикл питает rolling updates с проверкой здоровья. Deployment в Kubernetes поднимает новые поды, ждёт, пока пройдёт их readiness-проба, переводит трафик на них и только потом гасит старые — так кривой релиз никогда не обслуживает трафик, и ты получаешь zero-downtime выкатку и автоматический откат бесплатно. Compose перезапускает сервис на месте; в окне между остановкой и здоровым стартом этот сервис лежит. Нет ни проверки здоровья, ни автоматического отката.
| Возможность | Docker Compose | Kubernetes |
|---|---|---|
| Область планирования | Только один хост | Много нод, поды размещает планировщик |
| Отказ ноды | Всё на этом хосте умирает | Самовосстановление — поды переезжают |
| Деплои | Перезапуск на месте; короткий простой | Rolling update с проверкой readiness |
| Автомасштабирование | Нет (вручную, только вертикально) | Горизонтальное по метрикам |
| Накладные расходы | ~50MB, без control plane | ~2GB control plane до приложения |
| Кривая обучения | Минуты; один YAML-файл | Недели; поды, сервисы, CNI, RBAC, YAML |
Налог на сложность и кто его реально платит
Всё, что Kubernetes даёт, приходит в комплекте с налогом: control plane, который надо держать живым, сеть кластера (CNI), которую надо понять, RBAC, ingress, управление секретами и знаменитый разрастающийся YAML. Опросы стабильно ставят операционную сложность на первое место среди болей Kubernetes — около 70% пользователей называют её, — а кластеры рутинно работают на 30–50% утилизации, так что большая доля выделенного — это просто потери. Для маленькой команды цифра в деньгах жестокая: правдоподобный продакшен-сетап выходит в нижние пятизначные суммы в месяц, и реальная цена — это человеко-часы инженеров, уходящие на поддержание кластера вместо выпуска фич.
Поэтому трейдофф сеньора — не «что лучше», а возможности против налога на сложность, взвешенные относительно твоего реального масштаба. Возможности Kubernetes окупаются, только когда тебе действительно нужны планирование по нескольким нодам, zero-downtime выкатка под настоящим трафиком или автомасштабирование. Ниже этого ты платишь за самовосстановление поверх машин, которых у тебя нет, за планировщик, размещающий поды на единственной ноде. Каноничный провал — команда из трёх человек из Hook — это покупка налога до того, как появился масштаб, чтобы его оправдать.
Почему это работает
«Нам это понадобится для масштаба когда-нибудь» — фраза, которая покупает Kubernetes слишком рано. Честный контраргумент: один мощный хост с Compose может обслужить удивительно много трафика, а миграция на Kubernetes позже — известный, ограниченный проект. Импортировать его сложность сейчас — это постоянный налог с неопределённой датой окупаемости. Начинай с веса, который заработал твой трафик; апгрейдись, когда виден реальный потолок, а не гипотетический.
Где реально проходит граница — и что посередине
Есть честные сигналы, что ты перерос Compose. Первый — потолок одного хоста: Compose масштабируется вертикально (коробка побольше) или репликами на том же хосте, а у одной машины есть жёсткий предел — когда нужно размазать нагрузку по машинам, Compose не может. Второй — доступность: когда падение единственного хоста больше неприемлемо, нужно планирование, переживающее потерю ноды. Третий — операционные нужды, которых у Compose нет: zero-downtime rolling-деплои с проверкой здоровья и горизонтальное автомасштабирование под нагрузкой. Попади в одну из них по-настоящему — и налог начинает себя окупать.
Важно: это не бинарный выбор. Между «один хост с Compose» и «самоуправляемый Kubernetes» лежат варианты, дающие многонодовую устойчивость без полного операционного веса: Docker Swarm (многохостовый, синтаксис в духе Compose, куда проще k8s), HashiCorp Nomad и managed PaaS / serverless-контейнеры вроде Cloud Run, AWS App Runner, ECS или Azure Container Apps, которые гоняют твои контейнеры и берут масштабирование на себя без владения control plane. Managed Kubernetes (EKS/GKE/AKS) убирает эксплуатацию control plane, но не концептуальную сложность — ты по-прежнему владеешь подами, сетью и YAML.
Стартап из 4 человек гоняет API + Postgres + Redis + воркер, всё на одном арендованном сервере, скромный трафик. Выбери вес оркестрации.
Какая возможность — настоящая причина переходить с Compose на Kubernetes — то, чего Compose принципиально не может?
Что цикл согласования Kubernetes даёт такого, чего не даёт restart: always у Compose?
Расставь вопросы, которые сеньор задаёт, прежде чем тянуться к Kubernetes:
- 1 Влезает ли нагрузка на один хост с запасом на рост? Если да — Compose достаточно
- 2 Падение единственного хоста неприемлемо, или нужно размазать нагрузку по машинам?
- 3 Нужны ли zero-downtime rolling-деплои с проверкой здоровья или горизонтальное автомасштабирование?
- 4 Если да — может ли середина (Swarm, Nomad, managed PaaS) закрыть нужду с меньшим налогом?
- 5 Только если масштаб и ops-нужды реальны и середина не подходит → Kubernetes
- 01Объясни коллеге, почему команде из 3 человек брать самоуправляемый Kubernetes в первый же день — обычно ошибка, и что делать вместо этого.
- 02Какие конкретные сигналы говорят, что ты по-настоящему перерос Docker Compose?
Compose и Kubernetes оба запускают контейнеры, но отвечают на разные вопросы. Compose — менеджер процессов на одном хосте: один YAML, минуты на освоение, ~50MB накладных, идеален для локальной разработки и небольших однонодовых деплоев, но без многонодового планирования, без самовосстановления поверх машин, без выкаток с проверкой здоровья и без автомасштабирования. Kubernetes — распределённый control plane, чей цикл согласования непрерывно гонит реальность к объявленному желаемому состоянию, давая самовосстановление, планирование по нодам, zero-downtime rolling updates и горизонтальное автомасштабирование — ценой реального налога на сложность: control plane, CNI, RBAC, разрастающийся YAML, дежурства и пятизначные счета в месяц. Решение сеньора — возможности против сложности, взвешенные относительно реального масштаба. Каноничный провал — купить налог слишком рано; обратный провал — слишком долго игнорировать потолок одного хоста у Compose. Между ними лежат Swarm, Nomad и managed PaaS. Выбирай вес, который заработал твой трафик, и мигрируй, когда виден реальный потолок, а не гипотетический.