Как восстановить работу кластера etcd из резервной копии
В РОСА Кубис можно создать резервную копию etcd с помощью объекта NCI. Резервное копирование данных кластера etcd может понадобиться для восстановления кластера. Рекомендуется выполнять резервное копирования в период наименьшей нагрузки на кластер.
Создание резервной копии etcd
Для создания резервной копии etcd нужно:
- подготовить скрипт для резервного копирования, например, с именем etcdbackup.sh. Пример скрипта etcdbackup.sh:
#!/bin/sh
Проверка запуска из-под root
if [[ $EUID -ne 0 ]]; then
echo "This script must berun as root"
exit 1
fi
Проверка установки etcdctl для выполнения резервного копирования
if which etcdctl > /dev/null; then
echo etcdctl found
else
fi
function usage {
echo 'Path to backup dir required: ./cluster-backup.sh <path-to-backup-dir>'
exit 1
}
If the first argument is missing, or it is an existing file, then print usage and exit
if [ -z "$1" ] || [ -f "$1" ]; then
usage
fi
Проверка существования манифестов
function checkManifests {
echo 'No manifsts found in /etc/kubernetes/manifests'
exit 1
}
if [ -z "$(ls /etc/kubernetes/manifests/)" ];then
checkManifests
fi
function checkStatus () {
status=$?
if test $status -eq 0
then
echo "passed $1"
else
echo "failed $1"
exit 1
fi
}
Объявление переменных
archive="$(hostname)-$(date '+%F_%H%M%S').tar.gz" # Имя резервной копии etcd
backupdate="$1/backup/" # Расположение резервной копии etcd
mkdir -p $backupdate/manifests # Директория для резервной копии манифестов etcd
mkdir -p $backupdate/etcd # Директория для резервной копии etcd
Получение данных для подключения и создание резервной копии (snapshot)
etcdCTL_API=3 \
etcdCTL_CACERT='/etc/kubernetes/pki/etcd/ca.crt' \
etcdCTL_CERT='/etc/kubernetes/pki/etcd/server.crt' \
etcdCTL_KEY='/etc/kubernetes/pki/etcd/server.key' \
etcdCTL_ENDPOINTS='https://XX.XX.XX.XX:2379' \
/usr/local/bin/etcdctl snapshot save $backupdate/etcd/etcd.snapshot ;
checkStatus "etcd backup"
cp -r /etc/kubernetes/manifests/* $backupdate/manifests/
checkStatus "Create copies of static manifests"
echo "Manifests saved at $backupdate/manifests"
Бэкапирование secrets_encryption.yaml необходимо для кластеров с расширенными параметрами безопасности (secure=true)
cp /etc/kubernetes/secrets_encryption.yaml $backupdate/etcd/ >/dev/null 2>&1
echo "Create copies of secrets_encryption.yaml"
echo "Archiving backup...."
tar -zcf $1/$archive $backupdate 2> /dev/null
checkStatus "archiving file"
echo "Backup archiving finished"
chmod 666 $1/$archive
echo "Backup archive is located in $1/archive"
Удаление архивов с резервной копией старше 3-х дней
find /tmp/ -name "*.tar.gz" -mtime +3 -delete
checkStatus "removing old backups"
echo Backup finished
exit 0
- в графическом интерфейсе кластера открыть страницу "Конфигурация узлов" раздела "Администрирование", нажать + Добавить NCI. На странице добавления NCI:
- задать имя, например etcdbackup, и в селекторе узлов из выпадающего списка выбрать ключ лейбла node-role.kubernetes.io/control-plane. Значение для лейбла не устанавливать.
- в блоке "Настраиваемые разделы" выбрать "Файлы и директории" и "Пакеты для установки", нажать Продолжить **(**рисунок 129);
- в открывшемся окне на шаге конфигурации раздела "Пакеты для установки" нажать + и указать пакет etcdhelper (рисунок 130), выбрать целевое состояние пакета Present (рисунок 131);
- нажать Добавить и затем Продолжить, чтобы перейти к разделу "Файлы и директории";
- на шаге "Файлы и директории" нажать + и в поле "Путь к файлу или директории" прописать путь до создаваемого файла со скриптом резервного копирования. В типе файла/директории должно быть выбрано "Файл";
- в поле права доступа указать необходимые права, например 0755, что обеспечит владельцу полный доступ к файлу, группе владельца, другим пользователям ‒ доступ на чтение и выполнение. Владелец и группа должны быть root;
- в поле "Содержимое файла" вставить содержимое подготовленного скрипта из файла etcdbackup.sh, нажать Добавить **(**рисунки 132‒133);
- нажать + и в поле "Путь к файлу или директории" прописать путь до файла с расписанием запуска резервного копирования;
- в поле права доступа указать необходимые права, например 0600, что обеспечит правами только владельца файла на чтение и запись. (владелец и группа должны быть root);
- в поле "Содержимое файла" указать конфигурацию запуска резервного копирования: расписание в cron-формате, путь до файла со скриптом и путь до создаваемой резервной копии etcd. В поле "Содержимое файла" после записи конфигурации запуска требуется выполнить перенос строки;
- нажать Добавить (рисунки 134‒135).
Следует обратить внимание**, что р**екомендуется хранить резервную копию etcd в сетевой файловой системе не на Control Plane-узлах, а, например, в /nfs/share. Это может быть полезным в случае недоступности Control Plane-узлов.
Пример конфигурации запуска:
bash Terminal 30 18 * * * /opt/etcdbackup.sh /tmp/
- нажать Завершить. Пример NCI:

Рисунок 129 ‒ Блок "Настраиваемые разделы"

Рисунок 130 ‒ Указание пакетов

Рисунок 131 ‒ Выбор целевого пакета

Рисунок 132 ‒ Раздел "Файлы и директории"

Рисунок 133 ‒ Добавленный скрипт

Рисунок 134 ‒ Добавление скрипта

Рисунок 135 ‒ Добавленный скрипт
apiVersion: node.shturval.tech/v1beta2
kind: NodeConfigItem
metadata:
annotations:
shturval.tech/name: etcdbackup
finalizers:
‒ node.shturval.tech/finalizer
name: etcdbackup
spec:
packages:
‒ name: etcdhelper
state: present
files:
‒ content: |
#!/bin/sh
if [[ $EUID -ne 0 ]]; then
echo "This script must berun as root"
exit 1
fi
if which etcdctl > /dev/null; then
echo etcdctl found
else
echo etcdctl not found
fi
function usage {
echo 'Path to backup dir required: ./cluster-backup.sh <path-to-backup-dir>'
exit 1
}
If the first argument is missing, or it is an existing file, then print usage and exit
if [ -z "$1" ] || [ -f "$1" ]; then
usage
fi
function checkManifests {
echo 'No manifsts found in /etc/kubernetes/manifests'
exit 1
}
if [ -z "$(ls /etc/kubernetes/manifests/)" ];then
checkManifests
fi
function checkStatus () {
status=$?
if test $status -eq 0
then
echo "passed $1"
else
echo "failed $1"
exit 1
fi
}
archive="$(hostname)-$(date '+%F_%H%M%S').tar.gz"
backupdate="$1/backup/"
mkdir -p $backupdate/manifests
mkdir -p $backupdate/etcd
etcdCTL_API=3 \
etcdCTL_CACERT='/etc/kubernetes/pki/etcd/ca.crt' \
etcdCTL_CERT='/etc/kubernetes/pki/etcd/server.crt' \
etcdCTL_KEY='/etc/kubernetes/pki/etcd/server.key' \
etcdCTL_ENDPOINTS='https://XX.XX.XX.XX:2379' \
/usr/local/bin/etcdctl snapshot save $backupdate/etcd/etcd.snapshot ;
checkStatus "etcd backup"
cp -r /etc/kubernetes/manifests/* $backupdate/manifests/
checkStatus "Create copies of static manifests"
echo "Manifests saved at $backupdate/manifests"
cp /etc/kubernetes/secrets_encryption.yaml $backupdate/etcd/ >/dev/null 2>&1
echo "Create copies of secrets_encryption.yaml"
echo "Archiving backup...."
tar -zcf $1/$archive $backupdate 2> /dev/null
checkStatus "archiving file"
echo "Backup archiving finished"
chmod 666 $1/$archive
echo "Backup archive is located in $1/archive"
find /tmp/ -name "*.tar.gz" -mtime +3 -delete
checkStatus "removing old backups"
echo Backup finished
exit 0
group: root
mode: "0755"
owner: root
path: /opt/etcdbackup.sh
type: file
‒ content: "30 18 * * * /opt/etcdbackup.sh /tmp/"
group: root
mode: "0600"
owner: root
path: /var/spool/cron/root
type: file
nodeconfigselector:
node-role.kubernetes.io/control-plane: "
priority: 100
В результате успешного выполнения скрипта по расписанию для каждого Control Plane-узла будет создана резервная копия etcd.
Восстановить резервную копию etcd
Чтобы восстановить из резервной копии etcd, для каждого Control Plane-узла необходимо выполнить восстановление:
- на Control Plane-узле переместить манифест пода с именем файла kube-apiserver.yaml из etc/kubernetes/manifests/ в другую папку, например /root, чтобы остановить работу API-сервера. После перемещения необходимо дождаться удаления пода (результат команды — на рисунке 136):
Перемещение пода в папку /root/
mv /etc/kubernetes/manifests/kube-apiserver.yaml /root/
Получение информации о поде API-сервера
crictl ps | grep api
2. выполнить восстановление из резервной копии etcd (результат — на рисунке 137):
export etcdCTL_API=3
/usr/local/bin/etcdctl --data-dir /var/lib/etcd snapshot restore /tmp/backup/etcd/etcd.snapshot
где вместо /var/lib/etcd указать каталог, который будет создан в процессе восстановления резервной копии etcd, а вместо /tmp/backup/etcd/etcd.snapshot ‒ путь до резервной копии. Следует обратить внимание**, что, е**сли указывается каталог /var/lib/etcd, нужно удалить его до выполнения восстановления из резервной копии etcd. Важно ‒ В случае восстановления etcd на Control Plane-узлах нового созданного кластера необходимо восстановить secrets_encryption.yaml из архива. Сохранение secrets_encryption.yaml требуется для кластеров с расширенными параметрами безопасности (secure=true):
cp status/backup/etcd/secrets_encryption.yaml /etc/kubernetes/
где вместо status/backup/etcd/secrets_encryption.yaml указать путь до сохраненного файла secrets_encryption.yaml. 3. перезапустить под API-сервера, переместив файл kube-apiserver.yaml обратно в etc/kubernetes/manifests/ на узле (результат — на рисунке ):
mv /root/kube-apiserver.yaml /etc/kubernetes/manifests/
Получение информации о поде API-сервера
crictl ps | grep api
Рекомендуется** п**ерезапустить kube-scheduler, kube-controller-manager на Control Plane-узлах. Для этого нужно поочередно переместить файлы с манифестами в папку root, проверить, что под удален, после чего вернуть манифест обратно в /etc/kubernetes/manifests/.
Команда перезапуска kube-scheduler:
Перемещение пода в папку /root/
mv /etc/kubernetes/manifests/kube-scheduler.yaml /root/
Получение информации о поде kube-scheduler. дождаться удаления пода
crictl ps | grep scheduler
Возвращение пода kube-scheduler
mv /root/kube-scheduler.yaml /etc/kubernetes/manifests/
Команда перезапуска kube-controller-manager:
Перемещение пода в папку /root/
mv /etc/kubernetes/manifests/kube-controller-manager.yaml /root/
Получение информации о поде kube-controller-manager. дождаться удаления пода
crictl ps | grep controller
Возвращение пода kube-controller-manager
mv /root/kube-controller-manager.yaml /etc/kubernetes/manifests/
Затем следует перезапустить kubelet:
sudo systemctl restart kubelet
sudo systemctl status kubelet

Рисунок 136 ‒ Результат команды

Рисунок 137 ‒ Результат команды

Рисунок 138 ‒ Результат команды
Восстановление работы кластера etcd с помощью etcd-helper
Установка модуля
Восстановление работы кластера etcd с помощью модуля etcd-helper возможно только в высокодоступном кластере (HA):
- при недоступности узла кластера etcd;
- при изменении IP-адреса Control Plane узла;
- при изменении IP-адресов всех Control Plane узлов. Для начала работы с модулем:
- установить пакет с модулем etcd-helper, содержащий утилиты edtcdctl, etcdutl, etcdhelper:
yum install etcdhelper
Модуль etcd-helper будет загружен в /usr/local/bin (****рисунок 139).

Рисунок 139 ‒ Загузка модуля etcd-helper
- чтобы выполнить запрос к кластеру etcd, запустить etcdctl с необходимыми параметрами, с помощью команды etcdhelper exec. Требуемые параметры будут получены из /etc/kubernetes/manifests/etcd.yaml. Команда (результат — на рисунке 140):
/usr/local/bin/etcdhelper exec -- member list -w table
где параметр "--" необходим для корректной передачи ключей в скрипте.

Рисунок 140 ‒ Результат команды
Восстановление недоступного узла кластера etcd
Если IP-адрес и имя API-сервера не изменились, но на Control Plane-узле повреждены данные, нужно пересоздать узел в кластере etcd, выполнив команду (результат — на рисунке 141):
/usr/local/bin/etcdhelper rejoin

Рисунок 141 ‒ Результат команды

Рисунок 141 ‒ Результат команды
Важно ‒ Если контейнер etcd на узле в статусе "Running", то команда etcdhelper rejoin не может быть выполнена.
В результате выполнения команды произойдет:
- удаление нерабочего узла из кластера etcd;
- остановка Kubelet;
- удаление контейнера etcd;
- переименование каталога с данными etcd;
- добавление нового узла в кластер etcd;
- запуск Kubelet.
Восстановление при изменении IP-адреса Control Plane-узла
Если IP-адрес одного из Control Plane-узлов изменен, то можно восстановить работу кластера etcd, использовав команду (результат — на рисунке 142):
/usr/local/bin/etcdhelper ip --nodeip=ВВЕДИТЕ-НОВЫЙ-IP-АДРЕС-УЗЛА

Рисунок 142 ‒ Результат команды

Рисунок 142 ‒ Результат команды
В результате команды будет выполнено:
- резервное копирование манифестов и сертификатов;
- изменение IP-адреса узла в манифестах;.
- удаление сертификатов etcd, за исключением сертификата CA;
- генерация сертификатов, в том числе для API-сервера;
- изменение IP-адреса узла в кластере etcd.
Восстановление при изменении IP-адресов всех Control Plane-узлов
Для восстановления работоспособности кластера etcd нужно последовательно выполнить действия:
- на первом Control Plane-узле выполнить команду для подготовки конфигурации после смены IP:
/usr/local/bin/etcdhelper prepare --nodeip=ВВЕДИТЕ-НОВЫЙ-IP-АДРЕС-УЗЛА
- добавить опцию --force-new-cluster в манифест /etc/kubernetes/manifests/etcd.yaml;
- перезагрузить первый Control Plane-узел;
- отредактировать запись об узле в кластере etcd:
Посмотреть ID узла
/usr/local/bin/etcdhelper exec -- member list -w table
Обновить запись об узле
/usr/local/bin/etcdhelper exec -- member update ВВЕДИТЕ-ID-УЗЛА --peer-urls=https://ВВЕДИТЕ-НОВЫЙ-IP-АДРЕС-УЗЛА:2380
- удалить опцию --force-new-cluster из манифеста /etc/kubernetes/manifests/etcd.yaml;
- перезагрузить первый узел;
- убедиться, что кластер Kubernetes работает;
- при восстановлении кластера управления убедиться, что все поды в неймспейсе shturval-backend запущены. Если shturval-backend-redis или shturval-backend-valkey не запущены, выполнить принудительное удаление для перезапуска;
- при восстановлении кластера (клиентского, управления) с провайдером Shturval v2 подготовить новые хосты и добавить их в экземпляр провайдера;
- в графическом интерфейсе кластера открыть раздел "Администрирование" и перейти на страницу "Управление узлами", нажать на "Конфигурация группы Control Plane". На вкладке "Конфигурация ClusterAPI" установить "1" в поле "Запрошено реплик"; Примеры команды для применения в интерфейсе командной строки:
Изменить количество реплик в KubeadmControlPlane
kubectl edit KubeadmControlPlane -n ИМЯ-КЛАСТЕРА ИМЯ-КЛАСТЕРА-control-plane
- в spec KubeadmControlPlane установить значение "1" для параметра replicas;
- вернуться на страницу "Управление узлами" и скопировать имена узлов в статусе NotReady; Пример команды для применения в интерфейсе командной строки:
Получить имена узлов кластера
kubectl get node
- получить список Machines и удалить Machines, соответствующие Control Plane-узлам в статусе NotReady; Примеры команд
Получить все Machines кластера
kubectl get machines -n ИМЯ-КЛАСТЕРА
Удалить поочередно Machines, соответствующие Control Plane узлам в статусе `NotReady`
kubectl delete machines -n ИМЯ-КЛАСТЕРА ИМЯ-MACHINE
Удаление занимает некоторое время. В результате будут удалены Machines, узлы и ВМ, если кластер развернут с провайдером отличным от Shturval v2. Важно ‒ В случае длительного удаления, например более 15 минут, можно удалить Machines ручным способом:
- отредактировать удаляемый ресурс Machine, удалив finalizer;
- удалить узел из кластера и ВМ в платформе виртуализации.
- после удаления всех Machines в графическом интерфейсе кластера открыть раздел "Администрирование" и перейти на страницу "Управление узлами", нажать на "Конфигурация группы" Control Plane. На вкладке "Конфигурация ClusterAPI" установить "3" в поле "Запрошено реплик". Примеры команд для применения в интерфейсе командной строки
Изменить количество реплик в KubeadmControlPlane
kubectl edit KubeadmControlPlane -n ИМЯ-КЛАСТЕРА ИМЯ-КЛАСТЕРА-control-plane
- в spec KubeadmControlPlane установить значение "3" для параметра replicas.