Skip to content
Getting Started

Getting Started

Prerequisites

  • A Kubernetes cluster ≥ 1.26 with kubectl configured
  • Argo CD ≥ 3.3 installed in the cluster in the argocd namespace

Argo CD is required. Kokumi delegates all runtime deployment to Argo CD. When a Serving is activated, Kokumi creates or updates an Argo CD Application that points to the immutable OCI artifact of the selected Preparation. Without Argo CD, no workloads will be deployed.

If you don’t have Argo CD installed yet:

kubectl create namespace argocd
kubectl apply -n argocd --server-side --force-conflicts \
    -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.1/manifests/install.yaml

Argo CD registry credentials

The in-cluster registry currently serves plain HTTP. Until proper TLS support is added, register it with Argo CD using insecureOCIForceHttp=true:

kubectl -n argocd create secret generic manifests-registry-creds \
    --from-literal=type=oci \
    --from-literal=url=oci://kokumi-registry.kokumi.svc.cluster.local:5000 \
    --from-literal=insecureOCIForceHttp=true \
    --dry-run=client -o yaml | \
kubectl label -f - argocd.argoproj.io/secret-type=repo-creds --local -o yaml | \
kubectl apply -f -

Install Kokumi

kubectl apply -f \
    https://github.com/kokumi-dev/kokumi/releases/download/0.17.0/install.yaml

Verify the manager is running:

kubectl get pods -n kokumi
# NAME                                READY   STATUS    RESTARTS   AGE
# kokumi-controller-manager-xxx       1/1     Running   0          30s

Create your first Product and Order

A Product is the complete definition of an application: the source OCI artifact, how it is rendered, and its base values and patches.

An Order is a variant of exactly one Product, for example one environment. It only declares what differs: Helm values, patches, where the rendered artifact is pushed, and how it is promoted. Every application has at least one Order; a Product on its own is never rendered or deployed.

This Product renders the podinfo Helm chart, and its Order sets two values:

apiVersion: delivery.kokumi.dev/v1alpha1
kind: Product
metadata:
  name: podinfo
spec:
  # A Helm chart pushed to an OCI registry.
  source:
    url: oci://ghcr.io/stefanprodan/charts/podinfo
    version: "6.14.1"

  # Render the chart with these base values. The release name and namespace
  # default to each Order's name and namespace.
  render:
    helm:
      values:
        ui:
          color: "#EF6461"

  # Orders of this Product may set these values and nothing else. Without
  # overrides, Orders may not change anything.
  overrides:
    values:
      policy: Listed
      paths:
      - ui.message
      - replicaCount
apiVersion: delivery.kokumi.dev/v1alpha1
kind: Order
metadata:
  name: podinfo
spec:
  productRef:
    name: podinfo

  # Deep-merged over the Product's values; the Order's win.
  values:
    ui:
      message: "Hello from Kokumi"
    replicaCount: 2

  # Every change renders a new Preparation, an immutable OCI artifact in the
  # bundled registry. Nothing deploys until you promote a Preparation.
  promotion:
    mode: Manual

The Order’s values are deep-merged over the Product’s spec.render.helm.values; the Order’s settings win. An Order may only change what the Product’s overrides allow (see Restrict what Orders may change). Every Order pushes its Preparations to the bundled registry, below its namespace, unless it names another spec.destination.

Apply both to a new namespace, straight from the repository:

kubectl create namespace shop
kubectl apply -n shop -k "https://github.com/kokumi-dev/kokumi//examples/getting-started?ref=0.17.0"

The files live in examples/getting-started, next to more examples of what Kokumi does. The e2e tests apply every example the same way and check that it does what its docs say.

Kinds of sources

Kokumi renders four kinds of OCI artifacts. A Preparation holds the result:

SourceProductA Preparation holdsExample
A Helm chartspec.render.helmmanifest.yaml, the rendered chartgetting-started
YAML files at the artifact’s rootnothingone manifest.yaml, the files mergedmanifest-bundle
YAML files at the artifact’s rootspec.render.manifest.layout: Multithe files, as they aremulti-file-manifests
A kustomization.yaml at the artifact’s rootnothingthe files, as they are; Argo CD builds the kustomizationkustomize

Orders patch every kind of source with spec.patches, which set fields by path; Helm values are only for charts.

apiVersion: delivery.kokumi.dev/v1alpha1
kind: Product
metadata:
  name: external-secrets
spec:
  # An OCI artifact with a single manifest.yaml at its root. Several files are
  # merged into one manifest.yaml unless render.manifest.layout is Multi.
  source:
    url: oci://ghcr.io/kokumi-dev/testdata/external-secrets
    version: "0.1.0"

  # Orders of this Product may only scale the webhook Deployment.
  overrides:
    patches:
      policy: Listed
      targets:
      - target:
          kind: Deployment
          name: external-secrets-webhook
        paths:
        - .spec.replicas
apiVersion: delivery.kokumi.dev/v1alpha1
kind: Order
metadata:
  name: external-secrets
spec:
  productRef:
    name: external-secrets

  # Patches set fields of the rendered manifests, by path. Values are strings.
  patches:
  - target:
      kind: Deployment
      name: external-secrets-webhook
    set:
      .spec.replicas: "2"

Add another variant

More Orders of the same Product are its other variants, for example a production environment that runs more replicas, deploys a change only after podinfo ran it healthily for an hour, and needs approvals:

apiVersion: delivery.kokumi.dev/v1alpha1
kind: Order
metadata:
  name: podinfo-prod
spec:
  productRef:
    name: podinfo

  values:
    replicaCount: 3
    ui:
      message: "Hello from production"

  promotion:
    mode: Manual
    after:
      - order: podinfo
        soakSeconds: 3600
    approvals:
      requiredApprovals: 2
      allowedGroups:
        - release-approvers

The source version is set only on the Product. Changing it renders a new Preparation for every Order of the Product, and each Order promotes its own Preparation on its own terms: once podinfo is promoted, podinfo-prod waits until podinfo ran the change healthily for an hour, and for its approvals. Nothing is copied from podinfo to podinfo-prod; see Promotion Pipelines. The productRef of an Order cannot be changed after creation.

Watch a Preparation being created

Kokumi automatically reconciles the Order and produces an immutable Preparation. You never create Preparations manually. Every Order change produces a new one and the full history is retained indefinitely.

kubectl get preparations -n shop --watch
# NAME                   ORDER     READY   REASON   CREATED   AGE
# podinfo-d7ce0c46a686   podinfo   True    Ready    5s        5s

Activate with a Serving

A Serving points Argo CD at the selected Preparation’s immutable OCI artifact. There is exactly one Serving per Order, and it is created and managed automatically — you never write a Serving manifest yourself.

Two ways to activate or change a Serving:

MethodHow
Auto-deploySet spec.promotion.mode: Automatic on the Order. Kokumi deploys every new Preparation once it is ready and passes its gates
UISet spec.promotion.mode: Manual and click Promote on any Preparation in the Kokumi UI

Both modes hold a Preparation until it passes its gates: its upstream stages (spec.promotion.after, see Promotion Pipelines), its promotion checks, and its approvals. To require reviews, add spec.promotion.approvals to the Order. Reviewers vote in the UI; see Approvals.

Once activated, Kokumi creates a matching Argo CD Application in the argocd namespace and Argo CD syncs the manifests into the cluster.

Opt-in update protection. Kokumi will only update an Argo CD Application it did not create if the Application is annotated with delivery.kokumi.dev/allowed-order: "<order-name>" matching the Order that owns the Serving. When Kokumi creates the Application itself, this annotation is added automatically. If a pre-existing Application is missing the annotation (or has a different value), Kokumi refuses to modify it and surfaces the failure on the Serving’s status condition with the message Cannot update Argo CD Application, opt-in annotation must exist. Deleting the Serving deletes its Application only if it carries the matching annotation; any other Application is kept.

kubectl get servings -n shop
# NAME      ORDER     TARGET                 READY   REASON     APPROVED              VERIFIED             AGE
# podinfo   podinfo   podinfo-d7ce0c46a686   True    Deployed   ApprovalNotRequired   SignaturesVerified   10s

kubectl get applications -n argocd
# NAME      SYNC STATUS   HEALTH STATUS
# podinfo   Synced        Healthy

To roll back, promote any previous Preparation. No re-rendering required.

Restrict what Orders may change

A Product decides what its Orders may change with spec.overrides, for example when a platform team owns the Product and application teams own its Orders. Helm values and patches each have a policy:

policyOrders may set
None (default)nothing
Listedonly what is listed in paths (values) or targets (patches)
Allanything

The getting-started Product lets its Orders set two Helm values, and the kustomize Product lets them scale one Deployment:

spec:
  overrides:
    values:
      policy: Listed
      paths:
      - ui.message
      - replicaCount
    patches:
      policy: Listed
      targets:
      - target:
          kind: Deployment
          name: podinfo
        paths:
        - .spec.replicas

Here Orders may only set the listed Helm value paths and patch the listed targets and paths; the patch policy applies to edits made in the UI too. A target without a namespace matches the resource in any namespace. An Order that sets anything else fails with a ProcessingFailed condition that names the offending value or patch.

Access the UI

Kokumi includes a web UI and API server deployed alongside the controller. Port-forward the server service to access it locally:

kubectl port-forward -n kokumi svc/kokumi-server 8080:80

Then open http://localhost:8080 in your browser.

The UI requires authentication. The default credentials are:

UsernamePassword
adminadmin

Change the password before any non-development use. See the Operator Guide — Authentication for how to rotate the credentials Secret, manage the token signing key (kokumi-server-tokens), and configure the admin account via the Kitchen resource. The server picks up changes to the Secret and the Kitchen resource automatically; no restart is needed.

The UI lets you browse Products and their Orders, Preparations, and Servings, create an Order of a Product with one click, preview what a Product or Order renders, promote a Preparation to active, and view Argo CD sync status in real time.

Using a private registry

If your source lives in a private registry, store the credentials in a kubernetes.io/dockerconfigjson Secret, create a Registry for the part of the registry they are for, and list it on the Product, as the private-registry example does:

kubectl create secret docker-registry my-org-credentials -n shop \
    --docker-server=ghcr.io --docker-username=<user> --docker-password=<token>
apiVersion: delivery.kokumi.dev/v1alpha1
kind: Registry
metadata:
  name: my-org
spec:
  # The part of the registry the credentials are for. Products and Orders that
  # list this Registry in registryRefs connect through it to every location
  # below this URL.
  url: oci://ghcr.io/my-org
  # A kubernetes.io/dockerconfigjson Secret in the same namespace. Only who
  # may read the Secret may name it here.
  secretRef:
    name: my-org-credentials

The Product’s Registries authenticate its source, its images and its vendored copy; an Order lists the Registries of its own destination. See Registries and Repositories for which credentials every location uses and what Argo CD and the nodes need.

Next steps

Last updated on