Привет! Я Саша Хренников, руководитель 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, советую изучить наши статьи:

Комментарии (1)


  1. avinogradov
    20.10.2024 17:33

    Несколько странный кейс. Поломка кластера в случае если кончилось место на диске или или была прервана какая-то тяжёлая операция например удаление нескольких миллионов записей Ну это по крайней мере то с чем я в реальности сталкивался а не смена пароля.