Под капотом у CarPrice: как мы управляем инфраструктурой и жизненным циклом приложений
Что изменилось после переезда с технической точки зрения?
Не так уж много: до переезда мы пользовались набором разношерстных серверов, а сейчас перешли на блейд-платформу, поверх которой запущен гипервизор Proxmox. На гипервизоре развернуто чуть больше 100 виртуальных машин.
В общей сложности, у нас в распоряжении оказались:
Серверные шасси: HP BladeSystem c9000;
Типовая конфигурация серверов: 64 vCPU, 192 или 256 GB RAM;
Дисковые хранилища:
Сеть: 10 Гбит/с.
Но не железом единым — вернемся к вопросам инфраструктуры.
Кто живет на VM
Для каждого разработчика разворачивается маленькая копия прода в отдельном неймспейсе — поэтому кластер на dev-инфраструктуре крупнее. В нем более 60 виртуальных машин и суммарно более 3 000 подов.
Пример — stateful-приложения, которые требуют наличия дисковых ресурсов. В нашем случае Kubernetes больше подходит для stateless-приложений, так как запуск stateful требует наличия надежного кластерного хранилища, такого как CEPH. Stateful приложений у нас немного, поэтому поддержка подобного хранилища для нас не оправдана.
Все сервисы, которые развернуты на виртуальных машинах, но не в кластерах Kubernetes, мы резервируем. В большинстве случаев для резервирования используем демон Keepalived. Когда один из IP адресов машин в кластере отказывает, плавающий IP быстро переключается на новый узел — в итоге мы потеряем меньше секунды в случае аварии.
Структурная схема инфраструктуры CarPrice
Инфраструктуру CarPrice упрощенно можно представить в виде следующей схемы:
Как мы видим по схеме, инфраструктура CarPrice использует защиту от атак. С паблика трафик поступает на серверы внешнего провайдера, который защищает нас от DDoS, ботов, а также сканирует трафик на наличие вредоносных запросов. Уже отфильтрованный, он отправляется на наши VM с балансировщиками Nginx. Дальше Nginx распределяют трафик между потребителями: кластерами Kubernetes, Docker-сервисами и монолитами.
Немного о деплое
Как я уже рассказывал в этом блоге, мы сторонники CI/CD. Схема и инструменты, используемые для деплоя, зависят от того, на какие серверы этот деплой направлен.
GitOps — методология, которая фокусируется на использовании git-репозиториев для управления инфраструктурой и развертыванием кода приложений. По сути, это непрерывный процесс синхронизации из Git, который помогает удостовериться: наше окружение сохраняет желаемое состояние.
Благодаря GitOps мы можем автоматизировать весь процесс обслуживания приложения в кластере Kubernetes: деплой, контроль за работой, удаление. В результате бизнес получает более стабильный продукт и точное понимание его состояния.
Argo CD — это оператор с открытым кодом, который поддерживает непрерывную доставку для Kubernetes. Задача Argo CD — следить за Git-репозиторием. Какие бы изменения мы не внесли в манифесты, он заберет их из Git. Затем применит манифест в кластере Kubernetes и проконтролирует процесс запуска приложения. А в конце пришлет уведомление в чат релизов о статусе деплоя.
Как мы работаем с секретами
Отдельно стоит сказать о процессе работы с различными секретами, внутренними или внешними, вроде доступа к базе данных.
Для бизнеса хранение секретов — это вопрос информационной безопасности. Но даже в крупных ИТ-компаниях безопасностью часто пренебрегают. Секреты оказываются не просто видны на уровне инфраструктуры — они могут лежать прямо в git-репозитории.
Мы старались избежать этих ошибок: наши секреты хранятся в Vault и «заезжают» в манифесты приложений только в момент деплоя.
Как устроен процесс инъекции секрета из Vault:
Когда мы храним манифесты в Git, то вместо ключа или пароля добавляем в них специальную инструкцию, в которой хранится отсылка на путь хранения секрета в Vault наподобие такой: «vault: secret/
В Kubernetes при этом работает специальный оператор Bank-Vaults, который в момент деплоя видит в тексте манифеста отсылку на путь к Vault. Он идет по этому пути и добавляет вместо отсылки настоящее значение секрета.
Кроме оператора, никто в процессе деплоя не может узнать о секрете. Кроме того, нельзя увидеть секреты и войдя в контейнер через kubectl: переменные с секретами видны только процессу с pid 1 и его потомкам.
Проверка кода и мониторинг
Чтобы проверить код, мы используем статистический анализатор, линтеры и авто-тесты:
SonarQube;
SonarQube — это статический анализатор. Он проверяет, что разработчик не накосячил в коде;, а еще находит в нем уязвимости.
Линтер — это про оформление кода. Можно написать его в одну строчку, а можно разбить так, чтобы с ним удобно было работать. Линтер без участия людей проверяет, что код написан в соответствии с определенным набором правил.
Мы используем Smog End-to-End тесты в продакшене, которые симулируют действия живого человека. И юнит-тесты, которые помогают проверить, не сломал ли разработчик, пока вносил изменения, всю связку методов. В планах — масштабировать авто-тестирование на большее количество сервисов — на все клиентские и дилерские приложения.
Итак, мы проверили код статистическим анализатором и линтерами, задеплоили в кластер, провели авто-тест — приложение работает. Но его работа нуждается в дальнейшем мониторинге: нам нужно следить за VM, физическими серверами, метриками.
Тут нам помогают стандартные решения.
Для того, чтобы собирать метрики, мы используем Prometheus. Prometheus работает в режиме федерации: есть 2 инстанса, первый собирает все метрики с коротким временным интервалом опроса и хранит их ограниченное время, второй забирает метрики с меткой longterm из первого и хранит их не менее года. Таким образом проставив метку для важных метрик мы автоматически можем сохранять их продолжительное время.
Чтобы визуализировать метрики и строить по ним аналитику — Grafana.
Для сбора логов используем классический стек ELK: elasticsearch для хранения, перед ним — logstash для обработки логов. Агенты filebeat используем для сбора логов непосредственно с серверов и из Kubernetes.
Но есть и кое-что не такое популярное, как Prometheus и ELK:
Чтобы мониторить инциденты на инфраструктуре, мы используем Alerta. Это приложение, которое собирает все инциденты, отображает их на единой панели и дополнительно рассылает уведомления в RocketChat или Telegram.
Собирать инциденты по приложениям нам помогает Sentry. Многие сервисы настроены на работу с ним, и в случае сбоев присылают сообщения именно туда.
Sentry — агрегатор: он фиксирует все ошибки, видит, сколько раз они повторяются и может детализировать причину их возникновения. Мы также осуществляем в Sentry привязку релизов: отправляем информацию о релизе, чтобы дальнейшие ошибки можно было связать с ним.
Немного об итогах и планах
Новый ЦОД — «новая глава» в жизни инфраструктуры (и иногда — новые возможности).
Вот несколько изменений, которые мы планируем:
Продолжить работу над совершенствованием dev-окружений и перевести их на ArgoCD, чтобы не только контейнеры приложений, но и манифесты Kubernetes были одинаковыми с продом.
Внедрить в компании свой identity-провайдер на базе Keycloak и настроить на него авторизацию в корпоративных и служебных сервисах.
Добавить в CI/CD этапы со сканированием уязвимостей в коде и докер образах.
Запустить полноценный Stage, на котором прогонять функциональные тесты приложения перед их деплоем в прод.
Покрыть автотестами еще большее количество приложений.
С другой стороны, мы всегда уделяли особое внимание мониторингу — и планируем не сбавлять темп в дальнейшем и оптимизировать работу с инцидентами и их жизненным циклом.
Единственное, что вряд ли изменится со временем — в нашей команде всегда рады единомышленникам и новым крутым спецам :)