Восстановление при ошибках

В процессе работы DKP автоматически создает резервные копии конфигурации и данных, которые могут пригодиться в случае возникновения проблем. Эти резервные копии сохраняются в директории /etc/kubernetes/deckhouse/backup. Если в процессе работы возникли ошибки или непредвиденные ситуации, вы можете использовать эти резервные копии для восстановления до предыдущего исправного состояния.

Восстановление работоспособности кластера etcd

Если кластер etcd не функционирует и не удается восстановить его из резервной копии, вы можете попытаться восстановить его с нуля, следуя шагам ниже.

  1. Сначала на всех узлах, которые являются частью вашего кластера etcd, кроме одного, удалите манифест etcd.yaml, который находится в директории /etc/kubernetes/manifests/. После этого только один узел останется активным, и с него будет происходить восстановление состояния мультимастерного кластера.
  2. На оставшемся узле откройте файл манифеста etcd.yaml и укажите параметр --force-new-cluster в spec.containers.command.
  3. После успешного восстановления кластера, удалите параметр --force-new-cluster.

Эта операция является деструктивной, так как она полностью уничтожает текущие данные и инициализирует кластер с состоянием, которое сохранено на узле. Все pending-записи будут утеряны.

Восстановление master-узла при ошибке загрузки компонентов control plane через kubelet

Ситуация, когда kubelet не может загрузить компоненты control plane, может возникнуть, если в кластере с одним master-узлом был удалён каталог с образами (например, /var/lib/containerd). В этом случае после перезапуска kubelet не сможет загрузить образы компонентов control plane, поскольку параметры авторизации для доступа к registry.deckhouse.io на master-узле отсутствуют.

Далее приведена инструкция по восстановлению master-узла.

containerd

  1. Для восстановления работоспособности master-узла нужно в любом рабочем кластере под управлением DKP выполнить команду:

    d8 k -n d8-system get secrets deckhouse-registry -o json |
    jq -r '.data.".dockerconfigjson"' | base64 -d |
    jq -r '.auths."registry.deckhouse.io".auth'
    
  2. Скопируйте вывод команды и присвойте переменной AUTH на поврежденном master-узле.

  3. Далее на поврежденном master-узле загрузите образы компонентов control plane:

    for image in $(grep "image:" /etc/kubernetes/manifests/* | awk '{print $3}'); do
      crictl pull --auth $AUTH $image
    done
    
  4. После загрузки образов перезапустите kubelet.

Восстановление etcd

Просмотр списка узлов кластера в etcd

Способ 1

Используйте команду etcdctl member list.

Пример:

for pod in $(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name); do
  d8 k -n kube-system exec "$pod" -- 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
  if [ $? -eq 0 ]; then
    break
  fi
done

Внимание. Последний параметр в таблице вывода показывает, что узел находится в состоянии learner, а не в состоянии leader.

Способ 2

Используйте команду etcdctl endpoint status. Для лидера в столбце IS LEADER будет указано значение true.

Пример:

for pod in $(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name); do
  d8 k -n kube-system exec "$pod" -- 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 --cluster -w table
  if [ $? -eq 0 ]; then
    break
  fi
done

Восстановление кластера etcd при полной недоступности

  1. Остановите все узлы etcd, кроме одного, удалив манифест etcd.yaml на остальных.
  2. На оставшемся узле добавьте в команду etcd параметр --force-new-cluster.
  3. После восстановления удалите этот флаг.

Будьте осторожны: эти действия полностью уничтожают предыдущие данные и формируют новый кластер etcd.

Восстановление etcd при ошибке panic: unexpected removal of unknown remote peer

В некоторых случаях помогает ручное восстановление через etcdutl snapshot restore:

  1. Сохраните локальный снапшот /var/lib/etcd/member/snap/db.
  2. Воспользуйтесь etcdutl с опцией --force-new-cluster.
  3. Полностью очистите /var/lib/etcd и положите туда восстановленный снапшот.
  4. Удалите «зависшие» контейнеры etcd / kube-apiserver, перезапустите узел.

Действия при переполнении базы данных etcd (превышение quota-backend-bytes)

Когда объем базы данных etcd достигает лимита, установленного параметром quota-backend-bytes, доступ к ней становится read-only. Это означает, что база данных etcd перестает принимать новые записи, но при этом остается доступной для чтения данных. Вы можете понять, что столкнулись с подобной ситуацией, выполнив команду:

d8 k -n kube-system exec -ti $(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name | sed -n 1p) -- \
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 --cluster

Если в поле ERRORS вы видите подобное сообщение alarm:NOSPACE, значит вам нужно предпринять следующие шаги:

  1. Найдите строку с --quota-backend-bytes в файле манифеста пода etcd, расположенного по пути /etc/kubernetes/manifests/etcd.yaml и увеличьте значение, умножив указанный параметр в этой строке на два. Если такой строки нет — добавьте, например: - --quota-backend-bytes=8589934592. Эта настройка задает лимит на 8 ГБ.
  2. Сбросьте активное предупреждение (alarm) о нехватке места в базе данных. Для этого выполните следующую команду:

    d8 k -n kube-system exec -ti $(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name | sed -n 1p) -- \
    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/ alarm disarm
    
  3. Измените параметр maxDbSize в настройках модуля control-plane-manager на тот, который был задан в манифесте.

Дефрагментация etcd

Перед дефрагментацией создайте резервную копию etcd.

Для просмотра размера БД etcd на определенном узле перед дефрагментацией и после ее выполнения используйте команду (здесь NODE_NAME — имя master-узла):

d8 k -n kube-system exec -it etcd-NODE_NAME -- /usr/bin/etcdctl \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  endpoint status --cluster -w table

Пример вывода (размер БД etcd на узле указывается в колонке DB SIZE):

+-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
|          ENDPOINT           |        ID        | VERSION | STORAGE VERSION | DB SIZE | IN USE | PERCENTAGE NOT IN USE | QUOTA  | IS LEADER  | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | DOWNGRADE TARGET VERSION | DOWNGRADE ENABLED |
+-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
| https://192.168.199.80:2379 | 489a8af1e7acd7a0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |       true |      false |        56 |  258054684 |          258054684 |        |                          |             false |
+-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
| https://192.168.199.81:2379 | 589a8ad1e7ccd7b0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |      false |      false |        56 |  258054685 |          258054685 |        |                          |             false |
+-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
| https://192.168.199.82:2379 | 229a8cd1e7bcd7a0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |      false |      false |        56 |  258054685 |          258054685 |        |                          |             false |
+-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+

Как выполнить дефрагментацию etcd узла в кластере с одним master-узлом

Дефрагментация etcd — ресурсоемкая операция, которая на время полностью блокирует работу etcd на данном узле. Учитывайте это при выборе времени для проведения операции в кластере с одним master-узлом.

Чтобы выполнить дефрагментацию etcd в кластере с одним master-узлом, используйте следующую команду (здесь NODE_NAME — имя master-узла):

d8 k -n kube-system exec -ti etcd-NODE_NAME -- /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/ defrag --command-timeout=30s

Пример вывода при успешном выполнении операции:

Finished defragmenting etcd member[https://localhost:2379]. took 848.948927ms

При появлении ошибки из-за таймаута увеличивайте значение параметра –command-timeout из команды выше, пока дефрагментация не выполнится успешно.

Как выполнить дефрагментацию etcd в кластере с несколькими master-узлами

Чтобы выполнить дефрагментацию etcd в кластере с несколькими master-узлами:

  1. Получите список подов etcd. Для этого используйте следующую команду:

    d8 k -n kube-system get pod -l component=etcd -o wide
    

    Пример вывода:

    NAME           READY    STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
    etcd-master-0   1/1     Running   0          3d21h   192.168.199.80  master-0    <none>           <none>
    etcd-master-1   1/1     Running   0          3d21h   192.168.199.81  master-1    <none>           <none>
    etcd-master-2   1/1     Running   0          3d21h   192.168.199.82  master-2    <none>           <none>
    
  2. Определите master-узел — лидер. Для этого обратитесь к любому поду etcd и получите список узлов — участников кластера etcd с помощью команды (где NODE_NAME — имя master-узла):

    d8 k -n kube-system exec -it etcd-NODE_NAME -- /usr/bin/etcdctl \
      --cert=/etc/kubernetes/pki/etcd/server.crt \
      --key=/etc/kubernetes/pki/etcd/server.key \
      --cacert=/etc/kubernetes/pki/etcd/ca.crt \
      endpoint status --cluster -w table
    

    Пример вывода (у лидера в колонке IS LEADER будет значение true):

    +-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
    |          ENDPOINT           |        ID        | VERSION | STORAGE VERSION | DB SIZE | IN USE | PERCENTAGE NOT IN USE | QUOTA  | IS LEADER  | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | DOWNGRADE TARGET VERSION | DOWNGRADE ENABLED |
    +-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
    | https://192.168.199.80:2379 | 489a8af1e7acd7a0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |       true |      false |        56 |  258054684 |          258054684 |        |                          |             false |
    +-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
    | https://192.168.199.81:2379 | 589a8ad1e7ccd7b0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |      false |      false |        56 |  258054685 |          258054685 |        |                          |             false |
    +-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
    | https://192.168.199.82:2379 | 229a8cd1e7bcd7a0 |   3.6.1 |           3.6.0 |   76 MB |  62 MB |                   20% | 2.1 GB |      false |      false |        56 |  258054685 |          258054685 |        |                          |             false |
    +-----------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+------------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
    
  3. Поочередно выполните дефрагментацию etcd узлов — участников etcd кластера. Для дефрагментации используйте команду (здесь NODE_NAME — имя master-узла):

    Важно: дефрагментацию лидера необходимо выполнять в последнюю очередь.

    Восстановление etcd на узле после дефрагментации может занять некоторое время. Рекомендуется подождать не менее минуты прежде чем переходить к дефрагментации etcd следующего узла.

    d8 k -n kube-system exec -ti etcd-NODE_NAME -- /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/ defrag --command-timeout=30s
    

    Пример вывода при успешном выполнении операции:

    Finished defragmenting etcd member[https://localhost:2379]. took 848.948927ms
    

    При появлении ошибки из-за таймаута увеличивайте значение параметра –command-timeout из команды выше, пока дефрагментация не выполнится успешно.

Отказоустойчивость

Если какой-либо компонент control plane становится недоступным, кластер временно сохраняет текущее состояние, но не может обрабатывать новые события. Например:

  • При сбое kube-controller-manager перестаёт работать масштабирование deployment’ов.
  • При недоступности kube-apiserver невозможны любые запросы к Kubernetes API, но уже запущенные приложения продолжают функционировать.

Однако при продолжительной недоступности компонентов нарушается обработка новых объектов, реакция на сбои узлов и другие процессы. Со временем это может привести к деградации работы кластера и повлиять на пользовательские приложения.

Чтобы снизить такие риски, следует масштабировать control plane до отказоустойчивой конфигурации — минимум трёх узлов. Это особенно критично для etcd, так как он требует наличия кворума для выбора лидера. Кворум работает по принципу большинства (N/2 + 1) от общего числа узлов.

Пример:

Размер кластера Большинство Максимальные потери
1 1 0
3 2 1
5 3 2
7 4 3
9 5 4

Чётное число узлов не даёт преимущества по отказоустойчивости, но увеличивает накладные расходы на репликацию.

В большинстве случаев достаточно трёх узлов etcd, пять — если критична устойчивость. Более семи — крайне редко и не рекомендуется из-за высокой нагрузки.

После добавления новых узлов control plane:

  • Устанавливается лейбл node-role.kubernetes.io/control-plane="".
  • DaemonSet запускает поды на новых узлах.
  • DKP создает или обновляет файлы в /etc/kubernetes: манифесты, конфигурации, сертификаты и т.д.
  • Все модули DKP с поддержкой отказоустойчивости автоматически включают её, если значение глобальной настройки highAvailability не переопределено вручную.

Удаление узлов control plane выполняется в обратном порядке:

  • Удаляются лейблы node-role.kubernetes.io/control-plane, node-role.kubernetes.io/master, node.deckhouse.io/group.
  • DKP удаляет свои поды с этих узлов.
  • Члены etcd, расположенные на этих узлах, удаляются автоматически.
  • Если число узлов уменьшается с двух до одного, etcd может перейти в статус readonly. В этом случае требуется запуск с параметром --force-new-cluster, который следует убрать после успешного запуска.