DR-тест Kubernetes: восстановление etcd-кластера за 12 минут - проверено заранее
Провели первый плановый DR-тест Kubernetes-кластера клиента: восстановление из etcd-снапшота. 12 минут простоя - это цифра, которую хорошо знать до, а не во время реального сбоя.
Практика DR-тестирования Kubernetes etcd-кластера становится обязательной в production 2018
Одна из неочевидных вещей в сопровождении Kubernetes-кластеров: бэкап etcd настроить проще, чем убедиться что восстановление из него реально работает. Бэкапы снимаются, в Cron всё зелёное, снапшоты копируются в S3 - и всё, галочка стоит. Что произойдёт когда придётся этот снапшот развернуть - никто не проверял.
В ноябре мы закрыли этот пробел для одного из production-кластеров на managed-обслуживании: провели плановый DR-тест, восстановление из etcd-бэкапа от начала до конца в изолированном окружении. Вот что из этого вышло.
Почему etcd - это отдельная история
etcd - единственная stateful-компонента control plane Kubernetes. Всё состояние кластера - объекты, конфигурации, секреты, привязки - хранится там. Если etcd утрачен без бэкапа или бэкап не восстанавливается - кластер нужно поднимать с нуля, а workload вспоминать из манифестов. В хорошем случае манифесты есть в Git. В реальной жизни бывает по-разному.
У клиента кластер трёхнодовый, etcd - тоже кластер из трёх членов, quorum поддерживается. Штатный сценарий - выход одного члена - переживается без DR: etcd election работает, API отвечает. DR нужен когда теряем большинство или весь кластер. Это редкость, но вероятность не нулевая - железо падает, датацентры горят, администраторы ошибаются.
Как готовили тест
Первое - договорились о метриках. Нас интересовали два числа: RTO (сколько времени занимает восстановление) и RPO (насколько свежий снапшот мы можем гарантировать). По бэкап-расписанию снапшоты снимались каждый час, хранились 48 часов в S3 с репликацией. RPO у нас был теоретически час. RTO - неизвестен, его и шли измерять.
Второе - изолированное окружение. Восстанавливаться на production-кластере клиента никто не собирался. Подняли идентичный по конфигурации тестовый кластер: те же версии (Kubernetes 1.12, etcd 3.3), те же сертификаты инфраструктуры, та же топология. Взяли снапшот etcd из S3 - не самый свежий, а трёхдневной давности, чтобы было что терять и находить.
Третье - полный сброс etcd. Имитировали сценарий «все три члена потеряны»: остановили etcd на всех трёх нодах, очистили data-директории, удалили member-state. Чистый лист.
Что делали и сколько это заняло
Процедура восстановления etcd из снапшота выглядит примерно так:
- Скачать снапшот из S3 и проверить через
etcdctl snapshot status. Это первое что стоит сделать - убедиться что файл целый, а не оборванная загрузка. - Восстановить данные на каждом члене через
etcdctl snapshot restoreс параметрами имени кластера, peer-URL-ов и начального состоянияnew. Это создаёт новые data-директории с нужным содержимым и свежими member-идентификаторами. - Запустить etcd на всех нодах с флагом
--initial-cluster-state=new- они узнают друг друга и формируют новый кластер из восстановленных данных. - Проверить что API-сервер Kubernetes поднялся и видит объекты из снапшота.
- Перезапустить controller manager и scheduler - они иногда зависают на старых соединениях после перезапуска etcd.
По времени: скачивание снапшота (он был около 200 МБ) - 2 минуты. Восстановление данных на трёх нодах параллельно - 3 минуты. Запуск etcd и ожидание quorum - 4 минуты. Проверка состояния кластера, объектов, нескольких workload - ещё 3 минуты. Итого - 12 минут от «начали» до «кластер работает, данные на месте».
12 минут - это немного, но это и не мгновенно. Для кластера где крутится production-нагрузка, 12 минут простоя control plane - это простой всего что масштабируется, деплоится или перезапускается в этот момент. Workload, которые уже запущены и не падают, продолжают работать - kubelet на нодах автономен. Но новые поды не стартуют, ConfigMap не обновляются, Ingress-правила не меняются.
Что обнаружили по ходу
Несколько моментов, которые не очевидны пока не попробуешь вживую.
Сертификаты etcd. При восстановлении важно использовать те же CA-сертификаты, что были в оригинальном кластере. Если сертификаты утрачены вместе с кластером - восстановить etcd из снапшота технически можно, но придётся перевыпускать все клиентские сертификаты Kubernetes-компонентов. Это отдельная работа, которая не входит в 12 минут.
Порядок запуска. Восстанавливать etcd нужно сначала на всех нодах, и только потом запускать - а не запускать первый, ждать, запускать второй. Если запустить первый без указания остальных пиров, он поднимется в single-member режиме со своим cluster-ID, и добавить к нему остальных уже нельзя будет через restore.
coredns и системные поды. После того как API поднялся, несколько минут системные поды (coredns, kube-proxy) показывали Unknown статус - kubelet ещё не успел отрапортовать. Это нормально, прошло само. Но без понимания этого первая реакция - паника.
Что это дало
Главное что дал тест - уверенность, что процедура рабочая. До теста было: «бэкапы есть, восстановление должно работать». После - конкретная отработанная последовательность действий, измеренное время и понимание подводных камней.
Оформили runbook: пошаговый документ на случай реального DR, с командами, именами файлов под этот кластер, контактами. Это не большой документ - две страницы. Но две страницы с реальными командами лучше, чем документация etcd в момент когда всё горит.
Тест планируем повторять раз в квартал - и при обновлении etcd или Kubernetes. Процедура restore немного меняется между версиями, лучше знать об этом заранее.