Часть 12 из серии статей об изучении k8s!
Указатель всей серии
- Основы k8s
- Создать кластер k8s одной командой
- Первое размещение контейнера в k8s
- Зачем нам Pod
- Важные поля конфигурации модуля
- Под проектные объемы
- Проверка работоспособности и восстановление pod-контейнера
- Модель контроллера k8s
- Развертывание k8s
- Топология StatefulSet k8s
- K8s StatefulSet Storage
В моей последней статье я говорил о StatefulSet
состоянии хранилища. Нетрудно обнаружить, что StatefulSet
на самом деле является контейнерной абстракцией существующих типичных операций и обслуживания приложений. StatefulSet
, вероятно, самый сложный объект оркестровки в k8s, и для его освоения потребуется много практики, так что продолжайте практиковаться! Сегодня я представлю DaemonSet
, относительно более простую тему.
DaemonSet
В k8s DaemonSet
гарантирует, что все (или некоторые) узлы запускают копию Pod
. По мере добавления узлов в кластер к ним добавляется Pods
. Когда узлы удаляются из кластера, эти Pods
собираются сборщиком мусора. Удаление DaemonSet
приведет к очистке созданных им модулей. Этот Pod
называется Daemon Pod
.
Примеры использования DaemonSet
Daemon Pod
звучит просто, но это действительно очень важно. Позвольте мне представить вам несколько примеров использования:
- Агент сетевых плагинов должен работать на каждом узле, чтобы обрабатывать сеть контейнеров на этом узле.
- Агент подключаемых модулей хранилища также должен запускаться на каждом узле для монтирования удаленных каталогов хранилища на этом узле и управления каталогом тома контейнера.
- Агент компонентов мониторинга и компонентов журнала также должен работать на каждом узле и отвечать за сбор информации мониторинга и журналов на этом узле.
Что еще более важно, в отличие от других объектов оркестрации, DaemonSet
запускается часто, запускается весь кластер k8s.
Объект API DaemonSet
Давайте начнем понимать это с определения файла YAML:
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: k8s.gcr.io/fluentd-elasticsearch:1.30 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
управляет Pod
зеркальным отображением fluentd-elasticsearch. Функция этого образа очень проста: журналы в контейнере Docker перенаправляются в ElasticSearch через fluentd.
Как видите, DaemonSet
на самом деле очень похож на Deployment
, за исключением того, что здесь нет поля реплик; он также использует селектор для выбора и управления всеми модулями, имеющими метку name=fluentd-elasticsearch
.
Шаблоны этих Pods
также определяются с помощью поля шаблона. В этом поле мы определяем контейнер, который использует образ fluentd-elasticsearch:1.30
, и этот контейнер монтирует два тома типа hostPath, соответствующие каталогу /var/log
и каталогу /var/lib/docker/containers
хоста.
После запуска fluentd он соберет информацию журнала из этих двух каталогов и отправит ее в ElasticSearch для хранения. Таким образом, мы можем легко получить эти журналы через ElasticSearch.
Контроллер DaemonSet
Вы можете задаться вопросом, как DaemonSet обеспечивает наличие одного и только одного управляемого модуля на каждом узле? Это делается через DeamonSet Controller.
DaemonSet Controller
сначала получает все списки узлов из Etcd, а затем просматривает все узлы. В это время он может легко проверить, есть ли Pod, несущий тег name=fluentd-elasticsearch
, работающий в данный момент на этом узле.
Есть три возможности:
- Нет такого типа Pod, это означает, что такой Pod должен быть создан на этом узле.
- Если такой модуль есть, но его число больше 1, это означает, что избыточный модуль должен быть удален с этого узла.
- Есть ровно один такой
Pod
, значит, этот узел в норме.
Удалить Pod
легко, просто вызовите API k8s напрямую, но для создания нового Pod
на данном узле DaemonSet Controller
автоматически добавит определение nodeAffinity к объекту API Pod
при создании Pod
. Среди них имя узла, который необходимо связать, - это узел, который в настоящее время просматривается.
Конечно, DaemonSet
не нужно изменять шаблон Pod
в файле YAML, представленном пользователем, а напрямую изменять объект Pod
, сгенерированный в соответствии с шаблоном, перед отправкой запроса к k8s. Вдобавок DaemonSet
автоматически добавит в это Pod
другое поле, связанное с расписанием, которое называется tolerations
. Это поле означает, что этот модуль будет «терпеть» некоторую «порчу» узла.
Образец файла tolerations
:
apiVersion: v1 kind: Pod metadata: name: with-toleration spec: tolerations: - key: node.kubernetes.io/unschedulable operator: Exists effect: NoSchedule
Значение этого допуска: «терпеть» все узлы, помеченные как не подлежащие планированию «заражение»; эффект «толерантности» состоит в том, чтобы разрешить планирование.
При нормальных обстоятельствах для узла, помеченного неуправляемым «пятном», не будет никаких Pod
запланированных (эффект: NoSchedule). Однако DaemonSet
автоматически добавляет это специальное значение допуска к управляемому Pods
, чтобы эти Pods
могли игнорировать это ограничение, а затем гарантировать, что Pod
будет запланировано на каждом узле. Конечно, если узел выходит из строя, Pod
может не запуститься, и DaemonSet
всегда будет пытаться, пока Pod
не запустится успешно.
В настоящее время вы должны догадаться, что «трюк» с DaemonSet
на самом деле достигается за счет использования терпимости.
В k8s, когда сетевой плагин узла не был установлен, узел автоматически будет «испорчен» с именем node.kubernetes.io/network-unavailable
.
Если текущий DaemonSet
manages - это сетевой подключаемый модуль Agent Pod, тогда вы должны добавить шаблон Pod, который может «терпеть» node.kubernetes.io/network-unavailable
«taint» в YAML-файле этого DaemonSet:
... template: metadata: labels: name: network-plugin-agent spec: tolerations: - key: node.kubernetes.io/network-unavailable operator: Exists effect: NoSchedule
С таким допуском планировщик игнорирует «пятно» на текущем узле при планировании Pod
и успешно планирует запуск компонента агента сетевого подключаемого модуля для этой машины.
Этот механизм является фундаментальной причиной, по которой мы можем сначала развернуть сам k8s, а затем развернуть сетевой плагин.
Теперь вы должны хорошо понимать, что DaemonSet
на самом деле очень простой контроллер. В своем цикле управления ему нужно только пройти все узлы, а затем решить, создать или удалить Pod
, в зависимости от того, есть ли управляемый Pod
на узле.
Пример DeamonSet
Прежде всего, давайте создадим объект DaemonSet
:
$ kubectl create -f fluentd-es.yaml
После создания вы можете увидеть, что запущены два модуля.
$ kubectl get pod -n kube-system -l name=fluentd-elasticsearch NAME READY STATUS RESTARTS AGE fluentd-elasticsearch-xxxxx 1/1 Running 0 53m fluentd-elasticsearch-xxxxx 1/1 Running 0 53m $ kubectl get ds -n kube-system fluentd-elasticsearch NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluentd-elasticsearch 2 2 2 2 2 <none> 1h
Вы можете видеть, что, как и Deployment
, DaemonSet
также имеет несколько полей статуса, таких как DESIRED и CURRENT. Это также означает, что DaemonSet
может выполнять управление версиями, как Deployment
. В этой версии вы можете использовать kubectl rollout history
для проверки:
$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-system daemonsets "fluentd-elasticsearch" REVISION CHANGE-CAUSE 1 <none>
Теперь давайте обновим нашу DaemonSet
версию образа:
$ kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --record -n=kube-system
Давайте проверим статус непрерывного обновления:
$ kubectl rollout status ds/fluentd-elasticsearch -n kube-system Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 0 out of 2 new pods have been updated... Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 0 out of 2 new pods have been updated... Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 1 of 2 updated pods are available... daemon set "fluentd-elasticsearch" successfully rolled out
После этого давайте проверим историю:
$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-system daemonsets "fluentd-elasticsearch" REVISION CHANGE-CAUSE 1 <none> 2 kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --namespace=kube-system --record=true
Можно попробовать откатить на Revision=1
$ kubectl rollout undo daemonset fluentd-elasticsearch --to-revision=1 -n kube-system daemonset.extensions/fluentd-elasticsearch rolled back
Конечно, вы можете удалить DaemonSet
:
$ kubectl delete daemonset fluentd-elasticsearch
Заключение
В этой статье я сосредоточился на третьем важном объекте оркестровки k8s: DaemonSet
. По сравнению с Deployment
, DaemonSet
управляет только Pod
объектами, а затем с помощью небольших функций двух планировщиков, nodeAffinity
и Toleration
, он обеспечивает наличие только одного модуля на каждом узле.
Надеюсь, вам понравилась эта статья, и увидимся в следующей!
Больше контента на plainenglish.io