Как стать автором
Обновить

CI/CD для Helm Charts

Время на прочтение5 мин
Количество просмотров6.6K

Задача

Helm мощный и гибкий инструмент управления ресурсами в Kubernetes.

А что если одним Helm Chart пользуются несколько команд для развертывания своих приложений в Kubernetes? Как гарантировать, что Helm Chart как минимум рендериться после внесения изменений, прежде чем публиковать Helm Chart в репозиторий артефактов? Как гарантировать, что новая версия Helm Chart не "сломает" установку приложения в Kubernetes в критический момент(например во время релиза целевого продукта)?

Этими вопросами задался и я при разработке подобного Helm Chart.

Дополнительные требования к задаче

Надо отметить, что в моем случае, в качестве хранилища артефактов используется JFrog Artifactory внутри организации.

Для репозиториев есть явное деление на группы, в которые разрешено публиковать артефакты. В большинстве случаев под группой понимается groupId из pom.xml файла проекта/модуля.

Аналогичное правило работает и для репозиториев хранения Helm Charts.

Выбор инструмента

В моих проектах используется Apache Maven как инструмент сборки, запуска тестов, упаковки и публикации артефактов.

Под артефактом понимается все то, что создается при сборке проекта: JAR/WAR/EAR-файлы, Docker образы, сопутствующие файлы конфигурации, и тп.

Ок, я умею в Maven.

Ок, я умею в Helm Charts.

Почему бы не совместить эти два инструмента?

Что предлагает сообщество, с точки зрения плагинов для Apache Maven, которые можно использовать для работы с таким зверем как Helm Charts?

Сообщество предлагает два плагина:

  1. https://github.com/kokuwaio/helm-maven-plugin

  2. https://github.com/deviceinsight/helm-maven-plugin

Первый позволяет:

  • довольно гибко настроить подготовку Helm Chart как артефакта

  • позволяет сделать как минимум прогнать Helm Chart через встроенный в Helm линтер

  • позволяет опубликовать Helm Chart в репозиторий таким образом, что Helm Chart будет использоваться только лишь в том случае, если при выполнении helm upgrade добавить аргумент --devel, в данном случае будет использоваться пред-релизная(или developement) версия Helm Chart

Второй - не удовлетворял некоторым моим требованиям, поэтому решил идти в бой с первым!

Настройка

Создадим простой проект типа maven, со следующей структурой каталогов/файлов:

./pom.xml
./src/helm/Chart.yaml
./src/helm/templates/config-map.yaml

Содержимое ./src/helm/Chart.yaml:

apiVersion: v2
name: sample-helm-chart
version: 0.0.0

Тут важно отметить значения поля version - в исходном коде оно всегда будет равно 0.0.0

Содержимое ./src/helm/templates/config-map.yaml :

apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-config-map
data:
  foo: bar

То есть Helm Chart создает объект типа ConfigMap с одним ключом foo и значением bar

А теперь самое интересное, содержимое pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>sample-helm-chart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>helm</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>io.kokuwa.maven</groupId>
                <artifactId>helm-maven-plugin</artifactId>
                <version>6.3.0</version>
                <extensions>true</extensions>
                <configuration>
                    <chartDirectory>${project.basedir}/src/helm</chartDirectory>
                    <chartVersion>${project.version}</chartVersion>
                    <timestampOnSnapshot>true</timestampOnSnapshot>
                    <addDefaultRepo>false</addDefaultRepo>
                    <uploadRepoStable>
                        <name>central</name>
                        <url>https://example.org/artfactory/hlm-all</url>
                        <type>ARTIFACTORY</type>
                        <useGroupId>true</useGroupId>
                    </uploadRepoStable>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Давайте пройдемся по конфигурации плагина в секции <build>:

  • chartDirectory - указывает на корневой каталог, содержащий код Helm Chart

  • chartVersion - связываем версию Helm Chart и версию проекта/модуля

  • timestampOnSnapshot - в случае, если при сборке версия проекта/модуля имеет суффикс -SNAPSHOT - то суффикс будет заменен на текущее время в формате yyyyMMddHHmmss (формат по умолчанию)

  • addDefaultRepo - нам не нужен репозиторий по умолчанию, так как Helm Chart будет публиковаться в хранилище артефактов внутри организации.

  • uploadRepoStable/name - имя/идентификатор сервера из settings.xml . Необходимо в том числе для аутентификации в хранилище артефактов. В settings.xml должны быть заданы значения полей username и password для сервера указанного в данном поле.

  • uploadRepoStable/url - Адрес хранилища артефактов и базовый путь публикации артефакта.

  • uploadRepoStable/type - Тип репозитория. Плагин поддерживает три типа репозиториев.

  • uploadRepoStable/usegGroudId - согласно дополнительным требованиям к задаче, необходимо публиковать артефакты в свои группы. В случае если usegGroudId равен true , тогда, после публикации нашего Helm Chart в хранилище артефактов, Helm Chart из нашего примера можно будет скачать по адресу https://example.org/artfactory/hlm-all/org/example/0.0.1-SNAPSHOT/sample-helm-chart-0.0.1-20220701142516.tgz

Используя дополнительные плагины для Apache Maven, можно настроить автоматический инкремент версии, чтобы можно было выпускать релизные версии Helm Chart.

Пожалуй, самый важный параметр timestampOnSnapshot - зачем он нужен и как он помогает отделить мух от ... в достижении цели?

Как было описано в описании параметров конфигурации плагина:

в случае, если при сборке версия проекта/модуля имеет суффикс -SNAPSHOT - то суффикс будет заменен на текущее время в формате yyyyMMddHHmmss (формат по умолчанию)

Что это дает?

Обратимся к справке по SemVer2:

A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.–.

То есть, если в значении версии, помимо главных атрибутов <MAJOR>.<MINOR>.<PATCH>, есть некий суффикс(в нашем случае текущее время), то это считается пред-релизной версией, или с точки зрения Helm - development версией, а значит, когда выполняется команда helm upgrade будет использоваться только релизная версия Helm Chart, если таковая имеется в репозитории.

Если есть необходимость использовать пред-релизную(или development) версию Helm Chart - надо явно "сказать" Helm'у с помощью аргумента: helm upgrade --devel .

Заключение

Перед тем как имплементировать решение внутри организации, используемый плагин не поддерживал ряд функциональности, которая вытекала из Дополнительных требований к задаче, а так как у меня есть небольшой опыт написания плагинов для Apache Maven - я добавил недостающую функциональность в плагин.

Но самое сложное было то, что плагин давно не выпускался и пришлось не мало "побегать" за владельцами плагина. Благо ребята оказались отзывчивые и мы дружно вдохнули новую жизнь в плагин!

Как вы считаете нужен ли релизный цикл для таких вещей как Helm Charts?

Теги:
Хабы:
Всего голосов 4: ↑2 и ↓20
Комментарии1

Публикации

Истории

Работа

DevOps инженер
43 вакансии

Ближайшие события