Что такое DaemonSet и когда его использовать
DaemonSet – это контроллер Kubernetes, который гарантирует запуск и поддержку копии вашего Pod на каждом узле кластера. Его основная задача – развертывание системных сервисов, тесно связанных с инфраструктурой узла. Если ваш сервис должен быть представлен на каждом узле и взаимодействует с его ресурсами, вы используете DaemonSet.
Типичные сценарии применения включают агенты сбора логов, такие как Fluentd или Filebeat, системы мониторинга вроде Prometheus node-exporter, сетевые плагины (Calico, Cilium) и драйверы хранилищ. Эти сервисы выполняют фоновые задачи уровня операционной системы узла.
Содержание
- Что такое DaemonSet и когда его использовать
- DaemonSet vs Deployment: сравнительная таблица и правило выбора
- Создание базового DaemonSet: готовый манифест и его применение
- Управление размещением Pod: запуск DaemonSet не на всех узлах
- Практические примеры: развертывание системных агентов
- Обновление и управление жизненным циклом DaemonSet
- Резюме и лучшие практики
- FAQ: частые вопросы по DaemonSet
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 автоматически. Эта стратегия подходит для критичных сервисов, где обновление требует дополнительных проверок.
Пошаговый алгоритм безопасного обновления и отката
- Проверка текущего состояния. Убедитесь, что все Pod в рабочем состоянии:
kubectl get daemonset -o wide && kubectl get pods -l app=<ваше_приложение>. - Изменение манифеста. Отредактируйте YAML-файл: обновите версию образа (
image: my-agent:v2.1) или конфигурацию. - Применение изменений. Выполните команду:
kubectl apply -f daemonset.yaml. - Мониторинг процесса. Отслеживайте прогресс обновления:
kubectl rollout status daemonset/<имя-daemonset>. Командаkubectl get pods -wпокажет, как Pod пересоздаются на узлах. - Откат в случае проблем. Если новая версия работает некорректно, выполните откат к предыдущей ревизии:
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 работать на таких узлах.