✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Packaging Model

Kubernetes Packaging Model defines how apps are structured, bundled, and deployed in Kubernetes for consistent, scalable operations.

Kubernetes Packaging Model is the underlying conceptual structure shared by every Kubernetes packaging tool, regardless of specific implementation: a package is the combination of a versioned, parameterized template, a set of environment-specific input values, and a deterministic rendering step that together produce a concrete set of manifests, with an optional release record tracking what was actually installed and when.


The Three-Part Structure of a Package

Template, Values, and Rendering

Every packaging approach, whatever its syntax, separates a reusable template (the structure of the manifests, with placeholders for what varies) from the values supplied for a specific installation (the actual replica count, image tag, or hostname), and a rendering step that deterministically combines the two into concrete, appliable YAML.

# template
spec:
  replicas: {{ .Values.replicaCount }}
# values
replicaCount: 3
# rendered output
spec:
  replicas: 3
Rendered Manifest = f ( Template , Values )

Determinism as a Core Requirement

Rendering the same template with the same values must always produce identical output; a packaging tool whose rendering step depends on ambient state (the current time, a random seed, an unpinned external lookup) undermines the reproducibility that makes packaging valuable in the first place, since the same nominal installation could then produce different manifests on different runs.


The Release Concept

Tracking What Was Actually Installed

Beyond rendering, most packaging tools introduce a release concept, a record of which template version and which values were used for a specific installation, stored either as an in-cluster object (Helm's release secrets) or as the state of a Git repository at a specific commit (the GitOps equivalent).

helm list
NAME      CHART           APP VERSION   REVISION
my-app    mychart-1.2.0   2.0.1         3

Revisions as an Append-Only History

helm history my-app
REVISION   STATUS       CHART
1          superseded   mychart-1.0.0
2          superseded   mychart-1.1.0
3          deployed     mychart-1.2.0

Each install or upgrade of a release is recorded as a new, immutable revision rather than overwriting the previous record, which is what enables a rollback operation to reconstruct exactly what a prior revision's rendered manifests looked like and reapply them.


Declarative Rendering vs. Imperative Reconciliation

Packaging Produces a Snapshot, Not a Live Loop

A critical distinction in the packaging model is that rendering a package produces a one-time snapshot of manifests to be applied, not an ongoing reconciliation process; unlike a controller's reconcile loop, which continuously converges actual state toward desired state, a packaging tool's job ends the moment the rendered manifests are handed off to kubectl apply or an equivalent apply mechanism.

helm template ./chart -f values.yaml | kubectl apply -f -

Where GitOps Extends the Model

GitOps tooling extends the packaging model by continuously re-rendering and re-applying a package whenever its source template or values change in Git, effectively adding a reconciliation loop on top of an otherwise one-shot rendering step, closing the gap between "packaging produces a snapshot" and "the cluster should always match the current package definition."

GitOps Loop = Render + Apply + Watch(Source)

Versioning Within the Model

Package Version vs. Application Version

The packaging model distinguishes the version of the package itself (incremented when the template structure changes) from the version of the application it deploys (the container image tag), since a package can be updated purely to fix a templating bug without any change to the underlying application, or the application can be upgraded without any change to how it is packaged.

# Chart.yaml
version: 1.2.0
appVersion: "2.0.1"

Idempotent Application of Rendered Output

Convergence on Reapplication

Rendered manifests applied through kubectl apply (rather than create) are expected to converge to the same state whether applied once or many times, mirroring the idempotency requirement of a controller's reconcile logic; a packaging tool that renders manifests violating this property, generating a new random name on every render, for instance, breaks the ability to safely reapply a package without unintended side effects.


Relationship to Packaging Scope and Areas

The packaging model is the abstract structure underlying every specific tool covered under packaging and customization areas: Helm's charts and releases, Kustomize's bases and overlays, and configuration languages like CUE all instantiate the same template-values-render-release pattern in different syntaxes, and understanding this shared model is what makes switching between, or combining, these specific tools a matter of translating representation rather than relearning a fundamentally different underlying concept each time.

Template Values Render Release