Приветствую! Меня зовут Ксения, и я — DevOps инженер компании Smartex.
Я люблю создавать инфраструктуру и процессы, которые помогают разработчикам и операционной команде быть более эффективными и продуктивными.
Если ваша повседневная рутина связана с множеством однотипных микросервисов и разнообразными средами, данная информация может быть для вас полезна. Материал рассчитан на Junior+ и Middle DevOps специалистов.
Кейс
К нам обратился клиент, проект которого связан с работой кассовых систем сети супермаркетов, управлением списком товаров, ценами и другими данными. Перед нашей DevOps-командой была поставлена задача — помочь в миграции монолитного приложения из собственной инфраструктуры без контейнеризации в Kubernetes в публичном облаке, с созданием трех окружений — для разработки, для тестирования и для production. Приложение переписывалось на микросервисную архитектуру. Для экономии ресурсов клиента и максимального облегчения жизни разработчиков, мы должны были создать инфраструктуру, в которой разработчики могут сами, используя документацию, развернуть любое количество микросервисов, и в production, и в development-окружении. То есть, по сути создание новых приложений должно происходить с минимальным участием DevOps.
К моменту старта проекта уже было подготовлено несколько микросервисов. Используя Terraform, мы успешно настроили всю необходимую инфраструктуру, включая виртуальную сеть, подсеть, управляемый кластер Kubernetes, управляемую базу данных PostgreSQL и управляемый инструмент для хранения секретов. Также при помощи Terraform мы развернули веб-сервер Nginx Ingress и Argo CD. Все сервисы и микросервисы нашего приложения, включая служебные Helm-чарты, разворачиваются через Argo CD. Но мы столкнулись с рядом недочетов, которые хотелось устранить до запуска production окружения.
Вот какой технический стек мы использовали
Сетап микросервисов выполнен через Argo CD с применением подхода "App of Apps". Концепция "App of Apps" (приложение приложений) в Argo CD — это способ организации и управления несколькими приложениями Kubernetes через одно приложение, которое называется "App of Apps".
Мы создали 3 App of Apps, по одному для каждого окружения. Для каждого Application в Argo CD настроили Automated Sync Policy.
Данный механизм позволяет автоматически синхронизировать состояние приложений с их желаемым состоянием в Git-репозитории. Таким образом триггером для запуска синхронизации является коммит в Git-репозиторий Helm-чартов, который указан в качестве source для приложения.
Для каждого микросервиса создали отдельный Helm-чарт с одинаковыми шаблонами. Для Helm-чартов добавили values для 3 окружений — development, preproduction (тестовый) и production. При этом на все 3 окружения — одна ветка. Вот как на этом шаге выглядит структура Git-репозитория с шаблонами Helm-чартов:
Запустив development-окружение, мы столкнулись со следующими проблемами:
Неудобство администрирования. Без централизованного управления одинаковыми шаблонами для Helm-чартов возрастает риск возникновения ошибок. Мы копировали с места на место шаблоны, делали множество правок в каждой копии. Это вело к ошибкам.
Приходилось создавать branch для каждого окружения, так как Automated Sync Policy в Argo CD для production может привести к выкатке некорректного темплейта. Либо же требовалось создавать отдельные директории для каждого окружения. Такой объем работы не соответствовал изначально выбранной концепции.
Не соблюдается версионирование чартов, вернее версия указывалась вручную, а значит никто этого толком не делал. Работающее разделение чартов по версиям упрощает управление жизненным циклом.
Инфраструктура соответствовала требованиям разработчиков, но администрирование Helm- чартов — тяжелая ручная задача. Поэтому мы решили, что на проекте необходим чарт-репозиторий. Специализированные чарт-репозитории предназначены для решения проблем с версионированием. Наш выбор пал на ChartMuseum.
ChartMuseum — хранилище Helm-чартов, использование которого дает ряд значительных преимуществ в управлении и развертывании приложений с использованием Helm-чартов. Ключевыми преимуществами для нас были:
ChartMuseum обеспечивает локальное хранение Helm-чартов, что дает командам полный контроль над репозиториями чартов и возможность управлять ими в пределах собственной инфраструктуры. Репозиторий хранится прямо внутри кластера, администрируется вместе с его инфраструктурой и всегда под рукой.
ChartMuseum позволяет гибко управлять версиями, обновлениями и релизами Helm-чартов.
Гибкие механизмы аутентификации и авторизации дают контролировать доступ к репозиториям и чартам, поддерживая безопасность работы с ними.
Для такого решения выполнили следующие шаги:
Развернули ChartMuseum.
Создали директорию с новым Helm-чартом, который будет служить источником для всех микросервисов. Мы назвали его
library-chart
.Запушили
library-chart
в ChartMuseum.helm package library-chart -d library-chart/ cd library-chart && curl --data-binary "@library-1.0.11.tgz" https:/my-chart-museum/api/charts
Далее корректируем версию в Chart.yaml для микросервисов, которые переводим на новую версию чарта. После каждого изменения обновляем для них dependency:
apiVersion: v2 appVersion: 1.0.11 description: Chart for publishing microservice1 to Kubernetes name: microservice1 type: application version: 1.0.11 dependencies: - name: library version: "1.0.11" repository: https://my-chart-museum
helm dependency update
Данное решение относительно распространено, но для нас закрывает исключительно проблему отсутствия версионирования. У темплейтов теперь есть централизованный источник, но появляются дополнительные шаги при администрировании.
Поэтому мы пришли к решению — применить Multiple Sources for an Application + ChartMuseum, при котором данные для настройки Argo CD-приложения получаются из нескольких источников. Argo CD напрямую обращается к ChartMuseum, директория charts исчезает из Git-репозитория.
Такая «фича» появилась в Argo CD 2.6. На момент написания статьи этот функционал все еще помечен как Beta Feature.
Примеры использования «фичи» Multiple sources for an Application:
Объединение ресурсов из разных репозиториев для приложений на основе микросервисов.
Управление общими библиотеками или общими ресурсами между несколькими командами или репозиториями.
Объединение ресурсов из разных веток Git-репозитория для тестирования или экспериментов.
Управление ресурсами для разных сред (например, development, preproduction и production) в отдельных Git-репозиториях.
Указание файлов значений Helm из внешнего Git-репозитория — в ChartMuseum находится Helm, а в git-репозитории — values*.yaml.
Манифест для приложения в Argo CD выглядит следующим образом:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: microcervice1
namespace: argocd
spec:
project: default
sources:
- repoURL: 'https://my-chart-museum/'
chart: library
targetRevision: 1.0.11
helm:
valueFiles:
- $values/myproject/helm/microservice1/values.yaml
- $values/myproject/helm/microservice2/values-production.yaml
- repoURL: 'https://my-gitlab.com/active/my_repo.git'
targetRevision: master
ref: values
destination:
server: 'https://kubernetes.default.svc'
namespace: mynamespace
syncPolicy:
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
automated:
selfHeal: true
$values
тег ссылается на корневую директорию репозитория my_repo
, на который указывает ключ ref
в списке источников. Переменная $values
может быть указана только в начале пути к файлу значений. Соответственно, my_repo
выступает в роли источника values-файлов для микросервисов.
Структура становится чище и понятней, править нужно только library-chart
, появляется единая точка входа конфигураций:
Вот как происходит изменение версии Helm-чарта в нашей текущей реализации:
После изменения темплейтов фиксируем новую версию в Chart.yaml и пушим в ChartMuseum:
helm package library-chart -d library-chart/ cd library-chart && curl --data-binary "@library-1.0.12.tgz" https:/my-chart-museum/api/charts
Мы выполняли этот шаг вручную, так как после запуска инфраструктуры такие изменения сразу же стали крайне редки. Но этот шаг легко автоматизировать через CI/CD по коммиту.
Корректируем версию в манифесте приложения:
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: microcervice1 namespace: argocd spec: project: default sources: - repoURL: 'https://my-chart-museum/' chart: library targetRevision: 1.0.12
После выполнения Auto-sync в Argo CD происходит деплой новой версии чарта.
На какие особенности стоит обратить внимание
Параметры приложения не получится проверить и поправить через Argo CD. Для кого-то отсутствие такой возможности является большим минусом. Для нас это скорей плюс, так как даже если руки чешутся поправить параметры через Argo CD, сделать это не получится. Для концепции GitOps такая особенность — большое преимущество, так как единственным источником параметров будет служить Git-репозиторий.
Нет возможности сделать Rollback через UI Argo CD - “Rollback is not supported for apps with multiple sources”. В нашем случае это не проблема, так как мы применяем Argo Rollout c blue-green deployment. Трафик переключается на под только после прохождения анализа. Но для многих отсутствие данной возможности может быть критично. На исправление данного ограничения открыт pull request.
Итак. Какие преимущества мы получили
Ускорился процесс добавления нового микросервиса. Со стороны Git-репозитория добавляется директория микросервиса и values файлы для 3 окружений, а также добавляется манифест приложения Argo CD для каждого окружения. Для всех окружений в качестве источника выступает master branch.
Значительно упрощается процесс администрирования Helm-чартов. При этом нет необходимости в разнесении Helm-для различных окружений по отдельным веткам либо директориям.
Снизилась вероятность возникновения ошибки при изменениях в Helm-чартах.
Применение решения Multiple sources Argo CD + ChartMuseum для управления микросервисами на нашем проекте помогло оптимизировать процессы разработки, снизить расходы времени и риски возникновения ошибок в конфигурации.
Разработчики получили возможность добавлять новые микросервисы, не привлекая DevOps и с низкими шансами на ошибку, что соответствует основному требованию проекта.