Что изменилось после переезда с технической точки зрения?
Не так уж много: до переезда мы пользовались набором разношерстных серверов, а сейчас перешли на блейд-платформу, поверх которой запущен гипервизор Proxmox. На гипервизоре развернуто чуть больше 100 виртуальных машин.
В общей сложности, у нас в распоряжении оказались:
Серверные шасси: HP BladeSystem c9000;
Типовая конфигурация серверов: 64 vCPU, 192 или 256 GB RAM;
Дисковые хранилища:
IBM All Flash 900 Raid SAN Storage 9843-AE2 для быстрых дисков;
Dell MD3200i для холодных данных;
Сеть: 10 Гбит/с.
Но не железом единым — вернемся к вопросам инфраструктуры.
Кто живет на VM
Большинство наших виртуальных машин отводится под prod и dev кластеры Kubernetes.
Для каждого разработчика разворачивается маленькая копия прода в отдельном неймспейсе — поэтому кластер на dev-инфраструктуре крупнее. В нем более 60 виртуальных машин и суммарно более 3 000 подов.
Еще несколько VM отданы под Docker-сервисы, которые мы не деплоим в Kubernetes по различным причинам.
Пример — stateful-приложения, которые требуют наличия дисковых ресурсов. В нашем случае Kubernetes больше подходит для stateless-приложений, так как запуск stateful требует наличия надежного кластерного хранилища, такого как CEPH. Stateful приложений у нас немного, поэтому поддержка подобного хранилища для нас не оправдана.
Часть VM предназначена для инфраструктурных вещей вроде soft роутеров или почтовых серверов.
Все сервисы, которые развернуты на виртуальных машинах, но не в кластерах Kubernetes, мы резервируем. В большинстве случаев для резервирования используем демон Keepalived. Когда один из IP адресов машин в кластере отказывает, плавающий IP быстро переключается на новый узел — в итоге мы потеряем меньше секунды в случае аварии.
Еще на выделенных VM живут сервер с Elasticsearch для сбора логов, балансировщики Nginx и инстансы монолита.
Структурная схема инфраструктуры CarPrice
Инфраструктуру CarPrice упрощенно можно представить в виде следующей схемы:
Как мы видим по схеме, инфраструктура CarPrice использует защиту от атак. С паблика трафик поступает на серверы внешнего провайдера, который защищает нас от DDoS, ботов, а также сканирует трафик на наличие вредоносных запросов. Уже отфильтрованный, он отправляется на наши VM с балансировщиками Nginx. Дальше Nginx распределяют трафик между потребителями: кластерами Kubernetes, Docker-сервисами и монолитами.
Немного о деплое
Как я уже рассказывал в этом блоге, мы сторонники CI/CD. Схема и инструменты, используемые для деплоя, зависят от того, на какие серверы этот деплой направлен.
На VM с Docker-сервисами используем нехитрую схему: Gitalb CI с деплоем через Ansible.
А вот деплой в кластеры Kubernetes уже интереснее: тут мы используем GitOps подход и инструменты.
GitOps — методология, которая фокусируется на использовании git-репозиториев для управления инфраструктурой и развертыванием кода приложений. По сути, это непрерывный процесс синхронизации из Git, который помогает удостовериться: наше окружение сохраняет желаемое состояние.
Благодаря GitOps мы можем автоматизировать весь процесс обслуживания приложения в кластере Kubernetes: деплой, контроль за работой, удаление. В результате бизнес получает более стабильный продукт и точное понимание его состояния.
В качестве GitOps инструмента мы выбрали Argo CD.
Argo CD — это оператор с открытым кодом, который поддерживает непрерывную доставку для Kubernetes. Задача Argo CD — следить за Git-репозиторием. Какие бы изменения мы не внесли в манифесты, он заберет их из Git. Затем применит манифест в кластере Kubernetes и проконтролирует процесс запуска приложения. А в конце пришлет уведомление в чат релизов о статусе деплоя.
Как мы работаем с секретами
Отдельно стоит сказать о процессе работы с различными секретами, внутренними или внешними, вроде доступа к базе данных.
Для бизнеса хранение секретов — это вопрос информационной безопасности. Но даже в крупных ИТ-компаниях безопасностью часто пренебрегают. Секреты оказываются не просто видны на уровне инфраструктуры — они могут лежать прямо в git-репозитории.
Мы старались избежать этих ошибок: наши секреты хранятся в Vault и «заезжают» в манифесты приложений только в момент деплоя.
Как устроен процесс инъекции секрета из Vault:
Когда мы храним манифесты в Git, то вместо ключа или пароля добавляем в них специальную инструкцию, в которой хранится отсылка на путь хранения секрета в Vault наподобие такой: "vault:secret/<path>#<key>".
В 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 привязку релизов: отправляем информацию о релизе, чтобы дальнейшие ошибки можно было связать с ним.
Немного об итогах и планах
Новый ЦОД — «новая глава» в жизни инфраструктуры (и иногда — новые возможности).
Вот несколько изменений, которые мы планируем:
Внедрить service-mesh для более тщательного контроля за процессом взаимодействия сервисов. Пока что присматриваемся к linkerd.
Продолжить работу над совершенствованием dev-окружений и перевести их на ArgoCD, чтобы не только контейнеры приложений, но и манифесты Kubernetes были одинаковыми с продом.
Внедрить в компании свой identity-провайдер на базе Keycloak и настроить на него авторизацию в корпоративных и служебных сервисах.
Добавить в CI/CD этапы со сканированием уязвимостей в коде и докер образах.
Запустить полноценный Stage, на котором прогонять функциональные тесты приложения перед их деплоем в прод.
Покрыть автотестами еще большее количество приложений.
С другой стороны, мы всегда уделяли особое внимание мониторингу — и планируем не сбавлять темп в дальнейшем и оптимизировать работу с инцидентами и их жизненным циклом.
Единственное, что вряд ли изменится со временем — в нашей команде всегда рады единомышленникам и новым крутым спецам :)