DaemonSet

DaemonSet определяет Pod'ы, предоставляющие локальные для узла возможности. Они могут быть критически важны для работы кластера, например, сетевой вспомогательный инструмент, или являться частью дополнения.

DaemonSet гарантирует, что на всех (или некоторых) узлах запущена копия Pod'а. При добавлении узлов в кластер Pod'ы автоматически добавляются на них. При удалении узлов из кластера эти Pod'ы удаляются сборщиком мусора. Удаление DaemonSet приведёт к удалению всех созданных им Pod'ов.

Типичные случаи использования DaemonSet:

  • запуск демона кластерного хранилища на каждом узле
  • запуск демона сбора логов на каждом узле
  • запуск демона мониторинга узлов на каждом узле

В простом случае для каждого типа демона используется один DaemonSet, охватывающий все узлы. В более сложных конфигурациях может использоваться несколько DaemonSet для одного типа демона, но с разными флагами и/или разными запросами памяти и CPU для различных типов оборудования.

Написание спецификации DaemonSet

Создание DaemonSet

DaemonSet можно описать в YAML-файле. Например, файл daemonset.yaml ниже описывает DaemonSet, запускающий Docker-образ fluentd-elasticsearch:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # these tolerations are to have the daemonset runnable on control plane nodes
      # remove them if your control plane nodes should not run pods
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v5.0.1
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      # it may be desirable to set a high priority class to ensure that a DaemonSet Pod
      # preempts running Pods
      # priorityClassName: important
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

Создание DaemonSet на основе YAML-файла:

kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml

Обязательные поля

Как и для любой другой конфигурации Kubernetes, DaemonSet требует наличия полей apiVersion, kind и metadata. Общую информацию о работе с конфигурационными файлами см. в разделах запуск stateless-приложений и управление объектами с помощью kubectl.

Имя объекта DaemonSet должно быть допустимым DNS-именем поддомена.

DaemonSet также требует наличия секции .spec.

Шаблон Pod'а

Поле .spec.template является одним из обязательных полей в .spec.

Поле .spec.template представляет собой шаблон Pod'а. Оно имеет точно такую же схему, как и Pod, за исключением того, что является вложенным и не имеет полей apiVersion и kind.

Помимо обязательных полей для Pod'а, шаблон Pod'а в DaemonSet должен указывать соответствующие метки (см. селектор Pod'ов).

Шаблон Pod'а в DaemonSet должен иметь RestartPolicy, равную Always, или быть не указанным, что по умолчанию означает Always.

Селектор Pod'ов

Поле .spec.selector является селектором Pod'ов. Оно работает так же, как .spec.selector у Job.

Необходимо указать селектор Pod'ов, который соответствует меткам в .spec.template. Также, после создания DaemonSet, его .spec.selector не может быть изменён. Изменение селектора Pod'ов может привести к непреднамеренному осиротению Pod'ов, что может запутать пользователей.

Поле .spec.selector представляет собой объект, состоящий из двух полей:

  • matchLabels — работает так же, как .spec.selector у ReplicationController.
  • matchExpressions — позволяет создавать более сложные селекторы, указывая ключ, список значений и оператор, связывающий ключ и значения.

Когда указаны оба поля, результат объединяется по логическому И (AND).

Поле .spec.selector должно соответствовать .spec.template.metadata.labels. Конфигурация с несовпадающими значениями будет отклонена API.

Запуск Pod'ов на выбранных узлах

Если указано поле .spec.template.spec.nodeSelector, контроллер DaemonSet будет создавать Pod'ы на узлах, соответствующих этому селектору узлов. Аналогично, если указано поле .spec.template.spec.affinity, контроллер DaemonSet будет создавать Pod'ы на узлах, соответствующих этой привязке к узлам (node affinity). Если ни одно из полей не указано, контроллер DaemonSet будет создавать Pod'ы на всех узлах.

Как планируются Pod'ы демонов

DaemonSet может использоваться для обеспечения того, чтобы все подходящие узлы запускали копию Pod'а. Контроллер DaemonSet создаёт Pod для каждого подходящего узла и добавляет поле spec.affinity.nodeAffinity в Pod для соответствия целевому хосту. После создания Pod'а обычно управление берёт на себя планировщик по умолчанию, который привязывает Pod к целевому хосту, устанавливая поле .spec.nodeName. Если новый Pod не помещается на узле, планировщик по умолчанию может вытеснить (evict) некоторые из существующих Pod'ов на основе приоритета нового Pod'а.

Пользователь может указать другой планировщик для Pod'ов DaemonSet, установив поле .spec.template.spec.schedulerName у DaemonSet.

Исходная привязка к узлам, указанная в поле .spec.template.spec.affinity.nodeAffinity (если указана), учитывается контроллером DaemonSet при оценке подходящих узлов, но заменяется в созданном Pod'е на привязку к узлу, соответствующую имени подходящего узла.

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

Ограничения (taints) и допуски (tolerations)

Контроллер DaemonSet автоматически добавляет набор допусков (tolerations) к Pod'ам DaemonSet:

Допуски для Pod'ов DaemonSet
Ключ допуска Эффект Описание
node.kubernetes.io/not-ready NoExecute Pod'ы DaemonSet могут планироваться на узлы, которые не готовы или не могут принимать Pod'ы. Любые Pod'ы DaemonSet, работающие на таких узлах, не будут вытеснены.
node.kubernetes.io/unreachable NoExecute Pod'ы DaemonSet могут планироваться на узлы, недоступные для контроллера узлов. Любые Pod'ы DaemonSet, работающие на таких узлах, не будут вытеснены.
node.kubernetes.io/disk-pressure NoSchedule Pod'ы DaemonSet могут планироваться на узлы с проблемами нехватки дискового пространства.
node.kubernetes.io/memory-pressure NoSchedule Pod'ы DaemonSet могут планироваться на узлы с проблемами нехватки памяти.
node.kubernetes.io/pid-pressure NoSchedule Pod'ы DaemonSet могут планироваться на узлы с проблемами нехватки процессов.
node.kubernetes.io/unschedulable NoSchedule Pod'ы DaemonSet могут планироваться на узлы, помеченные как непланируемые.
node.kubernetes.io/network-unavailable NoSchedule Добавляется только для Pod'ов DaemonSet, запрашивающих сеть хоста, т.е. Pod'ов с spec.hostNetwork: true. Такие Pod'ы DaemonSet могут планироваться на узлы с недоступной сетью.

Вы также можете добавить собственные допуски к Pod'ам DaemonSet, определив их в шаблоне Pod'а DaemonSet.

Поскольку контроллер DaemonSet автоматически устанавливает допуск node.kubernetes.io/unschedulable:NoSchedule, Kubernetes может запускать Pod'ы DaemonSet на узлах, помеченных как непланируемые.

Если вы используете DaemonSet для предоставления важной функции уровня узла, такой как сетевое взаимодействие кластера, полезно, что Kubernetes размещает Pod'ы DaemonSet на узлах до того, как они будут готовы. Например, без этого специального допуска вы можете оказаться в тупиковой ситуации, когда узел не помечен как готовый, потому что сетевой плагин там не запущен, и в то же время сетевой плагин не запущен на этом узле, потому что узел ещё не готов.

Взаимодействие с Pod'ами демонов

Некоторые возможные паттерны взаимодействия с Pod'ами в DaemonSet:

  • Push: Pod'ы в DaemonSet настроены на отправку обновлений в другой сервис, например, в базу данных статистики. У них нет клиентов.
  • IP узла и известный порт: Pod'ы в DaemonSet могут использовать hostPort, чтобы быть доступными по IP-адресам узлов. Клиенты каким-либо образом знают список IP-адресов узлов и знают порт по соглашению.
  • DNS: Создайте headless-сервис с тем же селектором Pod'ов, а затем обнаруживайте DaemonSet'ы, используя ресурс endpoints или получая несколько A-записей из DNS.
  • Service: Создайте сервис с тем же селектором Pod'ов и используйте сервис для доступа к демону на случайном узле. Используйте политику внутреннего трафика сервиса (Service Internal Traffic Policy) для ограничения Pod'ами на том же узле.

Обновление DaemonSet

При изменении меток узлов DaemonSet оперативно добавит Pod'ы на узлы, которые теперь соответствуют условиям, и удалит Pod'ы с узлов, которые больше не соответствуют.

Вы можете изменять Pod'ы, созданные DaemonSet. Однако Pod'ы не позволяют обновлять все поля. Кроме того, контроллер DaemonSet будет использовать исходный шаблон при следующем создании узла (даже с тем же именем).

Вы можете удалить DaemonSet. Если указать --cascade=orphan с kubectl, то Pod'ы останутся на узлах. Если впоследствии создать новый DaemonSet с тем же селектором, новый DaemonSet примет существующие Pod'ы. Если какие-либо Pod'ы требуют замены, DaemonSet заменит их в соответствии со своей updateStrategy.

Вы можете выполнить плавное обновление (rolling update) DaemonSet.

Альтернативы DaemonSet

Init-скрипты

Безусловно, можно запускать процессы-демоны напрямую на узле (например, используя init, upstartd или systemd). Это вполне допустимо. Однако есть несколько преимуществ запуска таких процессов через DaemonSet:

  • Возможность мониторинга и управления логами демонов так же, как и приложений.
  • Один и тот же язык конфигурации и инструменты (например, шаблоны Pod'ов, kubectl) для демонов и приложений.
  • Запуск демонов в контейнерах с ограничениями ресурсов повышает изоляцию между демонами и контейнерами приложений. Однако этого также можно достичь, запуская демоны в контейнере, но не в Pod'е.

Обычные Pod'ы (Bare Pods)

Можно создавать Pod'ы напрямую, указывая конкретный узел для запуска. Однако DaemonSet заменяет Pod'ы, которые были удалены или завершены по любой причине, например, в случае сбоя узла или при разрушительном обслуживании узла, таком как обновление ядра. По этой причине следует использовать DaemonSet вместо создания отдельных Pod'ов.

Статические Pod'ы

Можно создавать Pod'ы, записывая файл в определённый каталог, отслеживаемый Kubelet. Такие Pod'ы называются статическими Pod'ами. В отличие от DaemonSet, статическими Pod'ами нельзя управлять с помощью kubectl или других клиентов Kubernetes API. Статические Pod'ы не зависят от apiserver, что делает их полезными в случаях начальной загрузки кластера. Также статические Pod'ы могут быть объявлены устаревшими в будущем.

Deployment'ы

DaemonSet'ы похожи на Deployment'ы тем, что оба создают Pod'ы, и эти Pod'ы содержат процессы, которые не должны завершаться (например, веб-серверы, серверы хранения).

Используйте Deployment для stateless-сервисов, таких как фронтенды, где масштабирование вверх и вниз количества реплик и развёртывание обновлений важнее, чем контроль того, на каком именно хосте запускается Pod. Используйте DaemonSet, когда важно, чтобы копия Pod'а всегда работала на всех или определённых хостах, если DaemonSet предоставляет функциональность уровня узла, позволяющую другим Pod'ам корректно работать на этом конкретном узле.

Например, сетевые плагины часто включают компонент, работающий как DaemonSet. Компонент DaemonSet обеспечивает работу кластерной сети на узле, где он запущен.

Что дальше

Изменено January 19, 2026 at 8:54 PM PST: Translate DaemonSet documentation page to RU (f0eb1d7784)