Timoni — пакетный менеджер для Kubernetes от Stefan Prodan (автора Flux CD). Вместо Go-шаблонов и YAML использует язык CUE для описания, валидации и дистрибуции Kubernetes-приложений через OCI-реестры.
Зачем нужен Timoni, если есть Helm
Helm решает задачу пакетирования, но имеет фундаментальные ограничения: Go-шаблоны поверх YAML не дают типизации, валидация values требует сторонних инструментов (kubeconform), CRD нельзя шаблонизировать, а client-side apply создаёт проблемы при drift detection.
Timoni устраняет эти проблемы:
| Аспект | Helm | Timoni |
|---|---|---|
| Шаблонизация | Go templates + YAML | CUE (типизированный язык) |
| Валидация values | Внешние инструменты | Встроенная через CUE-схемы |
| Применение | Client-side apply | Server-side apply (как Flux) |
| CRD | Только plain YAML | Полная шаблонизация |
| Дистрибуция | Helm-репо или OCI | Только OCI-реестры |
| Группировка | Umbrella charts | Bundles (декларативные CUE-файлы) |
| Подпись/верификация | PGP (provenance) | Cosign keyless |
| Drift detection | Нет | Встроенный |
| Обновление CRD | Игнорирует изменения | Полная поддержка |
Основные концепции
- Module — аналог Helm chart. Пакет на CUE, хранится в OCI-реестре.
- Instance — аналог Helm release. Развёрнутый на кластере модуль с конкретными values.
- Bundle — аналог umbrella chart. Декларативная группа инстансов с зависимостями.
Быстрый старт
Установка:
brew install stefanprodan/tap/timoniДеплой модуля:
timoni -n test apply podinfo oci://ghcr.io/stefanprodan/modules/podinfoTimoni скачает модуль из OCI-реестра, создаст namespace, применит ресурсы через server-side apply и дождётся готовности.
Проверка статуса:
timoni -n test status podinfolast applied 2024-01-20T19:51:17Z
module oci://ghcr.io/stefanprodan/modules/podinfo:6.5.4
digest sha256:1dba385f9d56f9a79e5b87344bbec1502bd11f056df51834e18d3e054de39365
ServiceAccount/test/podinfo Current - Resource is current
Service/test/podinfo Current - Service is ready
Deployment/test/podinfo Current - Deployment is available. Replicas: 1Конфигурация через CUE values
Values задаются в .cue-файлах с полной типизацией:
values: {
resources: requests: {
cpu: "100m"
memory: "128Mi"
}
resources: limits: resources.requests
}Применение с кастомными values:
timoni -n test apply podinfo oci://ghcr.io/stefanprodan/modules/podinfo \
--values qos-values.cueПревью изменений перед апгрейдом:
timoni apply --dry-run --diff -f bundle.cueBundles: группировка приложений
Bundle — декларативный CUE-файл для деплоя группы связанных инстансов. Аналог umbrella chart, но с типизацией, условиями и runtime-значениями.
Пример — Redis + podinfo с кешированием:
bundle: {
apiVersion: "v1alpha1"
name: "podinfo"
instances: {
redis: {
module: {
url: "oci://ghcr.io/stefanprodan/modules/redis"
version: "7.2.4"
}
namespace: "podinfo"
values: maxmemory: 256
}
podinfo: {
module: url: "oci://ghcr.io/stefanprodan/modules/podinfo"
module: version: "6.5.4"
namespace: "podinfo"
values: caching: {
enabled: true
redisURL: "tcp://redis:6379"
}
}
}
}timoni bundle apply -f podinfo.bundle.cueTimoni применит инстансы по порядку, дождётся готовности каждого и отследит дрифт.
Интеграции
GitHub Actions
Timoni предоставляет action для CI/CD — lint, build, push модулей в реестр:
name: Release module
on:
push:
tags: ['*']
permissions:
contents: read
packages: write
jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Timoni
uses: stefanprodan/timoni/actions/setup@main
- name: Lint
run: timoni mod lint ./my-module
- name: Push
run: |
timoni mod push ./my-module \
oci://ghcr.io/${{ github.repository_owner }}/my-module \
--version ${{ github.ref_name }} \
--creds ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}Поддерживается подпись через Cosign keyless — достаточно добавить --sign=cosign к timoni mod push.
GitOps с Flux CD
Timoni может использоваться как templating engine для Flux. Схема: Timoni собирает манифесты, Flux CLI пушит OCI-артефакт, Flux в кластере подхватывает изменения.
timoni -n apps build podinfo oci://ghcr.io/stefanprodan/modules/podinfo \
--values ./staging-values.cue | \
flux push artifact oci://registry.internal/podinfo:staging \
--source="http://github.com/stefanprodan/podinfo" \
--revision="6.3.4" \
--path=-На стороне кластера Flux забирает артефакт по таймеру:
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: podinfo
namespace: flux-system
spec:
interval: 1m
url: oci://registry.internal/podinfo
ref:
tag: staging
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: podinfo
namespace: flux-system
spec:
targetNamespace: apps
interval: 1h
prune: true
wait: true
sourceRef:
kind: OCIRepository
name: podinfoFlux AIO — установка Flux через Timoni
Flux All-In-One — легковесный дистрибутив Flux, упакованный как Timoni-модуль. Оптимизирован для edge-кластеров, serverless (EKS Fargate, GKE Autopilot) и bare-metal без CNI.
Установка Flux через bundle:
bundle: {
apiVersion: "v1alpha1"
name: "flux-aio"
instances: {
"flux": {
module: url: "oci://ghcr.io/stefanprodan/modules/flux-aio"
namespace: "flux-system"
values: {
controllers: {
helm: enabled: true
kustomize: enabled: true
notification: enabled: true
}
hostNetwork: false
securityProfile: "privileged"
}
}
}
}timoni bundle apply -f flux-aio.cueДоступны дополнительные модули:
- flux-oci-sync — синхронизация из OCI-реестра
- flux-git-sync — синхронизация из Git
- flux-helm-release — деплой Helm-чартов через Flux
- flux-tenant — мультитенантность с ограниченным доступом
Helm-интероперабельность
Timoni не отвергает Helm — через модуль flux-helm-release можно оркестрировать деплой Helm-чартов:
bundle: {
apiVersion: "v1alpha1"
name: "flux-aio"
instances: {
"flux": {
module: url: "oci://ghcr.io/stefanprodan/modules/flux-aio"
namespace: "flux-system"
values: {
hostNetwork: true
securityProfile: "privileged"
}
}
"cilium": {
module: url: "oci://ghcr.io/stefanprodan/modules/flux-helm-release"
namespace: "flux-system"
values: {
repository: url: "https://helm.cilium.io"
chart: {
name: "cilium"
version: "*"
}
helmValues: {
operator: replicas: 1
ipam: mode: "kubernetes"
}
sync: targetNamespace: "kube-system"
}
}
}
}Когда выбрать Timoni
Timoni имеет смысл, если:
- Вы уже используете или планируете Flux CD.
- Надоели проблемы с Go-шаблонами и невалидным YAML в Helm.
- Нужна строгая типизация и валидация values на этапе сборки.
- Хотите server-side apply с drift detection из коробки.
- Работаете с CRD, которые нужно шаблонизировать и обновлять.
- Нужна подпись модулей через Cosign/Sigstore.
Когда оставаться на Helm:
- Огромная экосистема готовых чартов (Bitnami, etc).
- Команда не готова осваивать CUE.
- Инструментарий вокруг Helm (ArgoCD, Helmfile) уже отлажен.