Контроллеры в Kubernetes: DaemonSet
DaemonSet гарантирует, что все (или некоторые) узлы запускают копию Pod. Когда узлы добавляются в кластер, к ним добавляются Pod'ы. Когда узлы удаляются из кластера, эти Pod'ы удаляются. Удаление DaemonSet приведет к очистке созданных им Pod'ов.
Некоторые типичные применения DaemonSet:
- запуск демона кластерного хранилища, такого как glusterd, ceph, на каждом узле.
- запуск демона сбора журналов на каждом узле, таком как fluentd или logstash.
- запуск демона мониторинга узла на каждом узле, таком как экспортер узлов Prometheus, агент Sysdig, collectd, Dynatrace OneAgent, агент AppDynamics, агент Datadog, агент New Relic, агент Ganglia gmond или агент Instana.
В простом случае один DaemonSet, охватывающий все узлы, будет использоваться для каждого типа демона. Более сложная установка может использовать несколько DaemonSets для одного типа демона, но с разными флагами и/или разными запросами памяти и процессора для разных типов оборудования.
Написание спецификации 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:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: gcr.io/fluentd-elasticsearch/fluentd:v2.5.1
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
Создайте DaemonSet на основе файла YAML:
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
Обязательные поля
Как и во всех других конфигурациях Kubernetes, для DaemonSet нужны поля apiVersion, kind и metadata.
DaemonSet также нуждается в разделе .spec.
Pod шаблон
.spec.template является одним из обязательных полей в .spec.
.spec.template является шаблоном pod. Он имеет ту же схему, что и Pod, за исключением того, что он вложенный и не имеет apiVersion или kind.
В дополнение к обязательным полям для Pod, шаблон Pod в DaemonSet должен указывать соответствующие метки.
Шаблон Pod в DaemonSet должен иметь RestartPolicy, равный Always, или быть неопределенным, что по умолчанию означает Always.
Pod селектор
Поле .spec.selector является селектором pod. Он работает так же, как .spec.selector для Job.
Начиная с Kubernetes 1.8, вы должны указать селектор pod, который соответствует меткам .spec.template. Селектор pod больше не будет задаваться по умолчанию, если оставить его пустым. Селектор по умолчанию был несовместим с kubectl apply. Кроме того, после создания DaemonSet его .spec.selector не может быть изменен. Отключение селектора Pod'ов может привести к непреднамеренной потере Pod'ами контроллеров.
.spec.selector - это объект, состоящий из двух полей:
- matchLabels - работает так же, как .spec.selector для ReplicationController.
- matchExpressions - позволяет создавать более сложные селекторы, указав ключ, список значений и оператор, который связывает ключ и значения.
Когда они оба указаны, результатом будет их совместная работа (применение их обоих как связанных логическим И).
Если указан .spec.selector, он должен соответствовать .spec.template.metadata.labels. Конфигурация с этими несоответствиями будет отклонена API.
Также вы не должны обычно создавать какие-либо Pod, чьи метки соответствуют этому селектору, либо напрямую, через другой DaemonSet, либо через другой контроллер, такой как ReplicaSet. В противном случае контроллер DaemonSet будет думать, что эти Pod'ы были созданы им. Kubernetes не остановит вас от этого. Один из случаев, когда вам может потребоваться сделать это, - вручную создать Pod с другим значением на узле для тестирования.
Запуск Pod'ов только на некоторых узлах
Если вы укажете .spec.template.spec.nodeSelector, то контроллер DaemonSet будет создавать Pod'ы на узлах, которые соответствуют этому селектору узлов. Аналогично, если вы укажете .spec.template.spec.affinity, то контроллер DaemonSet создаст Pod'ы на узлах, которые соответствуют сходству этого узла. Если вы не укажете ни один из них, контроллер DaemonSet будет создавать Pod'ы на всех узлах.
Как планируются Pod'ы демонов
Запланировано контроллером DaemonSet (по умолчанию отключено с 1.12)
Обычно машина, на которой работает Pod, выбирается планировщиком Kubernetes. Однако для Pod'ов, созданных контроллером DaemonSet, машина уже выбрана (.spec.nodeName указывается при создании Pod'а, поэтому он игнорируется планировщиком). Следовательно:
- unschedulable поле узла не учитывается контроллером DaemonSet.
- Контроллер DaemonSet может создавать Pod, даже если планировщик еще не запущен, что может помочь при загрузке кластера.
Запланировано планировщиком по умолчанию (включен по умолчанию с 1.12)
DaemonSet гарантирует, что все подходящие узлы запускают копию Pod. Обычно узел, на котором работает Pod, выбирается планировщиком Kubernetes. Однако Pod'ы DaemonSet создаются и планируются контроллером DaemonSet. Это создает следующие проблемы:
- Непоследовательное поведение Pod'ов: обычные Pod'ы, ожидающие запланированного создания, создаются и находятся в состоянии ожидания, но Pod'ы DaemonSet не создаются в состоянии ожидания. Это сбивает с толку пользователя.
- Выгрузка Pod'а (Pod preemption) обрабатывается планировщиком по умолчанию. Когда выгрузка включена, контроллер DaemonSet будет принимать решения о планировании без учета приоритета и выгрузки.
ScheduleDaemonSetPods позволяет планировать DaemonSets, используя планировщик по умолчанию вместо контроллера DaemonSet, добавляя термин NodeAffinity в Pod'ы DaemonSet вместо термина .spec.nodeName. Планировщик по умолчанию затем используется для привязки Pod'а к целевому хосту. Если сходство узлов Pod'а DaemonSet уже существует, оно заменяется. Контроллер DaemonSet выполняет эти операции только при создании или изменении Pod'ов DaemonSet, и в шаблон спецификации DaemonSet не вносятся никакие изменения.
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
Кроме того, допуск node.kubernetes.io/unschedulable:NoSchedule автоматически добавляется в Pod'ы DaemonSet. Планировщик по умолчанию игнорирует не подлежащие планированию узлы при планировании Pod'ов DaemonSet.
Пороки и допуски (Taints и Tolerations)
Несмотря на то, что Daemon Pods учитывают пороки и допуски, следующие допуски добавляются в DaemonSet Pods автоматически в соответствии со связанными функциями.
-
- Ключ допуска: node.kubernetes.io/not-ready
- Эффект: NoExecute
- Версия: 1.13+
- Описание: Pod'ы DaemonSet не будут выселены при возникновении проблем с узлами, таких как сетевой раздел.
-
- Ключ допуска: node.kubernetes.io/unreachable
- Эффект: NoExecute
- Версия: 1.13+
- Описание: Pod'ы DaemonSet не будут выселены при возникновении проблем с узлами, таких как сетевой раздел.
-
- Ключ допуска: node.kubernetes.io/disk-pressure
- Эффект: NoSchedule
- Версия: 1.8+
-
- Ключ допуска: node.kubernetes.io/memory-pressure
- Эффект: NoSchedule
- Версия: 1.8+
-
- Ключ допуска: node.kubernetes.io/unschedulable
- Эффект: NoSchedule
- Версия: 1.12+
- Описание: Pod'ы DaemonSet допускают неперестраиваемые атрибуты по умолчанию в планировщике.
-
- Ключ допуска: node.kubernetes.io/network-unavailable
- Эффект: NoSchedule
- Версия: 1.12+
- Описание: Pod'ы DaemonSet, использующие сеть хоста, допускают атрибуты недоступности сети по умолчанию для планировщика.
Общение с Daemon Pod'ами
Вот некоторые возможные шаблоны для взаимодействия с Pod'ами в DaemonSet:
- Push: Pod'ы в DaemonSet настроены для отправки обновлений в другой сервис, такой как база данных статистики. У них нет клиентов.
- NodeIP и известный порт. Pod'ы в DaemonSet могут использовать hostPort, поэтому Pod'ы могут быть доступны через IP-адреса узлов. Клиенты так или иначе знают список IP-адресов узлов и знают порт.
- DNS: создайте автономную службу с тем же селектором pod, а затем обнаружите DaemonSets с помощью ресурса конечных точек (endpoints resource) или получите несколько записей A из DNS.
- Сервис: создайте сервис с тем же селектором Pod и используйте сервис для доступа к демону на случайном узле. (Нет способа добраться до определенного узла.)
Обновление DaemonSet
Если метки узлов изменены, DaemonSet быстро добавит Pod'ы к новым соответствующим узлам и удалит Pod'ы из новых не соответствующих узлов.
Вы можете изменить Pod, который создает DaemonSet. Однако Pod'ы не позволяют обновлять все поля. Кроме того, контроллер DaemonSet будет использовать оригинальный шаблон при следующем создании узла (даже с тем же именем).
Вы можете удалить DaemonSet. Если вы укажете --cascade=false с kubectl, то Pod'ы останутся на узлах. Если впоследствии вы создадите новый DaemonSet с тем же селектором, новый DaemonSet примет существующие Pod'ы. Если какие-либо Pod'ы нуждаются в замене, DaemonSet заменяет их в соответствии с его updateStrategy.
Вы можете выполнить раскатываемое обновление (rolling update) DaemonSet.
Альтернативы DaemonSet
Init скрипты
Безусловно, можно запускать процессы демона, непосредственно запуская их на узле (например, используя init, upstartd или systemd). Это прекрасно. Тем не менее, есть несколько преимуществ для запуска таких процессов через DaemonSet:
- Возможность контролировать и управлять журналами для демонов так же, как приложения.
- Тот же язык конфигурации и инструменты (например, шаблоны Pod, kubectl) для демонов и приложений.
- Запуск демонов в контейнерах с ограничениями ресурсов увеличивает изоляцию между демонами от контейнеров приложений. Однако это также может быть достигнуто путем запуска демонов в контейнере, но не в Pod'е (например, запуск непосредственно через Docker).
Голые Pod'ы
Можно создавать Pod'ы напрямую, которые указывают конкретный узел для запуска. Однако DaemonSet заменяет Pod'ы, которые были удалены или прекращены по любой причине, например, в случае сбоя узла или прерывистого обслуживания узла, например, при обновлении ядра. По этой причине вы должны использовать DaemonSet, а не создавать отдельные Pod'ы.
Статичные Pod'ы
Pod'ы можно создать, записав файл в определенный каталог, который просматривает Kubelet. Это так называемые статичные Pod'ы. В отличие от DaemonSet, статичными Pod'ами нельзя управлять с помощью kubectl или других клиентов API Kubernetes. Статичные Pod'ы не зависят от apiserver, что делает их полезными в случаях начальной загрузки кластера. Однако, в будущем статичные Pod'ы могут быть устаревшими.
Deployment
DaemonSet похожи на Deployment в том, что они оба создают Pod, и у этих Pod есть процессы, которые не должны завершаться (например, веб-серверы, серверы хранения).
Используйте Deployment для сервисов без сохранения состояния, таких как внешние интерфейсы (frontends), где увеличение и уменьшение количества реплик и развертывание обновлений важнее, чем точный контроль того, на каком хосте работает Pod. Используйте DaemonSet, когда важно, чтобы копия Pod'а всегда выполнялась на всех или определенных хостах, а также когда он должен запускаться раньше других Pod'ов.
Читайте также:
- Контроллеры в Kubernetes: Deployment, создание
- Контроллеры в Kubernetes: ReplicaSet
- Контроллеры в Kubernetes: StatefulSet
Комментарии
Отправить комментарий