Резервное копирование и восстановление работы etcd

Создание резервной копии etcd

В Комплексе можно создать резервную копию ETCD с помощью объекта NCI. Резервное копирование данных кластера ETCD может понадобиться для восстановления кластера. Рекомендуется выполнять резервное копирования в период наименьшей нагрузки на кластер:

  1. подготовить скрипт для резервного копирования, например, с именем "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
  1. в графическом интерфейсе кластера открыть страницу "Конфигурация узлов" раздела "Администрирование", нажать + Добавить NCI. На странице добавления NCI:
  2. задать имя, например "etcdbackup", и в селекторе узлов из выпадающего списка выбрать ключ лейбла node-role.kubernetes.io/control-plane. Значение для лейбла не устанавливать.
  3. в блоке "Настраиваемые разделы" выбрать "Файлы и директории" и "Пакеты для установки", нажать Продолжить (рисунок 110);

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

  1. в открывшемся окне на шаге конфигурации раздела "Пакеты для установки" нажать + и указать пакет etcdhelper (рисунок 111), выбрать целевое состояние пакета Present (рисунок 112);

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

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

  1. нажать Добавить и затем Продолжить, чтобы перейти к разделу "Файлы и директории";
  2. на шаге "Файлы и директории" нажать + и в поле "Путь к файлу или директории" прописать путь до создаваемого файла со скриптом резервного копирования. В типе файла/директории должно быть выбрано "Файл";
  3. в поле права доступа указать необходимые права, например 0755, что обеспечит владельцу полный доступ к файлу, группе владельца, другим пользователям ‒ доступ на чтение и выполнение. Владелец и группа должны быть root;
  4. в поле "Содержимое файла" вставить содержимое подготовленного скрипта из файла "etcdbackup.sh", нажать Добавить (рисунки 113‒114);

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

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

  1. нажать + и в поле "Путь к файлу или директории" прописать путь до файла с расписанием запуска резервного копирования;
  2. в поле права доступа указать необходимые права, например 0600, что обеспечит правами только владельца файла на чтение и запись. (владелец и группа должны быть root);
  3. в поле "Содержимое файла" указать конфигурацию запуска резервного копирования: расписание в cron-формате, путь до файла со скриптом и путь до создаваемой резервной копии "etcd". В поле "Содержимое файла" после записи конфигурации запуска требуется выполнить перенос строки;
  4. нажать Добавить (рисунки 115‒116).

Следует обратить внимание, что рекомендуется хранить резервную копию "etcd" в сетевой файловой системе не на Master-узлах, а, например, в /nfs/share. Это может быть полезным в случае недоступности Master-узлов.

Пример конфигурации запуска:

30 18 * * * /opt/etcdbackup.sh /tmp/

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

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

  1. нажать Завершить.

Пример NCI:

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

В результате успешного выполнения скрипта по расписанию для каждого Master-узла будет создана резервная копия "etcd".

Восстановить резервную копию etcd

Чтобы восстановить из резервной копии "etcd", для каждого Master-узла необходимо выполнить восстановление:

  1. на Master-узле переместить манифест пода с именем файла "kube-apiserver.yaml" из etc/kubernetes/manifests/ в другую папку, например /root, чтобы остановить работу API-сервера. После перемещения необходимо дождаться удаления пода (результат команды — на рисунке 117):
Перемещение пода в папку /root/
mv /etc/kubernetes/manifests/kube-apiserver.yaml  /root/
Получение информации о поде API-сервера
crictl ps | grep api

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

  1. выполнить восстановление из резервной копии etcd (результат — на рисунке 118):
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".

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

Важно ‒ В случае восстановления etcd на Master-узлах нового созданного кластера необходимо восстановить "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".

  1. перезапустить под API-сервера, переместив файл "kube-apiserver.yaml" обратно в etc/kubernetes/manifests/ на узле (результат — на рисунке ):
mv /root/kube-apiserver.yaml /etc/kubernetes/manifests/
Получение информации о поде API-сервера
crictl ps | grep api

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

Рекомендуется перезапустить kube-scheduler, С на Master-узлах. Для этого нужно поочередно переместить файлы с манифестами в папку 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

Восстановление работы кластера etcd с помощью etcd-helper

Восстановление работы кластера "etcd" с помощью модуля "etcd-helper" возможно только в высокодоступном кластере (HA):

  1. установить пакет с модулем "etcd-helper", содержащий утилиты edtcdctl, etcdutl, etcdhelper:
yum install etcdhelper

Модуль "etcd-helper" будет загружен в /usr/local/bin (рисунок 120).

Рисунок 120 ‒ Загузка модуля "etcd-helper"

  1. чтобы выполнить запрос к кластеру "etcd", запустить "etcdctl" с необходимыми параметрами, с помощью команды etcdhelper exec. Требуемые параметры будут получены из /etc/kubernetes/manifests/etcd.yaml.

Команда (результат — на рисунке 121):

/usr/local/bin/etcdhelper exec -- member list -w table

где параметр -- необходим для корректной передачи ключей в скрипте.

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

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

Если IP-адрес и имя API-сервера не изменились, но на Master-узле повреждены данные, нужно пересоздать узел в кластере "etcd", выполнив команду (результат — на рисунке 122):

/usr/local/bin/etcdhelper rejoin

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

Важно ‒ Если контейнер "etcd" на узле в статусе Running, то команда etcdhelper rejoin не может быть выполнена.

В результате выполнения команды произойдет:

  • удаление нерабочего узла из кластера "etcd";
  • остановка Kubelet;
  • удаление контейнера "etcd";
  • переименование каталога с данными "etcd";
  • добавление нового узла в кластер "etcd";
  • запуск Kubelet.

Восстановление при изменении IP-адреса Master-узла

Если IP-адрес одного из Master-узлов изменен, то можно восстановить работу кластера "etcd", использовав команду (результат — на рисунке 123):

/usr/local/bin/etcdhelper ip --nodeip=10.11.16.11

где вместо 10.11.16.11 указать новый IP-адрес узла.

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

В результате команды будет выполнено:

  • резервное копирование манифестов и сертификатов;
  • изменение IP-адреса узла в манифестах;.
  • удаление сертификатов "etcd", за исключением сертификата CA;
  • генерация сертификатов, в том числе для API-сервера;
  • изменение IP-адреса узла в кластере "etcd".

Восстановление при изменении IP-адресов всех Master-узлов

Для восстановления работоспособности кластера "etcd" нужно последовательно выполнить действия:

  1. на первом Master-узле выполнить команду для подготовки конфигурации после смены IP:
etcdhelper prepare --nodeip=НОВЫЙ IP адрес
  1. добавить опцию --force-new-cluster в манифест /etc/kubernetes/manifests/etcd.yaml;
  2. перезагрузить первый узел;
  3. отредактировать запись об узле в кластере "etcd":
etcdhelper exec member list посмотреть id ноды
etcdhelper exec member update ID --peer-urls=https://НОВЫЙ_IP:2380
  1. удалить опцию --force-new-cluster из манифеста /etc/kubernetes/manifests/etcd.yaml;
  2. перезагрузить первый узел;
  3. убедиться, что кластер Kubernetes работает;
  4. удалить оставшиеся Master-узлы из кластера:
kubectl get node (ноды в статусе NotReady)
kubectl delete node ИМЯ_НОДЫ
  1. получить токен для добавления хостов в кластер:
kubeadm token list
  1. добавить оставшиеся Master-узлы в кластер:
etcdhelper kuberrejoin --token=ТОКЕН