Learning Platform
Глоссарий Troubleshooting
Урок 20.02 · 22 мин
Средний
dockerkubernetescomposeproductionorchestration

Compose vs Kubernetes: когда переходить

Compose отлично работает для локальной разработки и небольших stateless-сервисов. Но у него есть жёсткий предел масштабирования. В какой-то момент команда сталкивается с вопросом: остаёмся на compose-стенде или переходим на Kubernetes?

Этот урок — про границу между ними. Когда compose достаточно, когда k8s неизбежен, и как мигрировать с минимальной болью.


Что compose делает хорошо

Compose — идеальный инструмент для:

  • Local development: одна команда docker compose up поднимает весь стек разработчика.
  • CI integration tests: в прошлом уроке мы видели, как compose + --wait — стандарт для интеграционных тестов.
  • Small production: один сервер, 5-15 контейнеров, без HA-требований. Например, internal-инструмент для команды.
  • POC и спринты: быстро попробовать новый сервис, поднять в compose, выкинуть.

Компонентов в compose — три: YAML-файл, Docker daemon на одной машине, docker compose CLI. Простота — его суперсила.

Compose vs Kubernetes по нагрузке
1 хост, dev/testcomposeЛокальный ноутбук разработчика, CI runner, small VM. Простой YAML, один docker daemon.
growth
N хостов, HAkubernetesНесколько серверов, требования к uptime, autoscaling, rolling updates. Compose не справится.
Single VM prodSingle-node prod: 1 VM с 16-32 GB RAM. До ~20 контейнеров. Без HA. Compose работает.
Swarm (legacy)Docker Swarm -- между compose и k8s. Multi-host через compose-подобный YAML. С 2024 в режиме maintenance, новые проекты не выбирают.
KubernetesKubernetes -- production standard. Autoscaling, multi-host, declarative state, огромная экосистема.

Анатомия Pod — базовая единица Kubernetes Deployment: декларативное управление репликами

Где compose ломается

Один хост = single point of failure

Если упал сервер с compose, вместе с ним упало всё. Нет автоматического failover на другой сервер.

В k8s: control plane следит за тем, что Pod’ы запущены на нужном количестве нод. Нода упала — Pod’ы перезапускаются на других нодах.

Нет autoscaling

# Compose: всегда 2 worker'а Spark, не больше не меньше
spark-worker:
  scale: 2

В k8s: HorizontalPodAutoscaler масштабирует Pod’ы по CPU/memory или custom metrics:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: spark-worker
spec:
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Нет rolling updates

# Compose: тебе нужно остановить и поднять
docker compose pull
docker compose up -d   # downtime пока pulling

В k8s: Deployment делает rolling update без downtime:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # на 1 больше реплик во время update
      maxUnavailable: 0  # 0 unavailable -- zero downtime

Нет declarative state

Compose — “process YAML, run containers”. Если ты руками удалил контейнер — compose не вернёт его, пока ты не сделаешь up.

В k8s — declarative. Удалил Pod — ReplicaSet создаст новый. Удалил Deployment — всё чисто. Контроллеры постоянно сверяют actual state с desired.

Нет nativ secrets management

В compose-проде секреты через .env — файл на диске. Кто угодно с доступом к серверу читает.

В k8s — Secrets, RBAC, opt-in encryption-at-rest, integration с Vault / AWS Secrets Manager / GCP Secret Manager.


Когда compose достаточно

Конкретные сценарии:

Internal dashboard для команды. 5 контейнеров: Grafana + Prometheus + cAdvisor + Loki + Tempo. Один сервер. 10 пользователей. Downtime 5 минут раз в неделю — ОК. Compose — правильный выбор. k8s — overkill (нужно потратить недели на setup, чтобы запустить то, что компоуз делает за час).

ETL для маленькой команды. Airflow + Postgres + один Spark worker. Делает ночные DAG’и. Если упал — джобы запустятся следующей ночью. Compose — OK.

Локальный dev. Всегда compose. k8s локально (через kind/minikube) для редких случаев, когда тестируешь Helm-charts.

CI integration tests. Всегда compose. Поднял, протестил, опустил.

Internal tool для одной команды разработки. Если работает 10 человек, downtime тебе не убьёт, и трафик предсказуем — compose.


Когда нужен k8s

Public-facing service. Если downtime стоит денег и пользователи ждут 99.9% uptime — нужен k8s c rolling updates и multi-node HA.

Большая команда (50+ engineers). k8s даёт namespace-isolation, RBAC, quotas. На compose-сервере у всех root.

Autoscaling по нагрузке. Spark-jobs, которые иногда требуют 5 workers, иногда 50. Compose не умеет; k8s — из коробки.

Микросервисы с service mesh. 30+ сервисов, каждый общается с 5 другими. mTLS, observability, traffic management — это Istio / Linkerd на k8s.

Compliance требования. SOC2, ISO27001 ожидают audit trails, RBAC, encryption — стандарт k8s.

Multi-region. Failover между регионами, traffic policies, replication. k8s + service mesh.


Общие концепции: маппинг compose -> k8s

# Compose
services:
  api:
    image: my-api:v1
    ports:
      - "8080:8080"
    environment:
      DB_URL: postgresql://postgres/api
    deploy:
      replicas: 3
    healthcheck:
      test: ["CMD", "curl", "--fail", "http://localhost:8080/health"]

Эквивалент в k8s — два объекта:

# Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels: {app: api}
  template:
    metadata:
      labels: {app: api}
    spec:
      containers:
        - name: api
          image: my-api:v1
          ports:
            - containerPort: 8080
          env:
            - name: DB_URL
              value: postgresql://postgres/api
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
---
# Service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector: {app: api}
  ports:
    - port: 8080
      targetPort: 8080

Сравнение:

ConceptComposeKubernetes
СервисserviceDeployment + Service (split)
Контейнерimage: в servicecontainers: в Pod
Группа контейнеровPod (1+ containers sharing network)
Репликиdeploy.replicasDeployment.spec.replicas
ENVenvironment:env:
Healthcheckhealthcheck:readinessProbe, livenessProbe
Volumevolumes:PersistentVolumeClaim + mount
Networknetworks:автоматически (Pod-to-Pod через DNS)
Secret.envSecret resource + envFrom
ConfigMapConfigMap resource (для non-secret конфигов)
Healthcheck-startupdepends_on: condition: service_healthyinitContainers + readinessProbes

В k8s Pod — это группа из 1+ контейнеров, которые шарят network namespace. Большинство DE-сервисов = 1 контейнер на Pod. Sidecar-pattern (logging-collector, secrets-fetcher) — больше.


kompose: автоматическая миграция

kompose — CLI, который генерирует k8s-манифесты из compose.yml.

brew install kompose
kompose convert -f compose.yml
# Создаёт api-deployment.yaml, api-service.yaml, postgres-deployment.yaml, ...

Это начальная точка, не финальный продукт. kompose не умеет:

  • Конвертировать profiles:.
  • Правильно ставить resource requests/limits (нужно по нагрузке настраивать).
  • Создавать proper liveness/readiness probes из compose healthcheck (часто превращает в command:).
  • Настраивать ingress (compose ports: это NodePort, не Ingress).
  • Работать с depends_on: condition: (k8s ожидает init-containers или job dependencies).

Реальный путь миграции:

  1. kompose convert — получи skeleton.
  2. Пройди руками: добавь resource requests, probes, ingress, secrets.
  3. Замени hostPath volumes на PersistentVolumeClaim (для stateful).
  4. Замени .env на Secret / ConfigMap.
  5. Деплой через Helm / Kustomize / ArgoCD.
WARNING

ВНИМАНИЕ: stateful-сервисы (Postgres, Kafka) на k8s — сложнее, чем stateless. Нужен StatefulSet, PersistentVolume, headless Service. Для production обычно используют operators: kafka-operator (Strimzi), postgres-operator (Zalando / Crunchy). Junior’у на компоуз-стеке этого ещё не нужно знать — но впереди.


Путь миграции для DE-стека

Если у тебя compose-стек с Airflow + Postgres + Kafka:

  1. Stateful сначала в managed services. Postgres -> RDS / Cloud SQL. Kafka -> MSK / Confluent Cloud. Это снимает 80% сложности k8s-stateful.

  2. Stateless — в k8s. Airflow webserver/scheduler/workers — это stateless (state в Postgres). Деплой через official Helm chart airflow-helm/airflow.

  3. Используй managed k8s. EKS / GKE / AKS. Не пытайся kubeadm-кластер на VM — это full-time-job.

  4. Observability отдельно. Не пихай Prometheus / Grafana в свой кластер на старте. Cloud-managed (CloudWatch / Stackdriver) — быстрее.

  5. CI/CD через ArgoCD или Flux. GitOps: ваш git-репо с k8s-манифестами — single source of truth.


Связь с нашим Kubernetes-курсом

Этот курс заканчивается на compose. Следующий шаг — наш [kubernetes-course] (отдельный курс на платформе). Там:

  • Pods, Services, Deployments в деталях.
  • StatefulSets и PersistentVolumes.
  • Helm charts для DE-сервисов (Airflow, Spark Operator).
  • Ingress, NetworkPolicies.
  • RBAC и security.
  • ArgoCD GitOps workflow.

После compose ты уже знаешь основы контейнеров, образов, сетей, volumes. В k8s эти концепции масштабируются. Не нужно учить с нуля.


Trade-offs: реальная цена k8s

K8s даёт многое, но требует:

  • Кривая обучения: 200+ ресурсных типов, 50+ концепций. Месяцы для свободной работы.
  • Operational overhead: etcd backups, version upgrades, security patches. Даже на managed.
  • Compute overhead: control plane + kubelet + system pods = 1-2 cores на ноду. На маленьком стенде это огромная доля.
  • Network complexity: CNI plugin, NetworkPolicy, Service mesh — много слоёв.
  • Cost: managed k8s (EKS) платит 73/месзаcontrolplane+nodes.ComposeVMможетстоить73/мес за control plane + nodes. Compose-VM может стоить 10/мес.

Если ты ещё junior, и команда поднимает k8s — скорее всего, рано. Если ты junior в команде, которая уже на k8s — учи. Это де-факто стандарт enterprise compute.


Попробуй сам

# 1. Установи kompose
brew install kompose  # или snap install kompose

# 2. Возьми любой compose.yml из предыдущих уроков (например, Airflow-стек)
kompose convert -f compose.yml

# 3. Посмотри, что сгенерировалось
ls *.yaml
# airflow-webserver-deployment.yaml
# airflow-webserver-service.yaml
# postgres-deployment.yaml
# postgres-service.yaml
# pg-data-persistentvolumeclaim.yaml

# 4. Локально подними k3d / kind / minikube
brew install k3d
k3d cluster create de-test

# 5. Применяй манифесты
kubectl apply -f .

# 6. Проверь
kubectl get pods
kubectl get services

# 7. Forward webserver:
kubectl port-forward svc/airflow-webserver 8080:8080
# Открой http://localhost:8080

# 8. Cleanup
k3d cluster delete de-test

Это даст ощущение пути migration. Сравни сгенерированный YAML с compose — увидишь, сколько добавилось boilerplate (Deployment+Service+PVC вместо одного service).


Проверка знанийKnowledge check
Ваша команда DE -- 5 человек, держит на одном VM compose-стенд: Airflow + Postgres + ClickHouse. Бизнес хочет 99.9% uptime для дашбордов. CTO предлагает мигрировать на k8s. Это правильное решение?
ОтветAnswer
Не обязательно нужен полный k8s. 99.9% uptime = ~8.76 часов downtime в год -- это много, compose-стенд на одной VM может это дать (с auto-restart docker daemon и monitoring). Но для надёжного 99.9% реалистичный путь: (1) Postgres вынести в managed RDS / Cloud SQL -- решит 50% проблем (auto-failover, бэкапы). (2) ClickHouse -- в managed Aiven / Altinity Cloud, или в k8s через ClickHouse Operator. (3) Airflow -- managed (MWAA / Cloud Composer) или Helm на k8s. Полный k8s оправдан, когда команда >20 человек и приложений >10. Для 5 человек и 3 сервисов managed services + один compose-stenkov может быть дешевле и проще. Решение зависит от: бюджет, есть ли DevOps-ресурс, planned growth.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. В каком сценарии compose-стенд лучшее решение, чем k8s?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4