Deployments, StatefulSets і DaemonSets у Kubernetes

У Kubernetes для керування подами використовують різні типи контролерів. Найпоширеніші з них — Deployment, StatefulSet та DaemonSet. Вони виконують різні функції, хоча на рівні конфігурацій можуть виглядати схожими.

Вибір контролера безпосередньо впливає на стабільність застосунку, поведінку під час оновлень, масштабування та відновлення після збоїв. Помилки на цьому етапі зазвичай проявляються вже в продакшні — під навантаженням або під час інцидентів.

У цій статті розглянемо, як працюють Deployments, StatefulSets і DaemonSets, у чому полягають їх ключові відмінності та в яких випадках кожен із них доцільно використовувати в кластерах Kubernetes.

Контролери Kubernetes

У Kubernetes майже всім керують контролери. Їхнє завдання — стежити за поточним станом ресурсів і приводити його до бажаного. Ви описуєте як має бути, а контролер вирівнює реальність під цю декларацію.

Важливо: Deployments, StatefulSets і DaemonSets керують подами, але з різними гарантіями щодо ідентичності, порядку запуску та прив’язки до вузлів. Саме ці гарантії та визначають, який варіант правильний.

Deployment: стандарт для застосунків stateless

Deployment — найпоширеніший спосіб запуску застосунків у Kubernetes. Він створює й підтримує потрібну кількість однакових подів (реплік) та вміє оновлювати їх поступово, без простою сервісу.

Ключова ідея: поди взаємозамінні. Якщо один падає, його можна замінити іншим з таким самим шаблоном, і для користувача це буде непомітно.

Що дає Deployment на практиці?

  1. Автовідновлення. Видалили под випадково або він впав — контролер підніме новий.
  2. Масштабування. Потрібно більше потужності — збільшили replicas, і кластер додав поди.
  3. Rolling update. Оновлення образу відбувається порціями: частина подів уже на новій версії, частина — ще на старій.
  4. Rollback. Якщо оновлення пішло не так, можна повернутися до попереднього стану.

Ось базовий YAML-файл для розгортання:

apiVersion: apps/v1

kind: Deployment

metadata:

  name: simple-web-app

spec:

  replicas: 3

  selector:

    matchLabels:

      app: web

  template:

    metadata:

      labels:

        app: web

    spec:

      containers:

      - name: web-container

        image: nginx:latest

        ports:

        - containerPort: 80

Коли обирати Deployment?

Deployment підходить, якщо:

  • застосунок не зберігає критичний стан усередині пода;
  • будь-який под може обробити будь-який запит;
  • ви хочете прості оновлення й масштабування.

Типові приклади: фронтенд, API, мікросервіси, проксі.

На що звернути увагу, щоб не наступити на граблі?

  • Readiness та liveness probes

Readiness визначає, коли под готовий приймати трафік. Без нього оновлення може пройти формально успішно, але запити почнуть надходити на сервіс, який ще не готовий до роботи. Liveness відповідає за перезапуск завислих або некоректно працюючих контейнерів.

  • Ресурсні обмеження

Якщо для контейнерів не задано мінімальні та максимальні обсяги ресурсів, Kubernetes гірше розподіляє навантаження. У результаті один сервіс може перевантажувати вузол і впливати на роботу інших компонентів кластера.

  • Стратегія оновлення

Для сервісів, що мають працювати без простою, важливо коректно налаштувати параметри maxUnavailable і maxSurge. Вони визначають, скільки подів може бути недоступно та скільки нових подів створюється під час rolling update.

Корисні команди для перевірки:

  • kubectl get deployments

Виводить список наявних розгортань у поточному namespace та їхній стан: кількість бажаних, поточних і доступних реплік. Дозволяє перевірити, чи конфігурація застосована коректно.

  • kubectl get pods

Показує всі поди, створені в межах розгортання, їхній статус і час роботи. Команда допомагає швидко виявити проблеми зі стартом або виконанням контейнерів.

  • kubectl rollout status deployment/web

Відображає стан процесу оновлення. Дає змогу перевірити, чи rolling update завершився успішно або ще триває.

  • kubectl rollout undo deployment/web

Повертає систему до попередньої версії у разі проблем після оновлення.

StatefulSet: керування застосунками зі збереженням даних

StatefulSet потрібен там, де застосунок має зберігати дані або покладається на стабільну ідентичність кожного екземпляра. На відміну від Deployment, він гарантує, що поди матимуть сталі імена та запускатимуться в чіткому порядку.

Побачите таке найменування: app-0, app-1, app-2. Якщо app-1 впаде, Kubernetes підніме саме app-1 з тим самим індексом.

Ключові можливості StatefulSet

  • Стабільні імена подів. Поди мають імена, що дозволяє базам даних і розподіленим сервісам коректно працювати після перезапусків.
  • Окреме постійне сховище для кожного пода. Зазвичай через volumeClaimTemplates.
  • Послідовне масштабування. Поди стартують і зупиняються по черзі, що зменшує ризик хаосу під час перебудови кластера.

Скорочений фрагмент YAML-файлу для прикладу:

apiVersion: apps/v1

kind: StatefulSet

metadata:

  name: redis

spec:

  serviceName: "redis"

  replicas: 3

  selector:

    matchLabels:

      app: redis

  template:

    metadata:

      labels:

        app: redis

    spec:

      containers:

      - name: redis

        image: redis:latest

        ports:

        - containerPort: 6379

        volumeMounts:

        - name: redis-data

          mountPath: /data

  volumeClaimTemplates:

  - metadata:

      name: redis-data

    spec:

      accessModes: [ "ReadWriteOnce" ]

      resources:

        requests:

          storage: 1Gi

Коли потрібен StatefulSet?

Обирайте StatefulSet, якщо:

  • дані мають пережити перезапуск пода;
  • вузли кластера мають стабільні DNS-імена;
  • важливий порядок старту/зупинки (наприклад, leader/follower).

Типові приклади: PostgreSQL, MySQL, MongoDB, Redis у кластерному режимі, Kafka.

Практичні нюанси, про які часто забувають

  • Service для StatefulSet

    Для коректної роботи StatefulSet зазвичай використовують headless Service. Він забезпечує стабільні DNS-імена для подів і дозволяє сервісам звертатися до них напряму.
  • StorageClass

    У кластері має бути налаштований StorageClass для динамічного створення томів. Якщо його немає, PersistentVolumeClaim не буде прив’язаний до сховища й залишиться в статусі Pending.
  • Доступ до даних

    Режим ReadWriteOnce дозволяє підключати том лише до одного вузла одночасно. Це підходить для більшості баз даних, але обмежує можливість паралельного доступу з кількох вузлів.

Корисні команди:

  • kubectl get statefulsets

Показує список StatefulSet у поточному namespace та їхній поточний стан.

  • kubectl get pvc

Виводить усі PersistentVolumeClaim та їхній статус, зокрема чи прив’язані вони до сховища.

  • kubectl describe pvc <name>

Відображає детальну інформацію про вибраний PVC, включно з подіями та можливими причинами проблем.

DaemonSet: запуск одного пода на кожному вузлі кластера

DaemonSet розв’язує завдання запусти цей под на кожному вузлі кластера. Тут ви не задаєте кількість реплік вручну: скільки вузлів — стільки й подів. Додали новий вузол — под з’явився автоматично.

Де DaemonSet найчастіше використовується?

  • Збір логів (Fluentd, Filebeat), коли потрібно читати файли на вузлі.
  • Моніторинг вузлів (node exporter), щоб бачити метрики системи.
  • Мережеві плагіни (Calico, Cilium) та інші компоненти, які мають бути всюди.

Приклад:

 apiVersion: apps/v1

kind: DaemonSet

metadata:

  name: log-collector

spec:

  selector:

    matchLabels:

      app: log-collector

  template:

    metadata:

      labels:

        app: log-collector

    spec:

      containers:

      - name: log-collector-container

        image: fluentd:latest

        resources:

          limits:

            memory: "200Mi"

            cpu: "100m"

Нюанси DaemonSet, які впливають на безпеку

DaemonSet часто використовує hostPath, тобто отримує доступ до файлової системи вузла. Це нормально для лог-агента, але потребує дисципліни:

  • давайте мінімально необхідні права;
  • уникайте запуску з привілейованим режимом без потреби;
  • контролюйте, на яких вузлах це має працювати (nodeSelector, tolerations).

Як швидко обрати правильний контролер?

Спробуйте пройтися чеклистом:

  1. Застосунок stateless і поди взаємозамінні? Обирайте Deployment.
  2. Потрібні стабільні імена, власні диски, порядок старту? Обирайте StatefulSet.
  3. Потрібно, щоб компонент працював на кожному вузлі? Обирайте DaemonSet.

І ще одна порада з практики: якщо хочеться запустити базу даних у Deployment краще зупинитись. На демо це може пройти, але під час перезапусків ви ризикуєте отримати втрату даних або неконсистентний кластер. Для баз даних у Kubernetes майже завжди доречніший StatefulSet (або керований сервіс у хмарі).

Висновок

У Kubernetes немає універсального контролера для всіх випадків. Кожен тип закладає різні припущення щодо життєвого циклу подів, роботи зі сховищем і взаємодії з вузлами кластера. Якщо ці припущення не збігаються з реальними вимогами застосунку, система починає поводитися непередбачувано під час оновлень, або відновлення після збоїв.

Тому під час проєктування варто виходити не з простоти конфігурації, а з очікуваної поведінки сервісу в продакшні. Саме це визначає, який контролер забезпечить стабільну роботу кластера в довгостроковій перспективі.

Залишити відповідь

Дякуємо, що поділились