DaemonSet Kubernetes: примеры, настройка и манифест для запуска Pod на каждом узле | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

DaemonSet Kubernetes: примеры, настройка и манифест для запуска Pod на каждом узле

28 мая 2026 7 мин. чтения

Что такое DaemonSet и когда его использовать

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

Типичные сценарии применения включают агенты сбора логов, такие как Fluentd или Filebeat, системы мониторинга вроде Prometheus node-exporter, сетевые плагины (Calico, Cilium) и драйверы хранилищ. Эти сервисы выполняют фоновые задачи уровня операционной системы узла.

DaemonSet vs Deployment: сравнительная таблица и правило выбора

Ошибка выбора контроллера ведет к неоптимальной архитектуре. Используйте простое правило: DaemonSet для сервисов, привязанных к узлу, Deployment для масштабируемых сервисов, независимых от узлов.

Параметр DaemonSet Deployment
Цель Запуск Pod на каждом узле Управление набором идентичных Pod
Связь с узлами Прямая, один Pod на узел Косвенная, Pod размещаются по доступности ресурсов
Масштабирование Автоматически по числу узлов Ручное или через HPA
Типовой use-case Агенты логирования, мониторинга Веб-приложения, API, микросервисы

Попытка использовать Deployment для задач уровня узла, например для сбора логов с каждой ноды, приведет к ручному управлению количеством реплик и сложностям с гарантированным покрытием всех узлов.

Для более глубокого сравнения всех типов контроллеров Kubernetes, включая StatefulSet и Job, обратитесь к нашему практическому руководству: Выбор контроллера Kubernetes: Deployment, StatefulSet, DaemonSet и Job.

Создание базового DaemonSet: готовый манифест и его применение

Для создания DaemonSet используется YAML-манифест. Ниже приведен минимальный рабочий пример для версии Kubernetes 1.30 (apiVersion: apps/v1).

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
  namespace: default
spec:
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["sh", "-c", "sleep 3600"]
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1

Ключевые секции манифеста:

  • apiVersion: Для DaemonSet всегда используйте apps/v1.
  • spec.selector: Должен соответствовать меткам в spec.template.metadata.labels.
  • spec.template: Определяет Pod, который будет запущен на каждом узле.
  • updateStrategy: Задает стратегию обновления Pod. По умолчанию RollingUpdate.

Чтобы применить манифест и проверить статус, выполните команды:

kubectl apply -f daemonset.yaml
kubectl get daemonset -n default
kubectl get pods -l app=example-app -o wide

Команда kubectl get pods -o wide покажет, что Pod запущен на каждом узле кластера. Для работы с более сложными манифестами Pod и Deployment изучите основы их структуры в нашем практическом гайде по манифестам Kubernetes.

Управление размещением Pod: запуск DaemonSet не на всех узлах

Часто требуется запускать системный сервис не на всех узлах, а только на master-нодах, узлах с GPU или с определенной меткой. Для этого Kubernetes предоставляет три механизма: nodeSelector, nodeAffinity и Tolerations.

nodeSelector: базовый выбор узлов по меткам

Это самый простой метод. Сначала добавьте метку узлу:

kubectl label node <node-name> node-type=monitoring

Затем укажите эту метку в секции spec.template.spec манифеста DaemonSet:

spec:
  template:
    spec:
      nodeSelector:
        node-type: monitoring
      containers:
      - name: monitoring-agent
        image: prom/node-exporter:latest

Pod будет запущен только на узлах с меткой node-type=monitoring. Метод nodeSelector подходит для простых правил, но не поддерживает операторы типа «или», «не равно».

nodeAffinity и Tolerations: продвинутый контроль размещения

nodeAffinity предлагает более гибкие правила. Например, можно требовать запуск на узлах с определенной меткой или предпочитать узлы с GPU.

spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: node-role.kubernetes.io/master
                operator: Exists
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: accelerator
                operator: In
                values:
                - gpu

Этот пример требует запуска на master-узлах (метка node-role.kubernetes.io/master) и предпощает узлы с меткой accelerator=gpu.

Tolerations работают в паре с Taints (загрязнениями узлов). Если узел имеет taint, Pod без соответствующего toleration на нем не запустится. Это полезно для выделения узлов под специфичные задачи.

Допустим, узел помечен taint: kubectl taint nodes node1 dedicated=monitoring:NoSchedule. Чтобы DaemonSet мог на нем работать, добавьте tolerations:

spec:
  template:
    spec:
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "monitoring"
        effect: "NoSchedule"

Теперь Pod сможет быть запланирован на узле node1.

Практические примеры: развертывание системных агентов

DaemonSet для мониторинга: развертывание node-exporter

Prometheus node-exporter – стандартный инструмент для сбора метрик с узлов. Его развертывание через DaemonSet идеально.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: metrics
        securityContext:
          runAsNonRoot: true
          runAsUser: 65534
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
        - name: root
          mountPath: /host/root
          readOnly: true
        args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        - --path.rootfs=/host/root
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys
      - name: root
        hostPath:
          path: /

Ключевые моменты:

  • hostPath: Позволяет контейнеру получать доступ к системным директориям хоста (/proc, /sys).
  • securityContext: Запуск от непривилегированного пользователя (nobody, UID 65534) повышает безопасность.
  • hostNetwork: true: Позволяет Pod использовать сетевой стек хоста, что упрощает доступ к метрикам по порту 9100 напрямую с узла.

DaemonSet для логирования: пример с Fluentd

Для сбора логов со всех контейнеров и системных журналов используйте агент вроде Fluentd.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
        - name: FLUENT_ELASTICSEARCH_HOST
          value: "elasticsearch.logging.svc.cluster.local"
        resources:
          limits:
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: fluentd-config
          mountPath: /fluentd/etc
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: fluentd-config
        configMap:
          name: fluentd-config

Этот DaemonSet монтирует директории логов хоста (/var/log, /var/lib/docker/containers) и отправляет логи в Elasticsearch. Tolerations разрешают запуск на master-узлах, которые часто имеют taint NoSchedule. Для управления подобными production-приложениями ознакомьтесь с полным руководством по Deployment в Kubernetes.

Обновление и управление жизненным циклом DaemonSet

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

Стратегии обновления: RollingUpdate vs OnDelete

DaemonSet поддерживает две стратегии обновления, задаваемые в spec.updateStrategy.type:

  • RollingUpdate (по умолчанию): Kubernetes автоматически, по одному, удаляет старые Pod и создает новые на каждом узле. Параметр maxUnavailable определяет максимальное число Pod, которые могут быть недоступны во время обновления. Это предпочтительная стратегия для минимизации простоя.
  • OnDelete: Обновление происходит только после ручного удаления Pod пользователем. Kubernetes не создает новые Pod автоматически. Эта стратегия подходит для критичных сервисов, где обновление требует дополнительных проверок.

Пошаговый алгоритм безопасного обновления и отката

  1. Проверка текущего состояния. Убедитесь, что все Pod в рабочем состоянии: kubectl get daemonset -o wide && kubectl get pods -l app=<ваше_приложение>.
  2. Изменение манифеста. Отредактируйте YAML-файл: обновите версию образа (image: my-agent:v2.1) или конфигурацию.
  3. Применение изменений. Выполните команду: kubectl apply -f daemonset.yaml.
  4. Мониторинг процесса. Отслеживайте прогресс обновления: kubectl rollout status daemonset/<имя-daemonset>. Команда kubectl get pods -w покажет, как Pod пересоздаются на узлах.
  5. Откат в случае проблем. Если новая версия работает некорректно, выполните откат к предыдущей ревизии: kubectl rollout undo daemonset/<имя-daemonset>.

Важный нюанс: обновление происходит узел за узлом. На каждом узле старый Pod будет удален только после того, как новый Pod перейдет в состояние Ready (если определены readinessProbe). Всегда проверяйте корректность синтаксиса YAML перед применением. Ошибки в отступах или структуре могут заблокировать обновление. Рекомендации по написанию безошибочных манифестов собраны в нашем руководстве по синтаксису YAML для Kubernetes.

Резюме и лучшие практики

DaemonSet – специализированный инструмент для развертывания системных сервисов уровня узла. Следуйте этим практикам для надежной работы:

  • Используйте DaemonSet для агентов логирования, мониторинга, сетевых плагинов и драйверов хранилищ.
  • Контролируйте размещение Pod с помощью nodeSelector для простых правил и nodeAffinity/Tolerations для сложных сценариев (например, работа на master-узлах или нодах с GPU).
  • Для обновления в production предпочитайте стратегию RollingUpdate с настройкой maxUnavailable.
  • Всегда задавайте securityContext для контейнеров, особенно при использовании hostPath. Запускайте от непривилегированного пользователя, где это возможно.
  • Определяйте запросы и лимиты ресурсов (requests/limits) для Pod DaemonSet, чтобы они не конфликтовали с основными приложениями.
  • Перед применением манифестов в production проверяйте их в тестовой среде. Актуальный синтаксис всегда сверяйте с официальной документацией Kubernetes.

DaemonSet решает четкий круг задач. Правильное его применение упрощает управление инфраструктурой кластера. Для комплексного подхода к администрированию Linux и Kubernetes-сред изучите наш сборник практических руководств для DevOps.

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