Выбор контроллера Kubernetes: Deployment, StatefulSet, DaemonSet и Job — практическое сравнение и примеры | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Выбор контроллера Kubernetes: Deployment, StatefulSet, DaemonSet и Job — практическое сравнение и примеры

27 мая 2026 9 мин. чтения

В Kubernetes запустить Pod - это лишь первый шаг. Для реальных приложений нужны контроллеры: они управляют жизненным циклом Pod'ов, обеспечивают масштабирование, обновления и устойчивость. Deployment, StatefulSet, DaemonSet и Job - это четыре основных инструмента, каждый решает свою задачу. Правильный выбор определяет стабильность, корректность работы и управляемость вашего сервиса. Эта статья - практический гид для DevOps-инженеров и администраторов. Мы детально сравним контроллеры по ключевым параметрам, дадим готовые примеры YAML и алгоритм для принятия обоснованных архитектурных решений.

Зачем нужны контроллеры: от Pod к управляемым приложениям

Pod - минимальная единица развертывания в Kubernetes. Однако самостоятельный Pod не имеет механизмов самовосстановления, масштабирования или управляемых обновлений. Контроллер - это абстракция, которая декларативно описывает желаемое состояние группы Pod'ов и непрерывно работает для его достижения. Он выступает «мозгом», управляющим жизненным циклом Pod'ов под конкретные цели.

В Kubernetes есть четыре главных контроллера для разных сценариев:

  • Deployment - стандартный инструмент для развертывания и управления stateless-приложениями, например веб-сервисами или API.
  • StatefulSet - контроллер для stateful-приложений с состоянием, таких как базы данных или очереди сообщений, где важны порядок, устойчивая идентичность и постоянное хранилище.
  • DaemonSet - специализированный контроллер для запуска одного Pod'а на каждом узле кластера, обычно для системных демонов мониторинга или сетевых плагинов.
  • Job и CronJob - контроллеры для выполнения разовых или периодических задач с конечным результатом, например миграции базы данных или генерации отчетов.

Все эти контроллеры, кроме Job, используют ReplicaSet «под капотом» как механизм для поддержания заданного числа реплик Pod.

Pod и ReplicaSet: фундамент, на котором строятся контроллеры

Pod - это группа одного или нескольких контейнеров с общими ресурсами сети и хранилища. Это атомарная единица, которую Kubernetes планирует на узлы.

ReplicaSet - простейший контроллер. Его единственная задача - поддерживать заданное количество идентичных реплик Pod'ов (spec.replicas). Если Pod завершается, ReplicaSet создает новый. Если количество Pod'ов превышает заданное, ReplicaSet удаляет лишние. Он не управляет обновлениями или сложным жизненным циклом. Deployment, StatefulSet и DaemonSet используют ReplicaSet (или его логику) для обеспечения базовой репликации, добавляя к этой основе свою специфическую логику: стратегии обновления, управление хранилищем или правила размещения.

Deployment: стандарт для stateless-приложений и веб**-сервисов

Deployment - самый распространенный контроллер Kubernetes. Его основное назначение - развертывание и управление stateless (без состояния) приложениями. Pod'ы в Deployment взаимозаменяемы: они не имеют устойчивой сетевой идентичности (имя и IP меняются при пересоздании) и не требуют постоянного хранилища, привязанного к конкретной реплике. Это идеально для веб-серверов (Nginx, Apache), микросервисов, API и других сервисов, где любая реплика может обслуживать запрос.

Ключевые особенности Deployment:

  • Управляемые стратегии обновления: RollingUpdate (постепенная замена) и Recreate (полное удаление перед созданием новых).
  • Простое масштабирование: изменение количества реплик через kubectl scale или редактирование манифеста.
  • Откат к предыдущей версии: возможность вернуться к предыдущей ревизии Deployment при проблемах.

Для детального изучения структуры манифеста и лучших практик обратитесь к нашему руководству по структуре YAML-манифестов Kubernetes.

Стратегии обновления: Rolling Update vs Recreate

Выбор стратегии обновления критически влияет на downtime и риски при деплое.

  • RollingUpdate: Pod'ы новой версии создаются постепенно, одновременно работают Pod'ы старых и новых версий. Это обеспечивает непрерывность сервиса, но требует совместимости версий приложения (например, API). Конфигурация параметров maxSurge (сколько дополнительных Pod'ов можно создать сверх replicas) и maxUnavailable (сколько Pod'ов могут быть недоступны во время обновления) позволяет контролировать скорость и нагрузку.
  • Recreate: все старые Pod'ы удаляются перед созданием новых. Это приводит к кратковременному простою, но гарантирует чистый запуск новой версии без потенциальных конфликтов между репликами разных версий. Используется для приложений, где такая совместимость невозможна.

Пример конфигурации стратегии в YAML:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

Практический пример: развертывание веб-приложения Nginx

Это готовый YAML-манифест Deployment для развертывания Nginx с 3 репликами.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

После создания файла apply-deployment.yaml применяем его командой:

kubectl apply -f apply-deployment.yaml

Статус можно проверить командами kubectl get deployments и kubectl get pods. Для более сложных production-сценариев, включающих настройку проверок жизнеспособности и готовности, изучения полного руководства по Deployment даст готовые манифесты и пошаговые инструкции.

StatefulSet: для stateful-приложений с состоянием и порядком

StatefulSet предназначен для приложений, которые требуют сохранения состояния, устойчивой идентичности и строгого порядка операций. Типичные use-cases: базы данных (MySQL, PostgreSQL, MongoDB), очереди сообщений (Kafka, RabbitMQ) и кластерные приложения.

Ключевые различия StatefulSet от Deployment:

  • Устойчивая сетевая идентичность: каждый Pod получает стабильное имя (например, redis-0, redis-1) и DNS запись (redis-0.redis-service.default.svc.cluster.local), которая сохраняется даже после перезапуска Pod'а.
  • Упорядоченный и предсказуемый запуск/масштабирование: Pod'ы создаются последовательно (pod-0, затем pod-1) и в обратном порядке удаляются при масштабировании вниз.
  • Устойчивое хранилище: PersistentVolume, созданный через volumeClaimTemplates, привязывается к конкретному Pod и сохраняется при его пересоздании. Это гарантирует сохранность данных.

Pod'ы в StatefulSet не взаимозаменяемы. Каждый имеет уникальную роль и данные.

Управление хранилищем: Headless Service и PersistentVolumeClaims

Организация хранилища - самая сложная часть StatefulSet.

Headless Service: это Service без ClusterIP (clusterIP: None). Он не выполняет балансировку нагрузки, но обеспечивает стабильную DNS запись для каждого Pod'а StatefulSet, позволяя другим Pod'ам напрямую обращаться к конкретной реплике по имени. StatefulSet требует указания такого Service в поле serviceName.

volumeClaimTemplates: секция в манифесте StatefulSet, которая описывает шаблон для создания PersistentVolumeClaim (PVC). При создании каждого Pod'а StatefulSet создает для него уникальный PVC по этому шаблону. PVC затем связывается с PersistentVolume (PV), предоставляющим фактическое хранилище. Правильная настройка StorageClass критична для автоматического создания PV.

Пример структуры:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  serviceName: "redis-service"
  replicas: 2
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "fast-ssd"
      resources:
        requests:
          storage: 10Gi
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: data
          mountPath: /data

Практический пример: запуск кластера Redis с мастер-репликой

Это упрощенный пример StatefulSet для разворачивания двух инстансов Redis. Pod'ы получают имена redis-0 и redis-1. Для полноценного кластера Redis потребуется дополнительная конфигурация, но этот манифест демонстрирует базовые принципы.

apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  clusterIP: None
  selector:
    app: redis
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-statefulset
spec:
  serviceName: "redis-service"
  replicas: 2
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7-alpine
        ports:
        - containerPort: 6379

После применения Pod'ам можно обращаться по DNS: redis-0.redis-service.default.svc.cluster.local и redis-1.redis-service.default.svc.cluster.local.

DaemonSet и Job/CronJob: специализированные контроллеры

DaemonSet: системные демоны на каждом узле кластера

DaemonSet гарантирует запуск одного Pod'а на каждом узле кластера (или на узлах, соответствующих селекторам). Его назначение узкое, но критически важно для инфраструктурных задач.

Типичные use-cases:

  • Агенты мониторинга: Prometheus Node Exporter для сбора метрик с каждого узла.
  • Сборщики логов: Fluentd или Filebeat для агрегации логов со всех узлов.
  • Сетевые плагины: компоненты CNI, такие как Calico или Weave, которые должны работать на каждом узле для обеспечения сетевой коммуникации Pod'ов.

DaemonSet автоматически добавляет Pod на каждый новый узел, присоединенный к кластеру. Для запуска на master-узлах (которые обычно имеют taint для предотвращения запуска пользовательских Pod'ов) необходимо использовать tolerations в спецификации Pod.

Пример YAML для развертывания Node Exporter:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      tolerations:
      - key: "node-role.kubernetes.io/master"
        effect: "NoSchedule"
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.6.1
        ports:
        - containerPort: 9100

Job и CronJob: задачи с конечным результатом

Job и CronJob предназначены для выполнения задач, которые должны завершиться, а не работать непрерывно.

Job выполняет разовую задачу до успешного завершения. Параметры completions определяет количество успешных выполнений задачи, parallelism - сколько Pod'ов могут работать параллельно для достижения этого количества. Используется для миграции базы данных, обработки данных, запуска скриптов.

CronJob - это Job, запускаемый по расписанию, синтаксис которого аналогичен crontab (например, "0 * * * *" для запуска каждый час). Важно настроить historyLimit и successfulJobsHistoryLimit для управления историей выполненных задач.

Пример YAML для Job (запуск скрипта):

apiVersion: batch/v1
kind: Job
metadata:
  name: data-migration-job
spec:
  completions: 1
  parallelism: 1
  template:
    spec:
      containers:
      - name: migrator
        image: alpine:3.18
        command: ["sh", "-c", "echo 'Migration completed'"]
      restartPolicy: Never

Пример YAML для CronJob (ежедневный бэкап):

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-tool:latest
            command: ["backup.sh"]
          restartPolicy: OnFailure

Сравнительная таблица и алгоритм выбора

Эта таблица суммирует ключевые различия контроллеров и служит инструментом для быстрого принятия решения.

КонтроллерОсновное назначениеУправление состояниемСетевая идентичностьХранилищеСтратегия размещенияСтратегия обновленияЖизненный цикл Pod
DeploymentStateless приложения (веб, API)StatelessНеустойчиваяОбщее или временноеЛюбой узелRollingUpdate, RecreateНепрерывный
StatefulSetStateful приложения (БД, очереди)StatefulУстойчивая (pod-0.svc)Уникальное, постоянное (PVC)Любой узелRollingUpdateНепрерывный
DaemonSetСистемные демоны (агенты)Stateless или StatefulНеустойчиваяОбщее или постоянноеНа каждом узлеRollingUpdateНепрерывный
JobРазовая задача (миграция)Не имеет значенияНеустойчиваяОбщее или временноеЛюбой узелНетЗавершается
CronJobПериодическая задача (бэкап)Не имеет значенияНеустойчиваяОбщее или временноеЛюбой узелНетЗавершается

Пошаговый алгоритм выбора:

  1. Ваше приложение выполняет задачу и завершается? -> Job/CronJob.
  2. Нужно ли запускать Pod на каждом узле кластера? -> DaemonSet.
  3. Есть ли у приложения состояние (уникальные данные, порядок запуска, устойчивая идентичность)? -> StatefulSet.
  4. Во всех остальных случаях -> Deployment.

Распространенные ошибки и как их избежать

Ошибки в выборе контроллера приводят к потере данных, нестабильности сервиса и сложностям управления.

  • Использование Deployment для stateful-приложений. Это самая опасная ошибка. При пересоздании Pod'а в Deployment его данные, хранящиеся в ephemeral storage или общем volume, могут быть потеряны. Для баз данных всегда используйте StatefulSet с правильно настроенным volumeClaimTemplates и Headless Service.
  • Неправильная настройка volumeClaimTemplates в StatefulSet. Указание неподдерживаемого accessMode (например, ReadWriteMany для блока хранилища, который поддерживает только ReadWriteOnce) или отсутствие StorageClass приведет к невозможности создания Pod'ов. Проверьте возможности вашего провайдера хранилища перед составлением манифеста.
  • Запуск DaemonSet без tolerations на master-узлах. Если ваш DaemonSet должен работать на master-узлах (например, сетевой плагин), но в манифесте отсутствуют соответствующие tolerations, Pod'ы не будут запущены. Добавьте tolerations для taint'ов master-узлов.
  • Использование Job для долгоживущих сервисов. Job предназначен для завершаемых задач. Если запустить в Job процесс, который должен работать непрерывно (например, веб-сервер), он завершится после выполнения команды, и контроллер не будет его перезапускать. Для сервисов используйте Deployment или StatefulSet.
  • Игнорирование стратегии обновления в Deployment. Не заданная стратегия обновления может привести к непредсказуемому поведению при деплое. Явно указывайте type: RollingUpdate или Recreate и настраивайте параметры maxSurge/maxUnavailable для контроля над процессом.

Для глубокой диагностики проблем с конфигурацией, особенно при работе с Custom Resources, может помочь наш гайд по полной диагностике Custom Resources в Kubernetes.

Выбор правильного контроллера - фундаментальное архитектурное решение в Kubernetes. Deployment подходит для большинства stateless-сервисов. StatefulSet необходим для приложений с состоянием, где критичны порядок и устойчивое хранилище. DaemonSet обслуживает инфраструктурные задачи на каждом узле. Job и CronJob выполняют разовые и периодические работы. Используйте приведенную таблицу и алгоритм для системного выбора, а готовые примеры манифестов - для быстрого старта. Это позволит избежать типичных ошибок и построить стабильную, управляемую среду.

Поделиться:
Сохранить гайд? В закладки браузера