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

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

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

Что такое 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.

FAQ: частые вопросы по DaemonSet

Как ограничить DaemonSet только на определенных узлах?

Используйте nodeSelector для простых правил или nodeAffinity для сложных условий. Например, чтобы запускать DaemonSet только на узлах с меткой node-type=monitoring, добавьте соответствующую секцию в spec.template.spec. Для исключения узлов с taint применяйте Tolerations.

Чем DaemonSet отличается от Deployment?

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

Можно ли обновить DaemonSet без простоя?

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

Зачем нужны Tolerations в DaemonSet?

Tolerations позволяют Pod запускаться на узлах с taint. Например, master-узлы часто имеют taint NoSchedule, который запрещает размещение обычных Pod. Добавив соответствующий toleration, вы разрешите DaemonSet работать на таких узлах.

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