Русский
Русский
English
Статистика
Реклама

Etcd

Ломаем и чиним etcd-кластер

01.03.2021 20:22:05 | Автор: admin

etcd это быстрая, надёжная и устойчивая к сбоям key-value база данных. Она лежит в основе Kubernetes и является неотъемлемой частью его control-plane. Именно поэтому критически важно уметь бэкапить и восстанавливать работоспособность как отдельных нод, так и всего etcd-кластера.

В предыдущей статье мы подробно рассмотрели перегенерацию SSL-сертификатов и static-манифестов для Kubernetes, а также вопросы связанные восстановлением работоспособности Kubernetes. Эта статья будет посвящена целиком и полностью восстановлению etcd-кластера.


Для начала я сразу должен сделать оговорку, что рассматривать мы будем лишь определённый кейс, когда etcd задеплоен и используется непосредственно в составе Kubernetes. Приведённые в статье примеры подразумевают что ваш etcd-кластер развёрнут с помощью static-манифестов и запускается внутри контейнеров.

Для наглядности возьмём схему stacked control plane nodes из предыдущей статьи:

(стрелочки указывают на связи клиент --> сервер)(стрелочки указывают на связи клиент --> сервер)

Предложенные ниже команды можно выполнить и с помощью kubectl, но в данном случае мы постараемся абстрагироваться от плоскости управления Kubernetes и рассмотрим локальный вариант управления контейнеризированным etcd-кластером с помощью crictl.

Данное умение также поможет вам починить etcd даже в случае неработающего Kubernetes API.

Подготовка

По этому, первое что мы сделаем, это зайдём по ssh на одну из master-нод и найдём наш etcd-контейнер:

CONTAINER_ID=$(crictl ps -a --label io.kubernetes.container.name=etcd --label io.kubernetes.pod.namespace=kube-system | awk 'NR>1{a=$1} END{print a}')

Так же установим алиас, чтобы каждый раз не перечислять пути к сертификатам в командах:

alias etcdctl='crictl exec "$CONTAINER_ID" etcdctl --cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt'

Приведённые выше команды являются временными, вам потребуется выполнять их каждый раз перед тем как начать работать с etcd. Конечно, для своего удобства вы можете добавить их в .bashrc. Как это сделать выходит за рамки этой статьи.

Если что-то пошло не так и вы не можете сделать exec в запущенный контейнер, посмотрите логи etcd:

crictl logs "$CONTAINER_ID"

А также убедитесь в наличии static-манифеста и всех сертифиткатов в случае если контейнер даже не создался. Логи kubelet так же бывают весьма полезными.

Проверка состояния кластера

Здесь всё просто:

# etcdctl member list -w table+------------------+---------+-------+---------------------------+---------------------------+------------+|        ID        | STATUS  | NAME  |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |+------------------+---------+-------+---------------------------+---------------------------+------------+| 409dce3eb8a3c713 | started | node1 | https://10.20.30.101:2380 | https://10.20.30.101:2379 |      false || 74a6552ccfc541e5 | started | node2 | https://10.20.30.102:2380 | https://10.20.30.102:2379 |      false || d70c1c10cb4db26c | started | node3 | https://10.20.30.103:2380 | https://10.20.30.103:2379 |      false |+------------------+---------+-------+---------------------------+---------------------------+------------+

Каждый инстанс etcd знает всё о каждом. Информация о members хранится внутри самого etcd и по этому любое изменение в ней будет также обновленно и на остальных инстансах кластера.

Важное замечание, команда member list отображает только статус конфигурации, но не статус конкретного инстанса. Чтобы проверить статусы инстансов есть команда endpoint status, но она требует явного указания всех эндпоинтов кластера для проверки.

ENDPOINTS=$(etcdctl member list | grep -o '[^ ]\+:2379' | paste -s -d,)etcdctl endpoint status --endpoints=$ENDPOINTS -w table

в случае если какой-то из эндпоинтов окажется недоступным вы увидите такую ошибку:

Failed to get the status of endpoint https://10.20.30.103:2379 (context deadline exceeded)

Удаление неисправной ноды

Иногда случается так что какая-то из нод вышла из строя. И вам нужно восстановить работоспособность etcd-кластера, как быть?

Первым делом нам нужно удалить failed member:

etcdctl member remove d70c1c10cb4db26c

Прежде чем продолжить, давайте убедимся, что на упавшей ноде под с etcd больше не запущен, а нода больше не содержит никаких данных:

rm -rf /etc/kubernetes/manifests/etcd.yaml /var/lib/etcd/crictl rm "$CONTAINER_ID"

Команды выше удалят static-pod для etcd и дирректорию с данными /var/lib/etcd на ноде.

Разумеется в качестве альтернативы вы также можете воспользоваться командой kubeadm reset, которая удалит все Kubernetes-related ресурсы и сертифиткаты с вашей ноды.

Добавление новой ноды

Теперь у нас есть два пути:

В первом случае мы можем просто добавить новую control-plane ноду используя стандартный kubeadm join механизм:

kubeadm init phase upload-certs --upload-certskubeadm token create --print-join-command --certificate-key <certificate_key>

Вышеприведённые команды сгенерируют команду для джойна новой control-plane ноды в Kubernetes. Этот кейс довольно подробно описан в официальной документации Kubernetes и не нуждается в разъяснении.

Этот вариант наиболее удобен тогда, когда вы деплоите новую ноду с нуля или после выполнения kubeadm reset

Второй вариант более аккуратный, так как позволяет рассмотреть и выполнить изменения необходимые только для etcd не затрагивая при этом другие контейнеры на ноде.

Для начала убедимся что наша нода имеет валидный CA-сертификат для etcd:

/etc/kubernetes/pki/etcd/ca.{key,crt}

В случае его отсутсвия скопируейте его с других нод вашего кластера. Теперь сгенерируем остальные сертификаты для нашей ноды:

kubeadm init phase certs etcd-healthcheck-clientkubeadm init phase certs etcd-peerkubeadm init phase certs etcd-server

и выполним присоединение к кластеру:

kubeadm join phase control-plane-join etcd --control-plane

Для понимания, вышеописанная команда сделает следующее:

  1. Добавит новый member в существующий etcd-кластер:

    etcdctl member add node3 --endpoints=https://10.20.30.101:2380,https://10.20.30.102:2379 --peer-urls=https://10.20.30.103:2380
    
  2. Сгенерирует новый static-manifest для etcd /etc/kubernetes/manifests/etcd.yaml с опциями:

    --initial-cluster-state=existing--initial-cluster=node1=https://10.20.30.101:2380,node2=https://10.20.30.102:2380,node3=https://10.20.30.103:2380
    

    эти опции позволят нашей ноде автоматически добавиться в существующий etcd-кластер.

Создание снапшота etcd

Теперь рассмотрим вариант создания и восстановления etcd из резервной копии.

Создать бэкап можно довольно просто, выполнив на любой из нод:

etcdctl snapshot save /var/lib/etcd/snap1.db

Обратите внимание я намерянно использую /var/lib/etcd так как эта директория уже прокинута в etcd контейнер (смотрим в static-манифест /etc/kubernetes/manifests/etcd.yaml)

После выполнения этой команды по указанному пути вы найдёте снапшот с вашими данными, давайте сохраним его в надёжном месте и рассмотрим процедуру восстановления из бэкапа

Восстановление etcd из снапшота

Здесь мы рассмотрим кейс когда всё пошло не так и нам потребовалось восстановить кластер из резервной копии.

У нас есть снапшот snap1.db сделанный на предыдущем этапе. Теперь давайте полностью удалим static-pod для etcd и данные со всех наших нод:

rm -rf /etc/kubernetes/manifests/etcd.yaml /var/lib/etcd/member/crictl rm "$CONTAINER_ID"

Теперь у нас снова есть два пути:

Вариант первый создать etcd-кластер из одной ноды и присоединить к нему остальные ноды, по описанной выше процедуре.

kubeadm init phase etcd local

эта команда сгенерирует статик-манифест для etcd c опциями:

--initial-cluster-state=new--initial-cluster=node1=https://10.20.30.101:2380

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

# etcdctl member list -w table+------------------+---------+-------+---------------------------+---------------------------+------------+|        ID        | STATUS  | NAME  |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |+------------------+---------+-------+---------------------------+---------------------------+------------+| 1afbe05ae8b5fbbe | started | node1 | https://10.20.30.101:2380 | https://10.20.30.101:2379 |      false |+------------------+---------+-------+---------------------------+---------------------------+------------+

Восстановим бэкап на первой ноде:

etcdctl snapshot restore /var/lib/etcd/snap1.db \  --data-dir=/var/lib/etcd/new  --name=node1 \  --initial-advertise-peer-urls=https://10.20.30.101:2380 \  --initial-cluster=node1=https://10.20.30.101:2380mv /var/lib/etcd/member /var/lib/etcd/member.oldmv /var/lib/etcd/new/member /var/lib/etcd/membercrictl rm "$CONTAINER_ID"rm -rf /var/lib/etcd/member.old/ /var/lib/etcd/new/

На остальных нодах выполним присоединение к кластеру:

kubeadm join phase control-plane-join etcd --control-plane

Вариант второй: восстановить бэкап сразу на всех нодах кластера. Для этого копируем файл снапшота на остальные ноды, и выполняем восстановление вышеописанным образом. В данном случае в опциях к etcdctl нам потребуется указать сразу все ноды нашего кластера, к примеру

для node1:

etcdctl snapshot restore /var/lib/etcd/snap1.db \  --data-dir=/var/lib/etcd/new \  --name=node1 \  --initial-advertise-peer-urls=https://10.20.30.101:2380 \  --initial-cluster=node1=https://10.20.30.101:2380,node2=https://10.20.30.102:2380,node3=https://10.20.30.103:2380

для node2:

etcdctl snapshot restore /var/lib/etcd/snap1.db \  --data-dir=/var/lib/etcd/new \  --name=node2 \  --initial-advertise-peer-urls=https://10.20.30.102:2380 \  --initial-cluster=node1=https://10.20.30.101:2380,node2=https://10.20.30.102:2380,node3=https://10.20.30.103:2380

для node3:

etcdctl snapshot restore /var/lib/etcd/snap1.db \  --data-dir=/var/lib/etcd/new \  --name=node3 \  --initial-advertise-peer-urls=https://10.20.30.103:2380 \  --initial-cluster=node1=https://10.20.30.101:2380,node2=https://10.20.30.102:2380,node3=https://10.20.30.103:2380
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru