кластеру нет — с такой проблемой в Southbridge пришла компания Eats.World. Доступы остались у предыдущего подрядчика, с которым Eats.World расстались. Нам предстояло взломать кластер, вернуть приложение к жизни и навести порядок в служебных сервисах, чтобы проблемы не повторились.
В этой статье описываем процесс работы с заказчиком и показываем, какие технические ошибки совершили предшественники.
Осматриваемся на местности
Eats.World доставляет еду из ресторанов и параллельно помогает бизнесу в HoReCa налаживать цифровизацию и обучать сотрудников. Ключевой продукт компании — мобильное приложение по заказу и доставке еды Eats. Оно то и работало со сбоями из-за проблем в инфраструктуре.
Кластер был развёрнут на виртуальных машинах KVM, а доступа к ним не было. Предыдущий аутсорсер удалил всех ssh-пользователей, создал пользователя user, а пароль от него не сказал и при этом запретил доступ по паролю через ssh.
Не стартовали поды, отсутствовали данные в кластере ElasticSearch, в результате в мобильном приложении отказала часть функционала, работа проекта была нарушена.
Состояние сервисов в кластере на момент начала работ (из переписки):

Стек технологий, который используют в компании клиента: Gitlab, Kubernetes, Helm, Kafka, Hazelcast, Elasticsearch, Cassandra, Ceph, Prometheus, Grafana, Clickhouse, Minio.
Штурмуем кластер и тушим то, что горит
Первым делом мы создали телеграм-чат для оперативной связи с командой Eats.World, запросили имеющиеся доступы и определили список приоритетных задач.
Так как доступов к проблемному кластеру и виртуальным машинам KVM не было, пришлось их буквально взламывать. Наконец прорвав оборону, в консоли увидели такое

Приложение начало работать, но прогружались не все точки и встречались дубли:
При содействии клиента я убрал дубли в базе данных. Вместе мы сначала искали дублирующиеся записи в одной таблице, затем в другой смотрели, на какую запись они указывают, и удаляли лишние (из Cassandra и Elasticsearch). Так же делал экспорт записей из Cassandra в Elasticsearch.
DevOps-инженер Southbridge Александр Осипов
В конце концов мы убрали дубли и нашли причину, по которой не прогружались точки: у проблемных точек не в кэше не было значений из Hazelcast. Мы запускали миграции и перезапускали медиахостинги, в итоге все данные подтянулись, приложение заработало как надо.

Наводим порядок
Когда решили срочные задачи, перешли к плановым — менее приоритетным, но не менее важным.
Настроили мониторинг и заметили высокую нагрузку в кластере. Её создавало программное обеспечение, которое написал предыдущий аутсорсер. Это ПО управляло служебными сервисами внутри кластера: устанавливало и настраивало их. Так как ПО закрытое, посмотреть его код и что оно делает мы не могли. Зато могли отключить. Ситуация с нагрузкой в кластере улучшилась.

Иногда о проблемах мы узнавали сами, иногда от сотрудников Eats.World. Вот пример последнего:

Ниже список основных работ с некоторыми деталями.
❌Когда запустили серверы и кластер Kubernetes, оказалось, что в кластере Elasticsearch нет данных на одном из трёх узлов. В настройках узла Elasticsearch не был убран параметр: "cluster.initial_master_nodes: elastic-0". Узел не мог добавиться в существующий кластер и создавал новый из одного узла.
✔️Опцию убрали, узел успешно присоединился к кластеру.
❌Не запускалась Kafka, так как было исчерпано места на PV в кластере.
✔️Место добавили, Kafka запустилась.
❌Некоторые приложения в окружениях dev и prod использовали один кластер Kafka.
✔️Внесли изменения в helm-чарты для разделения окружений.
❌Плохо работал выпуск ssl-сертификатов. Для приложений клиента не был настроен автоматический выпуск сертификатов для https. Cертификаты хранились в CI проектов. Cert-manager был собран из образа предыдущего аутсорсера.
✔️Заменили образ cert-manager на стандартный, прописали аннотацию для автоматического выпуска ssl-сертификатов.
✔️Возникла задача ручного управления кластерами Hazelcast. Развернули “management-center (веб-интерфейс для ручного управления кластером), интегрировали в кластер.
✔️По просьбе клиента заполнили индекс в Elasticsearch на основании данных из Cassandra. Типы данных и структура индекса приведены к необходимому для приложения виду.
✔️ По просьбе клиента часто приходилось вручную редактировать данные в кластере Cassandra, вносить изменения в схему. Поэтому реализовали ежедневный бэкап кластеров Cassandra на удаленный сервер. Восстановление данных из бэкапа Cassandra уже использовалось при откате на предыдущую версию в dev-окружении.
✔️ Клиент разработал приложение на Flask, которое позволяет обслуживать внутренние данные основного приложения через веб-интерфейс. Для приложения мы написали helm-chart, настроили CI (без утилиты деплоя от предыдущего аутсорсера). Персистентные данные приложения хранятся в ceph rbd.
✔️ Решили вопрос повышенной нагрузки на кластер.
Чем дело кончилось
За несколько месяцев мы вместе с клиентом восстановили доступы, наладили работу приложения, исправили ошибки и устранили проблемные места, переделали мониторинг. Теперь поддерживаем проект 24/7.