Перейти к содержимому
ADMIN
FUTURE
Главная страница » Kubernetes: когда он реально нужен, а когда это Compose с понтами
FIELD NOTES / 29.09.2026

Kubernetes: когда он реально нужен, а когда это Compose с понтами

Максим Шаповалов11 мин чтения

В статье про Docker была одна фраза, которую легко пропустить, но которая на самом деле определяет треть решений об инфраструктуре, принимаемых сейчас в индустрии: «переходить на Kubernetes стоит тогда, когда конкретная проблема масштаба уже есть, а не потому что «так делают большие компании»». За этой фразой стоит целая эпидемия — тысячи компаний с тремя серверами и одним сайтом, у которых в проде крутится полноценный K8s-кластер, потому что на собеседовании неловко сказать «у нас просто Docker Compose». «Админ» ставит Kubernetes, потому что это модно и хорошо смотрится в резюме. «Архитектор» сначала считает, какую именно проблему он решает — а потом либо ставит Kubernetes осознанно, либо честно признаёт, что три сервера с Compose закрывают вопрос лучше, дешевле и с меньшим числом того, что может сломаться в три часа ночи.

Эта статья не будет ни агитировать за Kubernetes, ни высмеивать его как «оверинжиниринг для всех подряд» — оба лагеря одинаково бесполезны на практике. Вместо этого — честный разбор: какую именно проблему решает Kubernetes, чего он стоит на самом деле (не только в деньгах), и конкретный набор сигналов, по которым можно понять, действительно ли она у вас есть.


1. Что Kubernetes реально делает — без маркетинга

Compose и Kubernetes решают на первый взгляд похожую задачу — «опиши стек, запусти контейнеры» — но по факту это принципиально разные модели. Compose императивен по духу: вы говорите «подними эти сервисы» на конкретном хосте, и он их поднимает именно там. Kubernetes декларативен и работает по принципу постоянного согласования состояния (reconciliation loop): вы описываете желаемое состояние («мне нужно 3 реплики этого пода, с этими лимитами ресурсов, за этим сервисом»), а контроллер-менеджер непрерывно, десятки раз в секунду, сверяет это описание с реальностью кластера и сам чинит любое расхождение.

Именно из этого вытекают четыре вещи, которые Kubernetes даёт «бесплатно», и ради которых люди на него переходят:

  • Самовосстановление на уровне кластера, а не хоста. Если физический сервер, на котором крутился под, полностью упал — Kubernetes сам перепланирует его на другой узел с достаточным количеством ресурсов. Docker Compose такого не умеет в принципе: он управляет контейнерами на одном хосте, и если хост лёг, поднимать сервисы больше некому.
  • Планирование по ресурсам, а не по хосту. Вы говорите «этому поду нужно 2 CPU и 4 ГБ», а не «запусти его на сервере web-03» — планировщик сам находит узел, где реально есть это свободное место, с учётом уже запущенного на кластере.
  • Rolling-обновления с автоматическим откатом. Deployment сам поднимает новые поды, ждёт, пока они пройдут readiness-проверку, только потом гасит старые — и откатывается назад, если новая версия не проходит health-check.
  • Service discovery и балансировка из коробки, на уровне всего кластера, а не одной bridge-сети на хосте, как в Docker (см. статью про сеть Docker) — под может обратиться к сервису по имени независимо от того, на каком узле кластера тот физически сейчас работает.

💡 Ключевая мысль этого раздела: все четыре пункта выше решают задачи, которые становятся реальными только тогда, когда у вас несколько физических узлов, между которыми нужно распределять нагрузку и переживать отказ отдельного узла. Если у вас один сервер — все четыре пункта не имеют смысла: перепланировать под некуда, «весь кластер» и есть один хост, который либо жив, либо нет.


2. Тот же docker-compose.yml, три разных мира

Чтобы разница была не абстрактной, возьмём один и тот же простой стек — веб-приложение, база данных, reverse proxy, ровно тот, что уже был в статье про Docker — и посмотрим, что меняется на каждом следующем уровне.

Уровень 1 — Compose на одном сервере. Ровно то, что уже разбиралось: docker compose up -d, depends_on: condition: service_healthy, именованные тома. Если сервер падает целиком — падает всё, пока кто-то не перезапустит его руками или не сработает скрипт автоперезапуска на уровне облака.

Уровень 2 — Docker Swarm. Часто забытый режим самого Docker: те же compose-файлы (с небольшими отличиями в поддерживаемых ключах), но docker stack deploy вместо docker compose up — и сервисы уже распределяются по нескольким узлам с базовым самовосстановлением. Swarm жив, поддерживается, и для команды из 2-5 человек с 3-10 серверами часто закрывает 80% того, ради чего берут Kubernetes — ценой на порядок меньшей сложности:

Bash — тот же стек, но на кластере из нескольких узлов

# На первом сервере — инициализация кластера
docker swarm init --advertise-addr 10.0.0.1

# На остальных серверах — присоединение по токену,
# который выведет предыдущая команда
docker swarm join --token SWMTKN-xxx 10.0.0.1:2377

# Тот же самый docker-compose.yml, но через stack deploy —
# сервисы сами разъедутся по узлам с учётом реплик
docker stack deploy -c docker-compose.yml myapp

# Масштабирование одной командой, без правки YAML
docker service scale myapp_web=5

# Живой статус — на каком узле что крутится прямо сейчас
docker service ps myapp_web

Уровень 3 — Kubernetes. Тот же стек, но описанный уже не в docker-compose.yml, а в наборе YAML-манифестов (Deployment, Service, PersistentVolumeClaim, Ingress), применяемых через kubectl apply -f либо через Helm-чарт. Разница — не в том, что K8s «мощнее», а в том, что за эту мощность платится совсем другим объёмом движущихся частей, разобранных в следующем разделе.


3. Настоящая цена Kubernetes — не в деньгах за инстансы

Самая частая ошибка при оценке Kubernetes — считать его стоимость в цене серверов под control plane. Реальная цена — в операционной сложности, которая никуда не девается даже на managed-кластере (EKS, GKE, Managed Kubernetes от облачных провайдеров):

  • Сеть перестаёт быть простой. В Docker есть одна bridge-сеть и понятный docker network create. В Kubernetes есть CNI (Container Network Interface) — отдельный плагин (Calico, Cilium, Flannel), который нужно выбрать, настроить и понимать, как он маршрутизирует трафик между подами на разных узлах. Отладка «под А не достучался до пода Б» в Kubernetes на порядок сложнее, чем в Compose, просто потому что слоёв абстракции больше.
  • Хранилище — отдельная экосистема. Именованный том Docker — это папка на диске хоста. PersistentVolume в Kubernetes — это объект, привязанный к StorageClass, который сам обращается к CSI-драйверу (Container Storage Interface) конкретного облака или SAN. Для нового человека в команде это уже не «примонтировать папку», а разобраться в целой прослойке абстракций.
  • YAML разрастается быстрее кода приложения. Простой сервис с базой в Kubernetes — это обычно Deployment + Service + ConfigMap + Secret + PersistentVolumeClaim + Ingress, часто 150-300 строк YAML вместо 30 строк docker-compose.yml. И это без Helm-чартов и Kustomize-оверлеев, которые команды добавляют, чтобы совладать с этим же разрастанием.
  • Нужен человек, который спит спокойно с etcd. etcd — распределённая база данных, в которой Kubernetes хранит всё состояние кластера. Её отказ или рассинхронизация — один из самых болезненных инцидентов в мире Kubernetes, и на самостоятельно управляемом кластере ответственность за её здоровье (бэкапы, компакция, мониторинг задержек) целиком на вас. Managed-Kubernetes снимает именно эту головную боль — и это едва ли не главная причина, почему self-hosted control plane сегодня выбирают всё реже.

⚠️ Частая ошибка «Админа»: сравнивать «Compose на 3 серверах» с «managed Kubernetes» и делать вывод, что K8s «почти бесплатен», раз облако само держит control plane. Managed control plane снимает только один пункт из четырёх выше — сеть, хранилище и YAML-сложность остаются полностью на команде в любом случае.


4. Сигналы «пора» — и сигналы «рано»

Вместо абстрактного «когда вырастете» — конкретный список признаков, каждый из которых сам по себе указывает на реальную, а не воображаемую потребность в оркестрации такого уровня:

Сигналы «пора» (хотя бы 2-3 одновременно — весомый аргумент)

  • У вас уже больше 5-10 физических/виртуальных узлов, и распределение нагрузки между ними вручную (или через Swarm) начинает требовать отдельного человека на полный день.
  • Несколько независимых команд деплоят разные сервисы на одну и ту же инфраструктуру, и им нужна изоляция ресурсов и прав (Namespaces, ResourceQuotas, RBAC) без ручной координации между собой.
  • Нагрузка реально скачет в разы в течение суток или сезона (маркетплейс перед распродажей, сервис с пиками по расписанию) — и вам нужен настоящий autoscaling по метрикам, а не «руками добавить пару серверов на выходные».
  • Требования по compliance или архитектуре явно требуют network policies на уровне отдельных подов/сервисов, а не только периметрового файрвола.
  • У вас уже десятки микросервисов, и часть операционной боли — не в самих контейнерах, а в том, что нужно единообразно управлять их деплоем, конфигами и секретами через общий API, а не через набор bash-скриптов по SSH.

Сигналы «рано» — если это описывает вас, Kubernetes добавит риска, а не снимет его

  • Весь прод — 1-3 сервера, и это не собирается измениться в обозримые полгода-год.
  • В команде никто, включая вас самих, никогда не отлаживал сетевые проблемы CNI или не читал логи kube-apiserver в реальном инциденте.
  • Основной аргумент за переход — «так делают в компании, где я работал раньше» или «это хорошо выглядит в резюме команды», а не конкретная измеримая проблема, которая есть прямо сейчас.
  • У вас нет отдельного человека или роли, готовой взять на себя постоянную операционную нагрузку кластера — обновления версий, патчи безопасности control plane, мониторинг здоровья etcd (даже managed control plane не отменяет обновление версии кластера и миграцию API при выходе deprecated-полей).

5. Если решение принято — с чего начинать, а что отложить

Если сигналы из предыдущего раздела реально совпали — вот порядок, который экономит месяцы боли по сравнению с попыткой внедрить «весь Kubernetes сразу»:

  1. Managed control plane — всегда, если это вообще доступно. Self-hosted etcd и control plane — задача для команд, у которых это осознанный основной продукт (например, инфраструктурные провайдеры), а не побочная деятельность рядом с основным бизнесом.
  2. Сначала базовые объекты, без Helm и без Operators. Deployment, Service, ConfigMap, Secret, Ingress — этого достаточно для 90% реальных сервисов на старте. Helm-чарты решают проблему повторного использования конфигурации, которой у вас пока, скорее всего, ещё нет с одним-двумя сервисами.
  3. Один инструмент для наблюдаемости с первого дня. kubectl logs по одному поду не масштабируется дальше пяти сервисов — сразу закладывайте централизованный сбор логов и метрик (тот же стек Zabbix/ELK, уже разбиравшийся в статье про аудит Linux-сервера, или облачный аналог), а не откладывайте на «когда будет больно».
  4. Service Mesh (Istio, Linkerd) — сознательно последним, а не по умолчанию. Он решает задачи взаимного TLS между сервисами, детальной трассировки и канареечных релизов на уровне трафика — реальные задачи, но для кластера с 5-10 сервисами это почти всегда чистый оверинжиниринг поверх оверинжиниринга.

Bash — минимальный, но настоящий Deployment + Service, без Helm

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
        - name: web
          image: myapp:latest
          resources:
            requests: { cpu: "250m", memory: "256Mi" }
            limits: { cpu: "500m", memory: "512Mi" }
          readinessProbe:
            httpGet: { path: /healthz, port: 3000 }
            initialDelaySeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector: { app: web }
  ports:
    - port: 80
      targetPort: 3000

Обратите внимание на resources.requests/limits и readinessProbe — это прямые аналоги лимитов ресурсов и healthcheck из статьи про продакшен-готовность Docker-стека, просто описанные в декларативной модели Kubernetes вместо флагов docker run. Идея не меняется от смены инструмента — меняется только то, кто и как её применяет: раньше вы сами следили за лимитами на каждом хосте, теперь планировщик кластера делает это за вас, но только если вы явно об этом попросили.


Чек-лист: Compose, Swarm или Kubernetes

  1. Сформулируйте проблему масштаба одним конкретным предложением — не «нам нужен Kubernetes», а «нам нужно X, потому что Y уже происходит прямо сейчас». Если предложение не складывается — это уже ответ.
  2. Посчитайте узлы, а не серверы вообще — Kubernetes и даже Swarm начинают окупаться там, где узлов действительно несколько и нагрузку нужно между ними реально распределять.
  3. Попробуйте Swarm как промежуточный шаг, если чувствуете, что Compose на одном сервере уже тесно, но полного набора возможностей Kubernetes пока не нужно.
  4. Managed control plane, если решение в пользу K8s принято — self-hosted etcd не должен быть первым опытом команды с Kubernetes.
  5. Начинайте с Deployment/Service/Ingress без Helm, добавляйте инструменты экосистемы по мере реальной, а не воображаемой необходимости.

Вывод

Kubernetes не является «более продвинутой версией Docker» — это ответ на другой вопрос, который имеет смысл задавать только тогда, когда у вас действительно несколько узлов, между которыми нужно распределять нагрузку и переживать отказ. Для инфраструктуры в один-три сервера Compose (или Swarm, если хочется чуть больше отказоустойчивости без прыжка в полный оркестратор) — не временное решение до того, как «дорастёте» — это архитектурно верный выбор, который останется верным, даже когда денег на инфраструктуру станет больше.

Если из всей статьи запомнить одно правило: не спрашивайте «готовы ли мы к Kubernetes» — спрашивайте «какую конкретную, уже случившуюся проблему он решит, которую Compose или Swarm решить не может». Если честный ответ находится — переходите осознанно. Если нет — три сервера с Compose и есть архитектурно правильный выбор, а не временный компромисс.


Теги: #kubernetes #docker #devops #оркестрация #compose #sysadmin #infra #k8s


🚀 Хотите стать архитектором будущего, а не просто админом? Эта статья — лишь верхушка айсберга. В нашем Telegram-канале «Admin Future» мы каждый день публикуем системные гайды, готовые скрипты, AI-лайфхаки и чеклисты, которые не найти в Google. Мы не просто постим команды — мы строим библиотеку знаний для тех, кто хочет расти от админа до архитектора. Подписывайтесь и становитесь экспертом: Admin Future

МШ

Максим Шаповалов

Системный администратор. 17+ лет работы с инфраструктурой.

Обсудить задачу ↗

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх