nxs-universal-chart v3: переход к модульной архитектуре
Модульный подход к Helm, который упрощает развёртывание приложений и инфраструктуры в Kubernetes
Релиз nxs-universal-chart 2.8.3 состоялся более двух лет назад, и за это время Kubernetes-экосистема заметно изменилась. Ingress Nginx постепенно ушёл в прошлое, GitOps стал стандартным подходом к управлению инфраструктурой, а ИИ всё активнее входит в повседневные и бизнес-процессы. Эти изменения не могли не повлиять на наши подходы к DevOps и заставили пересмотреть архитектуру и возможности проекта.
Результатом стал релиз новой версии nxs-universal-chart v3.x. Мы постарались превратить универсальный набор встроенных шаблонов в модульную платформу для поставки приложений в Kubernetes, уделив особое внимание надёжности, расширяемости и современным практикам CI/CD.
В этой статье Пётр Рукин, инженер компании НИКСИС и maintainer проекта nxs-universal-chart, рассказывает, как изменилась первоначальная идея проекта и какие нововведения появились в чарте.
Новая идеология
Главная идея версии 3.x заключается в том, чтобы сделать nxs-universal-chart не просто универсальным шаблоном «на все случаи жизни», а предсказуемым и масштабируемым инструментом для команд с разным уровнем зрелости.
В первую очередь мы формализовали конфигурацию. Для этого используется values.schema.json, который задаёт строгий контракт для values и позволяет обнаруживать ошибки ещё до развёртывания.
Отдельное внимание уделили GitOps-сценариям. Рендеринг должен быть предсказуемым, чтобы одинаковая конфигурация приводила к одинаковому результату и не создавала лишних изменений в Kubernetes-манифестах. Это помогает уменьшить шум в diff и избежать случайных изменений при повторном рендеринге.
Изменилась и модель values. Мы перешли к структуре, ориентированной на ресурсы Kubernetes и их семейства, вместо набора разрозненных параметров.
Новая модель sub-charts
Следующим важным шагом стал переход к модели nuc-* sub-charts.
Раньше все шаблоны интеграций находились внутри основного чарта. Такой подход был удобен на начальном этапе, но по мере роста проекта становилось всё сложнее поддерживать существующие интеграции, тестировать их и добавлять новые возможности.
Кроме того, здесь есть концептуальная проблема.
Когда мы разворачиваем или удаляем приложение, обычно не хочется выполнять отдельные операции для каждого его компонента: Ingress, Service, Deployment и так далее. Логичнее воспринимать приложение как единое целое, включающее также Secret, Issuer, ServiceMonitor, autoscaler и другие необходимые ресурсы.
При этом иногда требуется отдельно описать или использовать только один из этих элементов, не подтягивая за собой весь основной чарт.
В версии 3.x мы решили разделить эти сценарии.
Логика интеграций была вынесена в отдельные OCI-зависимости — самостоятельные Helm-чарты семейства nuc-*. Их можно подключить к общему nxs-universal-chart либо использовать изолированно.
Такой подход даёт несколько преимуществ:
- Основной чарт становится легче и чище. Он отвечает за базовые Kubernetes-ресурсы и общую логику рендеринга.
- Специализированные интеграции могут развиваться независимо от основного чарта. Для них можно писать отдельные тесты, использовать собственное версионирование и обновлять только те компоненты, которые действительно нужны конкретной инфраструктуре. Это также снижает связанность между компонентами и упрощает сопровождение. При необходимости отдельные элементы можно независимо обновлять или откатывать.
- При этом все sub-charts следуют общей логике основного чарта. Это позволяет использовать единый подход к values и объединять отдельные модули в полноценную инфраструктуру.
Таким образом, nxs-universal-chart постепенно превращается в единую точку входа для набора совместимых инфраструктурных модулей.
Например, nuc-vault-secret-operator можно подключить следующим образом:
---
nameOverride: nxs
serviceAccount:
ro-secret:
labels:
component: nxs
nuc-vault-secret-operator:
enabled: true
vaultAuths:
nxs-vault-auth:
namespace: nxs
labels:
component: nxs
method: kubernetes
mount: kubernetes
params:
audience: nxs
kubernetes:
role: devops_service_nxs
serviceAccount: nxs-ro-secret
audiences:
- nxs
tokenExpirationSeconds: 900
vaultStaticSecrets:
nxs-auth:
namespace: nxs
labels:
app: nxs
vaultAuthRef: nxs-vault-auth
mount: nxs-kv
path: apps/nxs-hub-auth
refreshAfter: 10s
destSec: nxs-hub-auth
create: true
destinationType: "kubernetes.io/dockerconfigjson"
restartTargets:
- kind: Deployment
name: nxs-backend
NUC-семейство sub-charts
Переход к модульной архитектуре привёл к появлению целого семейства NUC-модулей. Они разделены по основным направлениям инфраструктуры.
Traffic
- nuc-traefik содержит шаблоны CRD Traefik: IngressRoute, Middleware, TLSOption, TLSStore, ServersTransport и TraefikService.
- nuc-istio отвечает за ресурсы Istio. В версии 3.0.7 его возможности были расширены, в том числе за счёт AuthorizationPolicy, EnvoyFilter, PeerAuthentication, RequestAuthentication, ServiceEntry, Sidecar, Telemetry, WasmPlugin, WorkloadEntry и WorkloadGroup.
- nuc-native-gateway предназначен для работы с нативными ресурсами Kubernetes Gateway API.
MLOps
- nuc-knative содержит ресурсы Knative Serving.
- nuc-kserve — ресурсы KServe для inference и model serving.
Monitoring
- nuc-kube-prometheus-stack предназначен для работы с CRD из экосистемы Prometheus Operator.
- nuc-victoria-metrics содержит шаблоны для VictoriaMetrics Operator.
Infrastructure
- nuc-vault-secret-operator отвечает за ресурсы Vault Secret Operator. В версии 3.0.7 в него были добавлены HCPAuth, HCPVaultSecretsApp, SecretTransformation, VaultAuthGlobal, VaultConnection, VaultDynamicSecret и VaultPKISecret.
- nuc-keda используется для ресурсов KEDA и настройки автоматического масштабирования.
- nuc-certificates содержит ресурсы cert-manager, включая Certificate, Issuer, ClusterIssuer и связанные сущности.
GitOps
- nuc-argocd содержит основные ресурсы ArgoCD.
- nuc-fluxcd — основные ресурсы Flux2.
В результате вместо одного большого набора встроенных интеграций получилась экосистема модулей, каждый из которых отвечает за свою область инфраструктуры.
Inference-контур
Для такого сценария можно объединить сразу несколько NUC-модулей:
- nuc-istio;
- nuc-kserve;
- nuc-knative;
- nuc-vault-secret-operator;
- nuc-kube-prometheus-stack.
Каждый модуль отвечает за свою часть общего контура.
nuc-istio получает и маршрутизирует трафик через Gateway, VirtualService, AuthorizationPolicy и DestinationRule.
nuc-kserve создаёт InferenceService, который направляет запросы к inference-runtime. На уровне Knative сервис разбивается на Route, Configuration и Revision.
nuc-vault-secret-operator позволяет сформировать необходимые Kubernetes Secret с использованием VaultConnection, VaultAuth и VaultStaticSecret.
Для мониторинга nuc-kube-prometheus-stack предоставляет ServiceMonitor и PodMonitor, которые используются для сбора метрик, а PrometheusRule — для описания правил алертинга.
В итоге отдельные модули собираются в единый инфраструктурный контур, при этом каждый из них остаётся независимым и может использоваться отдельно.
Тестирование
- Для ключевых шаблонов используются модульные тесты на базе helm-unittest, которые покрывают основные шаблоны и контракты рендеринга.
- Для контроля обратной совместимости выполняются проверки относительно предыдущих стабильных тегов.
- Проверки включают values.schema.json, контракты рендеринга, примеры конфигурации и валидацию через kubeconform.
- E2E-тесты основаны на kind: чарт разворачивается в реальном Kubernetes API, после чего проверяются основные ресурсы.
- Все чарты автоматически проходят полный набор тестов при слиянии изменений в release-ветки.
- Изменения в шаблонах, values-контрактах и зависимостях проходят несколько автоматических проверок, а не только локальный рендеринг.
- Для каждого репозитория есть Makefile для локального запуска тестов. Инструкции и необходимые зависимости находятся в директории docs.
Оставьте заявку, чтобы обсудить проект
Спасибо за обращение
Мы свяжемся с вами в ближайшее время.