Timoni

repository·main·Indexed 24 days ago

https://github.com/stefanprodan/timoni

A Kubernetes package manager powered by CUE that provides type-safe, validated, and scalable ways to author, package, and deploy applications. Timoni uses Modules, Bundles, and Instances to manage Kubernetes configurations, replacing Go templates or YAML layering with CUE's type safety and data validation. It distributes modules and bundles as semantically versioned OCI artifacts.

Tokens
52.5K
Snippets
149
Records
246
Agent score
78%

What's inside Timoni

  1. What is Timoni?

    main

    Timoni is a package manager for Kubernetes powered by CUE. It is designed to improve the user experience of authoring Kubernetes configurations by using CUE's type safety, code generation, and data validation instead of Go templates (like Helm) or YAML layering (like Kustomize).

    Note: Timoni is under active development. APIs and the CLI may undergo backwards incompatible changes.

  2. What is a Timoni Instance?

    main
    A Timoni Instance represents a specific instantiation of a module on a Kubernetes cluster. A single module can be installed multiple times on a cluster by assigning each instance a unique name within a namespace. When instantiating, users provide a values.cue file to override module defaults.
  3. What is Flux AIO Distribution?

    main
    Flux All-In-One (AIO) is a lightweight Flux CD distribution built with Timoni. It allows you to run the GitOps Toolkit controllers (source-controller, helm-controller, kustomize-controller, and notification-controller) as a single deployable unit. It is optimized for edge clusters, bare metal clusters without CNI, serverless clusters (like EKS Fargate), and environments requiring strict pod communication policies.
  4. What is a Timoni module?

    main

    A Timoni module is a package that describes how an application can be customized and deployed on Kubernetes using the CUE configuration language.

    Key characteristics include:

    • Composition: A module consists of Kubernetes objects and a well-defined configuration schema.
    • Lifecycle & Testing: Modules can specify how an application's lifecycle is managed and how it should be tested.
    • Distribution: Modules are packaged as Open Container Initiative (OCI) artifacts and distributed via OCI registries.
    • Versioning: Modules use semantic versioning and can be referenced by OCI tags or digests. They can also be cryptographically signed for security.
  5. What is a Timoni Bundle Runtime

    main

    A Timoni Runtime allows you to define configuration values that are not known ahead of time, such as values stored in a Kubernetes cluster (Secrets, ConfigMaps) or environment variables. This enables declarative Bundles to consume dynamic, runtime-available data.

    Timoni provides a Runtime API to fetch values from the Kubernetes API and map them to fields inside a Bundle using the @timoni() attribute.

  6. What is a Timoni Artifact?

    main

    Timoni modules and bundles are distributed as OCI (Open Container Initiative) artifacts. Timoni produces artifacts with specific media types:

    • Image: application/vnd.oci.image.manifest.v1+json
    • Config: application/vnd.timoni.config.v1+json
    • Layer: application/vnd.timoni.content.v1.tar+gzip

    To ensure reproducible builds, Timoni includes Git metadata (last modified date, source URL, and source revision) as annotations.

  7. What is a Timoni Bundle?

    main

    A Timoni Bundle is a declarative way to manage the lifecycle of applications and their infrastructure dependencies. It is defined using a CUE file that groups multiple instances together, specifying their module references, target namespaces, and configuration values.

    When you apply a bundle, Timoni:

    1. Validates the apiVersion.
    2. Fetches module versions from registries (e.g., OCI) using module.url and module.version.
    3. Creates Kubernetes namespaces if they do not exist.
    4. Builds, validates, and creates Kubernetes resources using the provided values.
    5. Stores managed resource metadata in a Kubernetes Secret within the instance's namespace.
    6. Performs a server-side apply dry-run to detect and apply only divergent changes.
    7. Deletes resources that are no longer present in the current bundle revision.
    8. Waits for all resources to become ready.
    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"
    			}
    		}
    	}
    }
  8. Understand the Timoni module file structure

    main

    A Timoni module is organized as a CUE module containing specific directories and files. A typical structure looks like this:

    ├── cue.mod
    │   ├── gen # Kubernetes APIs and CRDs schemas
    │   ├── pkg # Timoni APIs schemas
    │   └── 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
    ├── timoni.ignore # Timoni ignore rules
    ├── values.cue # Timoni values placeholder 
    ├── LICENSE # Module license
    └── README.md # Module documentation
  9. Use string interpolation in CUE

    main

    Interpolate expressions into strings, bytes, or field names using the \(expr) syntax. You can also use the + operator to concatenate strings.

    Examples:

    • "\(kubeLabel)/name" for dynamic field names.
    • "http-\(metadata.name)" for dynamic values.
    • (metadata.name) + "-http" for concatenation.
    nginxSvc: #Service & {
        let kubeLabel = "app.kubernetes.io"
        metadata: {
            name: "nginx"
        }
        spec: {
            selector: {
                "\(kubeLabel)/name": metadata.name
            }
            ports: [{
                name: "http-\(metadata.name)"
            }]
        }
    }
  10. Understand CUE field immutability and merging

    main
    CUE structs support merging: you can define a struct across multiple code blocks in the same package as long as you are not duplicating fields. However, CUE fields are immutable. Once a field is set to a concrete value, it cannot be changed. Attempting to reassign a field to a different value will result in a conflict error during cue eval or cue vet.
  11. Use aliases (let) in CUE

    main

    Define local values using the let keyword. Aliases are not members of the struct and are omitted from the final output. They are useful for intermediate calculations or reusing values within the same scope.

    nginxSvc: #Service & {
        let appName = "nginx"
        metadata: {
            name:      appName
            namespace: appName
        }
        spec: {
            selector: "app.kubernetes.io/name": appName
        }
    }
  12. How Embedding works in CUE

    main

    CUE allows embedding a definition into another using the & operator, similar to OOP composition. This is primarily used to create specialized schemas that further constrain the fields of a base schema.

    When you embed a schema (e.g., #Service) into a new one (e.g., #HeadlessService), the new schema inherits all fields and constraints from the base. If the specialized schema sets concrete values for certain fields, those fields become fixed and cannot be overridden by the instance using the specialized schema.

    #HeadlessService: #Service & {
        spec!: {
            type:      "ClusterIP"
            clusterIP: "None"
        }
    }