Вы просматриваете документацию для Cozystack v1.4. Документация последней версии доступна по ссылке: v1.5.

Cozystack Руководство по разработке

Cozystack Руководство по разработке

Как это работает

Cozystack — платформа на основе операторов. Начальная загрузка и текущее управление осуществляются набором контроллеров, работающих внутри кластера. Высокоуровневый поток выглядит так:

  1. Инсталлятор чарта (packages/core/installer) применяется через helm install. Он разворачивает Deployment cozystack-operator в пространстве имён cozy-system.

  2. cozystack-operator запускается и выполняет однократную начальную загрузку:

    • Устанавливает CRD Cozystack (Package, PackageSource) из встроенных манифестов (internal/crdinstall).
    • Устанавливает компоненты Flux (source-controller, helm-controller, source-watcher) из встроенных манифестов (internal/fluxinstall).
    • Создаёт начальный OCIRepository (cozystack-platform) из значений platformSourceUrl и platformSourceRef, заданных в инсталляторе.
    • Создаёт PackageSource, ссылающийся на начальный OCIRepository.
  3. Цикл согласования берёт управление. Оператор следит за CRD PackageSource и Package и преобразует их в объекты Flux HelmRelease. Flux затем устанавливает реальные Helm-чарты и управляет ими.

  4. Platform chart (packages/core/platform) разворачивается как обычный Package. Он читает конфигурацию кластера из ресурса cozystack.cozystack-platform Package и создаёт шаблоны манифестов пакетов, определяющих, какие системные компоненты должны быть установлены.

    Platform chart также создаёт вторичный OCIRepository (cozystack-packages), копируя спецификацию из начального OCIRepository. Все PackageSource ссылаются на этот вторичный репозиторий. При обновлениях platform chart выполняет миграции как pre-upgrade хуки перед созданием или обновлением HelmRelease компонентов.

  5. FluxCD — движок выполнения, он согласует объекты HelmRelease, созданные оператором, загружает артефакты чартов из ресурсов ExternalArtifact и применяет их к кластеру.

Полную цепочку согласования (PackageSource → ArtifactGenerator → ExternalArtifact → Package → HelmRelease → Pods), разрешение зависимостей, потоки обновления и отката, а также CLI cozypkg см. в разделе Ключевые концепции.

OCIRepository и поток миграции

Cozystack использует два ресурса OCIRepository для управления обновлениями платформы:

OCIRepositoryСоздаётсяСсылается на
cozystack-platformcozystack-operatorНастраивается через значения инсталлятора (platformSourceUrl, platformSourceRef)
cozystack-packagesPlatform chart (repository.yaml)Копирует спецификацию из cozystack-platform

Все PackageSource в packages/core/platform/sources/ ссылаются на cozystack-packages.

Выполнение миграций

Миграции выполняются как Helm pre-upgrade хуки в platform chart:

# packages/core/platform/templates/migration-hook.yaml
metadata:
  name: cozystack-migration-hook
  annotations:
    helm.sh/hook: pre-upgrade,pre-install
    helm.sh/hook-weight: "1"

Контейнер миграции считывает текущую версию из ConfigMap cozystack-version и выполняет скрипты миграции последовательно от CURRENT_VERSION до TARGET_VERSION - 1. Каждая миграция обновляет ConfigMap при успехе, обеспечивая идемпотентность миграций и возможность возобновления после сбоев.

Зачем два репозитория?

Разделение гарантирует, что:

  1. Начальный OCIRepository управляется оператором (через значения инсталлятора).
  2. Все PackageSource имеют согласованную ссылку (cozystack-packages), а не указывают напрямую на источник, управляемый оператором.
  3. Platform chart может выполнять миграции перед созданием вторичного OCIRepository, гарантируя выполнение миграций до обновления компонентов.

Ключевые бинарные файлы

Бинарный файлИсточникРоль
cozystack-operatorcmd/cozystack-operatorНачальная загрузка (CRD, Flux, источник платформы), согласование PackageSource и Package, репликация секрета cozystack-values.
cozystack-controllercmd/cozystack-controllerСогласование рабочих нагрузок и ApplicationDefinition, управление дашбордами.
cozystack-apicmd/cozystack-apiУровень агрегации API Kubernetes для групп API apps.cozystack.io и core.cozystack.io.
cozypkgcmd/cozypkgCLI-инструмент для управления пакетами — визуализация зависимостей, интерактивная установка и удаление.

Структура репозитория

Основная структура репозитория cozystack:

.
├── api             # Go-типы для CRD Cozystack (Package, PackageSource и т.д.)
├── cmd             # Точки входа для всех бинарных файлов
│   ├── cozystack-operator      # Основной оператор платформы
│   ├── cozystack-controller    # Контроллеры рабочих нагрузок и приложений
│   ├── cozystack-api           # Агрегированный API-сервер
│   └── cozypkg                 # CLI для управления пакетами
├── internal        # Реализации контроллеров и согласователей
│   ├── operator                # Согласователи PackageSource и Package
│   ├── controller              # Контроллеры рабочих нагрузок и ApplicationDefinition
│   ├── fluxinstall             # Встроенные манифесты Flux и инсталлятор
│   ├── crdinstall              # Встроенные манифесты CRD и инсталлятор
│   └── cozyvaluesreplicator    # Логика репликации секретов
├── packages        # Helm-чарты, организованные по слоям
│   ├── core            # Начальная загрузка и конфигурация платформы
│   ├── system          # Инфраструктурные операторы и upstream-чарты
│   ├── apps            # Пользовательские чарты приложений
│   └── extra           # Чарты приложений для конкретных тенантов
├── pkg             # Общие Go-библиотеки
├── dashboards      # Дашборды Grafana
├── hack            # Вспомогательные скрипты для локальной разработки
└── docs            # Журналы изменений и примечания к релизам

Разработку можно вести локально, изменяя и обновляя файлы в этом репозитории.

Пакеты

core

Core-пакеты отвечают за начальную загрузку и конфигурацию на уровне платформы.

installer

Helm-чарт, разворачивающий Deployment cozystack-operator. Он создаёт пространство имён cozy-system, ServiceAccount с правами cluster-admin и Deployment оператора с флагами, инициирующими установку CRD и Flux при запуске. Образ оператора и URL источника платформы задаются во время сборки.

platform

Helm-чарт, разворачиваемый как обычный Package (не применяется напрямую). Он читает конфигурацию кластера из ресурса cozystack.cozystack-platform Package и создаёт шаблоны манифестов согласно указанному варианту и настройкам компонентов, определяя, какие системные компоненты должны быть установлены.

flux-aio

Компоненты Flux, упакованные для развёртывания оператором.

talos

Конфигурационные ресурсы Talos OS.

system

System-пакеты настраивают систему для управления и развёртывания пользовательских приложений. Необходимые системные компоненты указываются в конфигурации пакета.

System-пакеты включают два вида компонентов:

  • Операторы (например, postgres-operator, kafka-operator, redis-operator): Контроллеры, умеющие управлять полным жизненным циклом конкретного приложения, включая операции второго дня.
  • Upstream Helm-чарты для приложений без выделенного оператора (например, nats, ingress-nginx): Эти чарты размещаются в system, чтобы пакеты apps и extra могли разворачивать их через Flux HelmRelease CR, фактически используя FluxCD в качестве оператора.

apps

Эти пользовательские приложения отображаются в дашборде и включают манифесты для применения к кластеру.

Чарты apps служат высокоуровневым API для пользователей. Они определяют только те параметры, которые должны быть открыты и проверены через values.schema.json, сохраняя интерфейс минимальным и безопасным. Чарты apps не должны содержать бизнес-логику развёртывания самого приложения — вместо этого они делегируют её оператору или FluxCD.

В зависимости от наличия выделенного оператора приложения apps следуют одному из двух паттернов:

Паттерн на основе оператора

Когда для приложения есть выделенный оператор (например, PostgreSQL, MongoDB, Redis, Kafka), чарт app создаёт экземпляры CRD, которыми управляет оператор:

packages/system/postgres-operator/   # Helm-чарт оператора
packages/apps/postgres/              # App-чарт создаёт postgresql.cnpg.io/v1.Cluster CR

Оператор обрабатывает все детали развёртывания и операции второго дня (масштабирование, резервное копирование, переключение при сбое). App-чарт просто создаёт соответствующий CRD со значениями, полученными из пользовательского ввода.

Паттерн на основе HelmRelease

Когда для приложения нет выделенного оператора и стандартным методом развёртывания является Helm-чарт, upstream-чарт размещается в system/, а app-чарт создаёт Flux HelmRelease CR, указывающий на него:

packages/system/nats/                # Upstream Helm-чарт NATS
packages/apps/nats/                  # App-чарт создаёт helm.toolkit.fluxcd.io/v2.HelmRelease

В этом случае FluxCD выступает оператором, управляя жизненным циклом Helm-релиза. App-чарт контролирует, какие upstream-значения открываются пользователю, обеспечивая дополнительный уровень безопасности — пользователи не могут обойти валидацию для развёртывания чарта с произвольными значениями.

Другие примеры этого паттерна: extra/ingress, extra/seaweedfs, extra/monitoring.

extra

Аналогично apps, но не отображается в каталоге приложений. Могут устанавливаться только в составе тенанта. Разрешены для использования нижележащими тенантами, установленными в пространстве имён текущего тенанта.

Подробнее о Системе тенантов читайте на странице основных концепций.

В одном пространстве имён тенанта можно использовать только один тип приложения.

Extra-пакеты следуют тем же двум архитектурным паттернам, что и apps (на основе оператора или HelmRelease).

Структура пакета

Каждый пакет — это типичный Helm-чарт, содержащий все необходимые образы и манифесты для платформы. Мы следуем логике umbrella-чарта, размещая upstream-чарты в директории ./charts и переопределяя values.yaml в корне приложения. Такая структура упрощает обновление upstream-чартов.

.
├── Chart.yaml                           # Определение Helm-чарта и описание параметров
├── Makefile                             # Общие цели для упрощения локальной разработки
├── charts                               # Директория для upstream-чартов
├── images                               # Директория для Docker-образов
├── patches                              # Опциональная директория для патчей upstream-чартов
├── templates                            # Дополнительные манифесты для upstream Helm-чарта
├── templates/dashboard-resourcemap.yaml # Роль для отображения ресурсов k8s в дашборде
├── values.yaml                          # Значения переопределения для upstream Helm-чарта
└── values.schema.json                   # JSON-схема для валидации входных значений и отрисовки элементов UI в дашборде

Use cozyvalues-gen to generate the README.md parameters table and the values.schema.json schema from annotations in values.yaml.

Install the cozyvalues-gen binary from the releases page and run make generate in the package directory. Besides the schema and the README, it also refreshes the package’s ApplicationDefinition (spec.application.openAPISchema and spec.dashboard.keysOrder) via hack/update-crd.sh.

Принципы разработки Helm-чартов

Структура пакетов и рабочий процесс разработки в Cozystack основаны на следующих принципах:

Простое обновление upstream-чартов

Оригинальный upstream-чарт должен быть легко обновляемым, переопределяемым и изменяемым. Мы используем паттерн umbrella-чарта — upstream-чарты находятся в директории ./charts и хранятся в оригинальном виде. Кастомизации вносятся через переопределения values.yaml и дополнительные templates/, а структурные изменения в upstream-чарте применяются через patches/. Такое разделение гарантирует простое обновление до новой upstream-версии: выполните make update, просмотрите diff и при необходимости повторно примените патчи.

Локальные артефакты

Патчи и образы контейнеров хранятся локально и являются частью пакета. Директория patches/ содержит любые изменения upstream-чарта, а директория images/ — Dockerfile для сборки всех необходимых образов. Это обеспечивает полную воспроизводимость — всё необходимое для сборки и развёртывания пакета самодостаточно внутри репозитория.

Рабочий процесс локальной разработки и тестирования

Каждый пакет должен быть легко обновляемым и тестируемым локально на реальном кластере без использования CI. Стандартные цели make (make image, make diff, make apply) обеспечивают быструю обратную связь: сборка образов, сравнение отрендеренных манифестов с живым кластером и применение изменений — всё с рабочей станции разработчика.

Без внешних зависимостей

Пакеты не должны зависеть от внешних ресурсов во время выполнения. Все чарты, образы и патчи включены в репозиторий. Это гарантирует детерминированность сборок и развёртываний, а также отсутствие сбоев из-за недоступности upstream-реестров, удалённых тегов или проблем с сетью.

Разработка

Настройка Buildx

Для сборки образов необходимо установить и настроить плагин docker buildx.

Вместо встроенного сборщика можно настроить дополнительные, которые могут быть удалёнными или поддерживать несколько архитектур. В этом примере показано, как создать сборщик с драйвером kubernetes, позволяющим собирать образы непосредственно в кластере Kubernetes:

docker buildx create \
  --bootstrap \
  --name=buildkit \
  --driver=kubernetes \
  --driver-opt=namespace=tenant-kvaps,replicas=2 \
  --platform=linux/amd64 \
  --platform=linux/arm64 \
  --use

Либо опустите параметры –driver*, чтобы настроить среду сборки в локальном Docker-окружении.

Управление пакетами

Каждое приложение включает Makefile для упрощения процесса разработки. Для каждого пакета мы следуем такой логике:

make update  # Обновить Helm-чарт и версии из upstream-источника
make image   # Собрать Docker-образы, используемые в пакете
make show    # Показать вывод отрендеренных шаблонов
make diff    # Сравнить Helm-релиз с объектами в кластере Kubernetes
make apply   # Применить Helm-релиз к кластеру Kubernetes

Например, для обновления cilium:

cd packages/system/cilium         # Перейти в директорию приложения
make update                       # Загрузить новую версию из upstream
make image                        # Собрать образ cilium
git diff .                        # Показать diff с изменёнными манифестами
make diff                         # Показать diff с применёнными манифестами кластера
make apply                        # Применить изменённые манифесты к кластеру
kubectl get pod -n cozy-cilium    # Проверить корректность работы
git commit -m "Update cilium"     # Зафиксировать изменения в ветке

Для сборки контейнера cozystack с обновлённым чартом:

cd packages/core/installer        # Перейти в директорию пакета cozystack
make image-packages               # Собрать образ пакетов
make apply                        # Применить к кластеру
kubectl get pod -n cozy-system    # Проверить корректность работы
kubectl get hr -A                 # Проверить объекты HelmRelease

Тестирование

Платформа включает скрипт e2e.sh, выполняющий следующие задачи:

  • Запускает три виртуальные машины QEMU
  • Настраивает Talos Linux
  • Устанавливает Cozystack
  • Ожидает установки всех HelmRelease
  • Выполняет дополнительные проверки работоспособности компонентов

Скрипт e2e.sh можно запускать как локально, так и непосредственно в контейнере Kubernetes.

Для запуска тестов в кластере Kubernetes перейдите в директорию packages/core/testing и выполните следующие команды:

make apply    # Создать тестовую песочницу в кластере Kubernetes
make test     # Запустить end-to-end тесты в существующей песочнице
make delete   # Удалить тестовую песочницу из кластера Kubernetes

Динамическая среда разработки

Если вы предпочитаете разрабатывать Cozystack в виртуальных машинах вместо изменения существующего кластера, можно использовать ту же песочницу из тестовой среды. Makefile в packages/core/testing включает дополнительные опции:

make exec     # Открывает интерактивную оболочку в контейнере песочницы.
make login    # Загружает kubeconfig во временную директорию и запускает оболочку с окружением песочницы; требуется установленный mirrord.
make proxy    # Включает SOCKS5 прокси-сервер; требуются mirrord и gost.

Прокси Socks5 можно настроить в браузере для доступа к сервисам кластера, работающего в песочнице. В Firefox есть удобное расширение для переключения прокси: