Как добавить master-узел в статичном или гибридном кластере?
Важно иметь нечётное количество мастеров для обеспечения кворума.
Добавление master-узла в статичный или гибридный кластер ничем не отличается от добавления обычного узла в кластер. Воспользуйтесь для этого соответствующей инструкцией. Все необходимые действия по настройке компонентов control plane кластера на новом узле будут выполнены автоматически, дождитесь их завершения — появления master-узлов в статусе Ready
.
Как добавить master-узлы в облачном кластере (single-master в multi-master)?
Перед добавлением узлов убедитесь в наличии необходимых квот.
Важно иметь нечётное количество мастеров для обеспечения кворума.
- Сделайте резервную копию
etcd
и папки/etc/kubernetes
. - Скопируйте полученный архив за пределы кластера (например, на локальную машину).
- Убедитесь, что в кластере нет алертов которые могут помешать созданию новых master-узлов.
-
На локальной машине запустите контейнер установщика Deckhouse соответствующей редакции и версии (измените адрес container registry при необходимости):
DH_VERSION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/version}') \ DH_EDITION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/edition}' | tr '[:upper:]' '[:lower:]' ) \ docker run --pull=always -it -v "$HOME/.ssh/:/tmp/.ssh/" \ registry.deckhouse.io/deckhouse/${DH_EDITION}/install:${DH_VERSION} bash
-
В контейнере с инсталлятором выполните следующую команду, чтобы проверить состояние перед началом работы:
dhctl terraform check --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> --ssh-host <MASTER-NODE-0-HOST>
Ответ должен сообщить вам, что Terraform не хочет ничего менять.
-
В контейнере с инсталлятором выполните следующую команду и укажите требуемое количество реплик в параметре
masterNodeGroup.replicas
:dhctl config edit provider-cluster-configuration --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST>
-
В контейнере с инсталлятором выполните следующую команду для запуска масштабирования:
dhctl converge --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> --ssh-host <MASTER-NODE-0-HOST>
-
Дождитесь появления необходимого количества master-узлов в статусе
Ready
и готовности всех экземпляровcontrol-plane-manager
:kubectl -n kube-system wait pod --timeout=10m --for=condition=ContainersReady -l app=d8-control-plane-manager
Как уменьшить число master-узлов в облачном кластере (multi-master в single-master)?
- Сделайте резервную копию
etcd
и папки/etc/kubernetes
. - Скопируйте полученный архив за пределы кластера (например, на локальную машину).
- Убедитесь, что в кластере нет алертов которые могут помешать обновлению master-узлов.
-
На локальной машине запустите контейнер установщика Deckhouse соответствующей редакции и версии (измените адрес container registry при необходимости):
DH_VERSION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/version}') \ DH_EDITION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/edition}' | tr '[:upper:]' '[:lower:]' ) \ docker run --pull=always -it -v "$HOME/.ssh/:/tmp/.ssh/" \ registry.deckhouse.io/deckhouse/${DH_EDITION}/install:${DH_VERSION} bash
-
В контейнере с инсталлятором выполните следующую команду и укажите
1
в параметреmasterNodeGroup.replicas
:dhctl config edit provider-cluster-configuration --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> \ --ssh-user=<USERNAME> --ssh-host <MASTER-NODE-0-HOST>
- Снимите следующие лейблы с удаляемых master-узлов:
node-role.kubernetes.io/control-plane
node-role.kubernetes.io/master
node.deckhouse.io/group
Команда для снятия лейблов:
kubectl label node <MASTER-NODE-N-NAME> node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master- node.deckhouse.io/group-
-
Убедитесь, что удаляемые master-узлы пропали из списка членов кластера etcd:
kubectl -n kube-system exec -ti $(kubectl -n kube-system get pod -l component=etcd,tier=control-plane -o name | head -n1) -- sh -c \ "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key \ --endpoints https://127.0.0.1:2379/ member list -w table"
-
Выполните drain для удаляемых узлов:
kubectl drain <MASTER-NODE-N-NAME> --ignore-daemonsets --delete-emptydir-data
-
Выключите виртуальные машины, соответствующие удаляемым узлам, удалите инстансы соответствующих узлов из облака и подключенные к ним диски (
kubernetes-data-master-<N>
). -
Удалите в кластере Pod’ы, оставшиеся на удаленных узлах:
kubectl delete pods --all-namespaces --field-selector spec.nodeName=<MASTER-NODE-N-NAME> --force
-
Удалите в кластере объекты Node удаленных узлов:
kubectl delete node <MASTER-NODE-N-NAME>
-
В контейнере с инсталлятором выполните следующую команду для запуска масштабирования:
dhctl converge --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> --ssh-host <MASTER-NODE-0-HOST>
Как убрать роль master-узла, сохранив узел?
- Сделайте резервную копию
etcd
и папки/etc/kubernetes
. - Скопируйте полученный архив за пределы кластера (например, на локальную машину).
- Убедитесь, что в кластере нет алертов которые могут помешать обновлению master-узлов.
- Снимите лейблы
node.deckhouse.io/group: master
иnode-role.kubernetes.io/control-plane: ""
. -
Убедитесь, что удаляемый master-узел пропал из списка членов кластера etcd:
kubectl -n kube-system exec -ti $(kubectl -n kube-system get pod -l component=etcd,tier=control-plane -o name | head -n1) -- sh -c \ "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key \ --endpoints https://127.0.0.1:2379/ member list -w table"
-
Зайдите на узел и выполните следующие команды:
rm -f /etc/kubernetes/manifests/{etcd,kube-apiserver,kube-scheduler,kube-controller-manager}.yaml rm -f /etc/kubernetes/{scheduler,controller-manager}.conf rm -f /etc/kubernetes/authorization-webhook-config.yaml rm -f /etc/kubernetes/admin.conf /root/.kube/config rm -rf /etc/kubernetes/deckhouse rm -rf /etc/kubernetes/pki/{ca.key,apiserver*,etcd/,front-proxy*,sa.*} rm -rf /var/lib/etcd/member/
Как изменить образ ОС в multi-master-кластере?
- Сделайте резервную копию
etcd
и папки/etc/kubernetes
. - Скопируйте полученный архив за пределы кластера (например, на локальную машину).
- Убедитесь, что в кластере нет алертов которые могут помешать обновлению master-узлов.
-
На локальной машине запустите контейнер установщика Deckhouse соответствующей редакции и версии (измените адрес container registry при необходимости):
DH_VERSION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/version}') \ DH_EDITION=$(kubectl -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/edition}' | tr '[:upper:]' '[:lower:]' ) \ docker run --pull=always -it -v "$HOME/.ssh/:/tmp/.ssh/" \ registry.deckhouse.io/deckhouse/${DH_EDITION}/install:${DH_VERSION} bash
-
В контейнере с инсталлятором выполните следующую команду, чтобы проверить состояние перед началом работы:
dhctl terraform check --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST>
Ответ должен сообщить вам, что Terraform не хочет ничего менять.
-
В контейнере с инсталлятором выполните следующую команду и укажите необходимый образ ОС в параметре
masterNodeGroup.instanceClass
(укажите адреса всех master-узлов в параметре--ssh-host
):dhctl config edit provider-cluster-configuration --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST>
Следующие действия выполняйте поочередно на каждом master-узле, начиная с узла с наивысшим номером (с суффиксом 2) и заканчивая узлом с наименьшим номером (с суффиксом 0).
-
Выберите master-узел для обновления (укажите его название):
NODE="<MASTER-NODE-N-NAME>"
-
Выполните следующую команду для снятия лейблов
node-role.kubernetes.io/control-plane
,node-role.kubernetes.io/master
,node.deckhouse.io/group
с узла:kubectl label node ${NODE} \ node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master- node.deckhouse.io/group-
-
Убедитесь, что узел пропал из списка членов кластера etcd:
kubectl -n kube-system exec -ti $(kubectl -n kube-system get pod -l component=etcd,tier=control-plane -o json | jq -r '.items[] | select( .status.conditions[] | select(.type == "ContainersReady" and .status == "True")) | .metadata.name') -- sh -c \ "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key \ --endpoints https://127.0.0.1:2379/ member list -w table"
-
Выполните
drain
для узла:kubectl drain ${NODE} --ignore-daemonsets --delete-emptydir-data
-
Выключите виртуальную машину, соответствующую узлу, удалите инстанс узла из облака и подключенные к нему диски (kubernetes-data).
-
Удалите в кластере Pod’ы, оставшиеся на удаляемом узле:
kubectl delete pods --all-namespaces --field-selector spec.nodeName=${NODE} --force
-
Удалите в кластере объект Node удаленного узла:
kubectl delete node ${NODE}
-
В контейнере с инсталлятором выполните следующую команду для создания обновленного узла:
Вам нужно внимательно прочитать, что converge собирается делать, когда запрашивает одобрение.
Если converge запрашивает одобрение для другого мастер-узла, его следует пропустить, выбрав “no”.
dhctl converge --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST>
-
На созданном узле посмотрите журнал systemd-unit’а
bashible.service
. Дождитесь окончания настройки узла — в журнале появится сообщениеnothing to do
:journalctl -fu bashible.service
-
Убедитесь, что узел появился в списке членов кластера etcd:
kubectl -n kube-system exec -ti $(kubectl -n kube-system get pod -l component=etcd,tier=control-plane -o json | jq -r '.items[] | select( .status.conditions[] | select(.type == "ContainersReady" and .status == "True")) | .metadata.name') -- sh -c \ "ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key \ --endpoints https://127.0.0.1:2379/ member list -w table"
-
Убедитесь, что
control-plane-manager
функционирует на узле.kubectl -n kube-system wait pod --timeout=10m --for=condition=ContainersReady \ -l app=d8-control-plane-manager --field-selector spec.nodeName=${NODE}
-
Перейдите к обновлению следующего узла.
Как изменить образ ОС в single-master-кластере?
-
Преобразуйте single-master-кластер в multi-master в соответствии с инструкцией.
Помимо увеличения числа реплик вы можете сразу указать образ с необходимой версией ОС в параметре
masterNode.instanceClass
. - Обновите master-узлы в соответствии с инструкцией.
- Преобразуйте multi-master-кластер в single-master в соответствии с инструкцией
Как посмотреть список member’ов в etcd?
Вариант 1
-
Зайдите в Pod с etcd:
kubectl -n kube-system exec -ti $(kubectl -n kube-system get pod -l component=etcd,tier=control-plane -o name | head -n1) sh
-
Выполните команду:
ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/ca.crt \ --key /etc/kubernetes/pki/etcd/ca.key --endpoints https://127.0.0.1:2379/ member list -w table
Внимание! Последний параметр в таблице вывода показывает, что член etcd находится в состоянии learner, а не в состоянии leader.
Вариант 2
Используйте команду etcdctl endpoint status
. Пятый параметр в таблице вывода будетtrue
у лидера.
Пример:
$ ETCDCTL_API=3 etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/ca.crt \
--key /etc/kubernetes/pki/etcd/ca.key --endpoints https://127.0.0.1:2379/ endpoint status -w table
https://10.2.1.101:2379, ade526d28b1f92f7, 3.5.3, 177 MB, false, false, 42007, 406566258, 406566258,
https://10.2.1.102:2379, d282ac2ce600c1ce, 3.5.3, 182 MB, true, false, 42007, 406566258, 406566258,
Что делать, если что-то пошло не так?
В процессе работы control-plane-manager оставляет резервные копии в /etc/kubernetes/deckhouse/backup
, они могут помочь.
Что делать, если кластер etcd развалился?
- Остановите (удалите
/etc/kubernetes/manifests/etcd.yaml
) etcd на всех узлах, кроме одного. С него начнётся восстановление multi-master’а. - На оставшемся узле в манифесте
/etc/kubernetes/manifests/etcd.yaml
укажите параметр--force-new-cluster
вspec.containers.command
. - После успешного подъёма кластера удалите параметр
--force-new-cluster
.
Внимание! Операция деструктивна, она полностью уничтожает консенсус и запускает etcd кластер с состояния, которое сохранилось на узле. Любые pending записи пропадут.
Как настроить дополнительные политики аудита?
-
Включите параметр auditPolicyEnabled в настройках модуля:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: control-plane-manager spec: version: 1 settings: apiserver: auditPolicyEnabled: true
-
Создайте Secret
kube-system/audit-policy
с файлом политик, закодированным вbase64
:apiVersion: v1 kind: Secret metadata: name: audit-policy namespace: kube-system data: audit-policy.yaml: <base64>
Минимальный рабочий пример
audit-policy.yaml
выглядит так:apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata omitStages: - RequestReceived
Подробную информацию по настройке содержимого
audit-policy.yaml
можно получить по следующим ссылкам:
Как исключить встроенные политики аудита?
Установите параметр apiserver.basicAuditPolicyEnabled модуля в false
.
Пример:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: control-plane-manager
spec:
version: 1
settings:
apiserver:
auditPolicyEnabled: true
basicAuditPolicyEnabled: false
Как вывести аудит-лог в стандартный вывод вместо файлов?
Установите параметр apiserver.auditLog.output модуля в значение Stdout
.
Пример:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: control-plane-manager
spec:
version: 1
settings:
apiserver:
auditPolicyEnabled: true
auditLog:
output: Stdout
Как работать с журналом аудита?
Предполагается наличие на master-узлах «скрейпера логов» (log-shipper, promtail, filebeat), который будет следить за файлом с логами:
/var/log/kube-audit/audit.log
Параметры ротации файла журнала предустановлены и их изменение не предусмотрено:
- Максимальное занимаемое место на диске
1000 Мб
. - Максимальная глубина записи
7 дней
.
В зависимости от настроек Policy
и количества запросов к apiserver логов может быть очень много, соответственно глубина хранения может быть менее 30 минут.
Предостережение
Внимание! Текущая реализация функционала не является безопасной с точки зрения возможности временно сломать control plane.
Если в Secret’е с конфигурационным файлом окажутся неподдерживаемые опции или опечатка, то apiserver не сможет запуститься.
В случае возникновения проблем с запуском apiserver потребуется вручную отключить параметры --audit-log-*
в манифесте /etc/kubernetes/manifests/kube-apiserver.yaml
и перезапустить apiserver следующей командой:
docker stop $(docker ps | grep kube-apiserver- | awk '{print $1}')
# Или (в зависимости используемого вами CRI).
crictl stopp $(crictl pods --name=kube-apiserver -q)
После перезапуска будет достаточно времени исправить Secret или удалить его:
kubectl -n kube-system delete secret audit-policy
Как ускорить перезапуск Pod’ов при потере связи с узлом?
По умолчанию, если узел за 40 секунд не сообщает своё состояние — он помечается как недоступный. И еще через 5 минут Pod’ы узла начнут перезапускаться на других узлах. Итоговое время недоступности приложений около 6 минут.
В специфических случаях, когда приложение не может быть запущено в нескольких экземплярах, есть способ сократить период их недоступности:
- Уменьшить время перехода узла в состояние
Unreachable
при потере с ним связи настройкой параметраnodeMonitorGracePeriodSeconds
. - Установить меньший таймаут удаления Pod’ов с недоступного узла в параметре
failedNodePodEvictionTimeoutSeconds
.
Пример
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: control-plane-manager
spec:
version: 1
settings:
nodeMonitorGracePeriodSeconds: 10
failedNodePodEvictionTimeoutSeconds: 50
В этом случае при потере связи с узлом, приложения будут перезапущены через ~ 1 минуту.
Предостережение
Оба описанных параметра оказывают непосредственное влияние на потребляемые control-plane’ом ресурсы процессора и памяти. Уменьшая таймауты, мы заставляем системные компоненты чаще производить отправку статусов и сверки состояний ресурсов.
В процессе подбора подходящих вам значений обращайте внимание на графики потребления ресурсов управляющих узлов. Будьте готовы к тому, что чем меньшие значения параметров вы выбираете, тем больше ресурсов может потребоваться выделить на эти узлы.
Резервное копирование etcd и восстановление
Как сделать бекап etcd?
Войдите на любой control-plane узел под пользователем root
и используйте следующий bash-скрипт:
#!/usr/bin/env bash
for pod in $(kubectl get pod -n kube-system -l component=etcd,tier=control-plane -o name); do
if kubectl -n kube-system exec "$pod" -- sh -c "ETCDCTL_API=3 /usr/bin/etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key --endpoints https://127.0.0.1:2379/ snapshot save /tmp/${pod##*/}.snapshot" && \
kubectl -n kube-system exec "$pod" -- gzip -c /tmp/${pod##*/}.snapshot | zcat > "${pod##*/}.snapshot" && \
kubectl -n kube-system exec "$pod" -- sh -c "cd /tmp && sha256sum ${pod##*/}.snapshot" | sha256sum -c && \
kubectl -n kube-system exec "$pod" -- rm "/tmp/${pod##*/}.snapshot"; then
mv "${pod##*/}.snapshot" etcd-backup.snapshot
break
fi
done
cp -r /etc/kubernetes/ ./
tar -cvzf kube-backup.tar.gz ./etcd-backup.snapshot ./kubernetes/
rm -r ./kubernetes
В текущей директории будет создан файл etcd-backup.snapshot
со снимком базы etcd одного из членов etcd-кластера.
Из полученного снимка можно будет восстановить состояние кластера etcd.
Также рекомендуем сделать бекап директории /etc/kubernetes
в которой находятся:
- манифесты и конфигурация компонентов control-plane;
- PKI кластера Kubernetes. Данная директория поможет быстро восстановить кластер при полной потери control-plane узлов без создания нового кластера и без повторного присоединения узлов в новый кластер.
Мы рекомендуем хранить резервные копии снимков состояния кластера etcd, а также бекап директории /etc/kubernetes/
в зашифрованном виде вне кластера Deckhouse.
Для этого вы можете использовать сторонние инструменты резервного копирования файлов, например: Restic, Borg, Duplicity и т.д.
О возможных вариантах восстановления состояния кластера из снимка etcd вы можете узнать здесь.
Как восстановить объект Kubernetes из резервной копии etcd?
Чтобы получить данные определенных объектов кластера из резервной копии etcd:
- Запустите временный экземпляр etcd.
- Наполните его данными из резервной копии.
- Получите описания нужных объектов с помощью
etcdhelper
.
Пример шагов по восстановлению объектов из резервной копии etcd
В примере далее, etcd-snapshot.bin
— резервная копия etcd (snapshot), infra-production
— namespace, в котором нужно восстановить объекты.
- Запустите Под, с временным экземпляром etcd.
-
Подготовьте файл
etcd.pod.yaml
шаблона Пода, выполнив следующий команды:cat <<EOF >etcd.pod.yaml apiVersion: v1 kind: Pod metadata: name: etcdrestore namespace: default spec: containers: - command: - /bin/sh - -c - "sleep 96h" image: IMAGE imagePullPolicy: IfNotPresent name: etcd volumeMounts: - name: etcddir mountPath: /default.etcd volumes: - name: etcddir emptyDir: {} EOF IMG=`kubectl -n kube-system get pod -l component=etcd -o jsonpath="{.items[*].spec.containers[*].image}" | cut -f 1 -d ' '` sed -i -e "s#IMAGE#$IMG#" etcd.pod.yaml
-
Создайте Под:
kubectl create -f etcd.pod.yaml
-
-
Скопируйте
etcdhelper
и снимок etcd в контейнер Пода.etcdhelper
можно собрать из исходного кода или скопировать из готового образа (например из образаetcdhelper
на Docker Hub).Пример:
kubectl cp etcd-snapshot.bin default/etcdrestore:/tmp/etcd-snapshot.bin kubectl cp etcdhelper default/etcdrestore:/usr/bin/etcdhelper
-
В контейнере установите права на запуск
etcdhelper
, восстановите данные из резервной копии и запустите etcd.Пример:
~ # kubectl -n default exec -it etcdrestore -- sh / # chmod +x /usr/bin/etcdhelper / # etcdctl snapshot restore /tmp/etcd-snapshot.bin / # etcd &
-
Получите описания нужных объектов кластера, отфильтровав их с помощью
grep
.Пример:
~ # kubectl -n default exec -it etcdrestore -- sh / # mkdir /tmp/restored_yaml / # cd /tmp/restored_yaml /tmp/restored_yaml # for o in `etcdhelper -endpoint 127.0.0.1:2379 ls /registry/ | grep infra-production` ; do etcdhelper -endpoint 127.0.0.1:2379 get $o > `echo $o | sed -e "s#/registry/##g;s#/#_#g"`.yaml ; done
Замена символов с помощью
sed
в примере позволяет сохранить описания объектов в файлы, именованные подобно структуре реестра etcd. Например:/registry/deployments/infra-production/supercronic.yaml
→deployments_infra-production_supercronic.yaml
. -
Скопируйте полученные описания объектов на master-узел:
kubectl cp default/etcdrestore:/tmp/restored_yaml restored_yaml
-
Удалите из полученных описаний объектов информацию о времени создания, UID, status и прочие оперативные данные, после чего восстановите объекты:
kubectl create -f restored_yaml/deployments_infra-production_supercronic.yaml
-
Удалите Под с временным экземпляром etcd:
kubectl -n default delete pod etcdrestore
Как выбирается узел, на котором будет запущен Pod?
За распределение Pod’ов по узлам отвечает планировщик Kubernetes (компонент scheduler
).
У него есть 2 фазы — Filtering и Scoring (на самом деле их больше, и есть еще pre-filtering / post-filtering, но глобально можно свести к двум фазам).
Общее устройство планировщика Kubernetes
Планировщик состоит из плагинов, которые работают в рамках какой-либо фазы (фаз).
Примеры плагинов:
- ImageLocality — отдает предпочтение узлам, на которых уже есть образы контейнеров, которые используются в запускаемом Pod’е. Фаза: Scoring
- TaintToleration — реализует механизм taints and tolerations. Фазы: Filtering, Scoring
- NodePorts — проверяет, есть ли у узла свободные порты, необходимые для запуска Pod’а. Фаза: Filtering
Полный список плагинов можно посмотреть в документации Kubernetes.
Логика работы
Сначала идет фаза фильтрации (Filtering). В этот момент работают filter
-плагины, которые из всего списка узлов выбирают те, которые попадают под условия фильтров (taints
, nodePorts
, nodeName
, unschedulable
, и т. д.). Если узлы лежат в разных зонах, то при выборе зоны чередуются, чтобы не размещать все Pod’ы в одной зоне.
Предположим, что узлы распределяются по зонам следующим образом:
Zone 1: Node 1, Node 2, Node 3, Node 4
Zone 2: Node 5, Node 6
В этом случае они будут выбираться в следующем порядке:
Node 1, Node 5, Node 2, Node 6, Node 3, Node 4
Обратите внимание, что с целью оптимизации выбираются не все попадающие под условия узлы, а только их часть. По умолчанию функция выбора количества узлов линейная. Для кластера из ≤ 50 узлов будут выбраны 100% узлов, для кластера из 100 узлов — 50%, а для кластера из 5000 узлов — 10%. Минимальное значение — 5% при количестве узлов более 5000. Таким образом, при настройках по умолчанию узел может не попасть в список возможных узлов для запуска. Эту логику можно изменить (см. подробнее про параметр percentageOfNodesToScore
в документации Kubernetes), но Deckhouse не дает такой возможности.
После того как выбраны узлы, подходящие под условия, запускается фаза Scoring. Каждый плагин анализирует список отфильтрованных узлов и назначает оценку (score) каждому узлу. Оценки от разных плагинов суммируются. На этой фазе оцениваются доступные ресурсы на узлах, pod capacity, affinity, volume provisioning, и так далее. По итогам этой фазы выбирается узел с наибольшей оценкой. Если сразу несколько узлов получили максимальную оценку, узел выбирается случайным образом.
В итоге Pod запускается на выбранном узле.