Timoni
Timoni is a package manager for Kubernetes, powered by CUE and inspired by Helm.
The Timoni project strives to improve the UX of authoring Kubernetes configs. Instead of mingling Go templates with YAML like Helm, or layering YAML on top of each-other like Kustomize, Timoni relies on cuelang's type safety, code generation and data validation features to offer a better experience of creating, packaging and delivering apps to Kubernetes.
Development phase
Timoni in under active development and is still in its infancy. The APIs and interfaces may change in a backwards incompatible manner.
Concepts
Timoni Modules
A Timoni module contains a set of CUE definitions and constraints organised
into a CUE module
with an opinionated structure.
A module accepts a set of values supplied by the user as values.cue
files,
and outputs a set of Kubernetes objects that Timoni deploys on Kubernetes.
Module structure:
├── cue.mod
│ ├── gen # Kubernetes types
│ └── module.cue # Module metadata
├── templates
│ ├── config.cue # Config schema and default values
│ ├── deployment.cue # Kubernetes Deployment template
│ └── service.cue # Kubernetes Service template
├── timoni.cue # Timoni entry point
└── values.cue # Timoni values placeholder
Module example
An example module can be found in Timoni's repository at examples/podinfo. The example module is published to GitHub Container Registry and is publicly available at ghcr.io/stefanprodan/modules/podinfo.
Commands for working with local modules:
timoni mod init <module-name>
timoni mod lint <path/to/module>
timoni build <name> <path/to/module> -n <namespace>
timoni apply <name> <path/to/module> -f <path/to/values.cue> --dry-run --diff
OCI Artifacts
Timoni modules are distributed as OCI artifacts and can be stored in container registries which support custom OCI media types. Modules are versioned using strict semantic versioning, the version of a module is used as the OCI artifact tag.
Commands for working with remote modules:
timoni mod push <path/to/module> oci://<module-url> -v <semver>
timoni mod pull oci://<module-url> -v <semver> -o <path/to/module>
timoni mod list oci://<module-url>
Timoni produces artifacts compatible with Docker Hub, GitHub Container Registry, Azure Container Registry, Amazon Elastic Container Registry, Google Artifact Registry, self-hosted Docker Registry and others.
Timoni Instances
A Timoni instance represent a module instantiation on a Kubernetes cluster. A module can be installed multiple times on a cluster by giving its instances unique names per namespace.
When instantiating a module, users can supply their own values.cue
that gets merged with the defaults included in the module:
values: {
ingress: {
enabled: true
className: "nginx"
host: "app.example.com"
}
autoscaling: enabled: true
monitoring: enabled: true
}
Commands for working with module instances:
timoni install <name> oci://<module-url> -v <semver> -n <namespace>
timoni upgrade <name> oci://<module-url> -v <semver> -f <path/to/values.cue>
timoni uninstall <name> -n <namespace>
timoni list -n <namespace>
timoni inspect [module|values|resources] <name> -n <namespace>
timoni status <name> -n <namespace>
The install
and upgrade
commands are aliases of timoni apply
.
To apply the Kubernetes resources belonging to a module instance,
Timoni uses Kubernetes server-side apply and
Flux's drift detection.
The apply command validates all resources with a dry-run apply, and reconciles only the ones with changes to the cluster state.
To recreate immutable resources such as Kubernetes Jobs,
these resources can be annotated with action.timoni.sh/force: "enabled"
.
Timoni's garbage collector keeps track of the applied resources and prunes the Kubernetes objects that were previously applied but are missing from the current revision.
To prevent Timoni's garbage collector from deleting certain
resources such as Kubernetes Persistent Volumes,
these resources can be annotated with action.timoni.sh/prune: "disabled"
.
After an installation or upgrade, Timoni waits for the applied resources to be fully reconciled by checking the ready status of deployments, jobs, services, ingresses, and Kubernetes custom resources.
Timoni Bundles
Timoni bundles offer a declarative way of managing the lifecycle of applications and their infra dependencies.
A Timoni bundle is a CUE file for defining a group of instances together with their values and module references:
bundle: {
apiVersion: "v1alpha1"
instances: {
redis: {
module: {
url: "oci://ghcr.io/stefanprodan/modules/redis"
version: "7.0.9"
}
namespace: "podinfo"
values: maxmemory: 256
}
podinfo: {
module: url: "oci://ghcr.io/stefanprodan/modules/podinfo"
module: version: "6.3.4"
namespace: "podinfo"
values: caching: {
enabled: true
redisURL: "tcp://redis:6379"
}
}
}
}
For deterministic operations, it is possible to pin a module version by its OCI digest:
redis: {
module: {
url: "oci://ghcr.io/stefanprodan/modules/redis"
digest: "sha256:e9137d41b0d263bfaf2a43fc862648ad9dc3a976b4b0fc6e27617ea28ee27d45"
}
}
Bundle example
An example bundle can be found in Timoni's repository at examples/bundles/podinfo.cue. This bundle defines a Redis master-replica cluster and a podinfo instance connected to the Redis instance. The secret values are defined in a separate file which can be kept encrypted or pulled from a secure vault at apply time.
In the bundle files you can use arithmetic operations, string interpolation and everything else that CUE std lib supports.
Commands for working with bundles:
timoni bundle lint -f bundle.cue
timoni bundle apply -f bundle.cue -f bundle_extras.cue --dry-run --diff
timoni bundle delete -f bundle.cue -f bundle_extras.cue
timoni bundle build -f bundle.cue -f bundle_extras.cue
To learn more about bundles, please see the Bundle API documentation.
License
Timoni is Apache 2.0 licensed and accepts contributions via GitHub pull requests.