Привет! Я Саша Хренников, руководитель DevOps-юнита в KTS.
Недавно мы провели DevOps-челлендж, где нужно поднять неисправный экземпляр MySQL. Было нелегко — быстрее всех справились восемь сильнейших DevOps-мастеров, которым мы уже отправляем призовой мерч. Вот они — слева направо:
@gsirrxz (Время прохождения: 28m 00s)
@ovsjke (Время прохождения: 31m 27s)
@mr_hightlook (Время прохождения: 34m 6s)
@angapov (Время прохождения: 51m 49s)
@iTem86 (Время прохождения: 55m 14s)
@Yepcock (Время прохождения: 56m 0s)
@Benosa19 (Время прохождения: 58m 51s)
@ovss_s (Время прохождения: 59m 38s)
В этой статье я разберу задачу и покажу, как её можно решить двумя способами.
Оглавление
Как понять, что кластер сломался
Для начала разберёмся, что же произошло с нашим кластером.
Первое что мы видим — pod mysql-0
, который завис в состоянии Terminating. Чтобы понять, что произошло, заглянем в describe. Среди прочих ошибок получаем и такую строку:
Handler 'on_pod_delete' failed temporarily: Cluster cannot be restored because there are unreachable pods
Похоже, что у пода «залип finalizer».
Чтобы избавиться от этого недоразумения, смело можно запустить kubectl edit либо patch, если так привычнее. Достаточно удалить вот эти строки:
finalizers:
- mysql.oracle.com/membership
- kopf.zalando.org/KopfFinalizerMarker
После этого видим, что под запускается. Но сервис так и не хочет отвечать. Продолжим расследование и посмотрим в лог MySQL:
[Note] [MY-010926] [Server] Access denied for user 'mysqladmin'@'10-1-128-45.mysql-operator.mysql-operator.svc.cluster.local' (using password: YES)
Загуглив имя пользователя «mysqladmin», в первой ссылке находим, что это служебный пользователь, созданный оператором. Пароль от него лежит в секрете mysql-privsecrets. Подробнее по ссылке.
Добываем пароль из секрета и, провалившись в контейнер mysql, проверяем, что пароль не подходит. Похоже, какой-то злодей его поменял…
kubectl exec -it mysql-0 -c mysql -- /bin/bash
bash-5.1$ mysql -u mysqladmin -p
Enter password:
ERROR 1045 (28000): Access denied for user 'mysqladmin'@'localhost' (using password: YES)
Как же восстановить работу кластера? Есть два пути.
Вариант первый
У нас есть реквизиты root-пользователя, и они вполне работоспособны. Поэтому простым и понятным способом будет записать его учётку из секрета mycluster-cluster-secret в секрет mysql-privsecrets: и пароль, и имя пользователя.
После чего в логах mysql-router видим заветное:
metadata_cache WARNING [7f20d83d6640] Failed fetching metadata from metadata server on mysql-0.mysql-instances.default.svc.cluster.local:3306 - No result returned for metadata query
metadata_cache WARNING [7f20d83d6640] Metadata server mysql-0.mysql-instances.default.svc.cluster.local:3306 is not an online GR member - skipping.
metadata_cache INFO [7f20d83d6640] Potential changes detected in cluster after metadata refresh (view_id=0)
metadata_cache INFO [7f20d83d6640] Metadata for cluster 'mysql' has 1 member(s), single-primary:
metadata_cache INFO [7f20d83d6640] mysql-0.mysql-instances.default.svc.cluster.local:3306 / 33060 - mode=RW
Вариант второй
Можно посмотреть, что база с данными у нас одна и снять с неё дамп.
kubectl exec -i mysql-0 -c mysql -- mysqldump -u root -p**** KTS > kts.dump
Сохранить конфиги кластера и очистить их от лишних записей.
kubectl get InnoDBCluster mysql -o yaml > cluster.yaml
Удалить кластер и его pvc. Правда, тут тоже может понадобиться поработать очисткой finalizer-ов.
kubectl delete InnoDBCluster mysql
kubectl delete pvc datadir-mysql-0
Заново создать кластер, так как секрет mycluster-cluster-secret создаётся отдельно от кластера, и пароль пользователя root не изменится.
kubectl apply -f cluster.yaml
Ну и последним шагом — создаём базу и выливаем дамп обратно.
kubectl exec -i mysql-0 -c mysql -- mysql -u root -p**** -e "create database KTS;"kubectl exec -i mysql-0 -c mysql -- mysql -u root -p**** -D KTS <
kts.dump
О работе секретов MySQL-оператора
Особенность работы оператора в том, что при создании кластера он создает служебные секреты (в том числе privsecrets
) и пользователей на основе этих секретов при инициализации базы.
Далее — эти секреты используются только для подключения к работающей базе. Для нас это значит, что стоит потерять такой пароль, и без приключений подключиться к базе или сбросить его не получится. Так что, если вам не нужны такие проблемы с работой кластера то, возможно, стоит задуматься о бэкапировании этих секретов.
Мы провели уже три DevOps-челленджа. Скоро анонсируем ещё один! Не теряйтесь, залетайте в наш бот и пишите /start
— пришлём приглашение на челлендж одним из первых
С MySQL разобрались. А если хочется больше полезного контента по DevOps, советую изучить наши статьи:
avinogradov
Несколько странный кейс. Поломка кластера в случае если кончилось место на диске или или была прервана какая-то тяжёлая операция например удаление нескольких миллионов записей Ну это по крайней мере то с чем я в реальности сталкивался а не смена пароля.