Environment overrides

Run the same kdef project against staging, production, and anything else, without duplicating files.

You have one deployment. It needs to run in staging with 1 replica, in production with 5 replicas and a different image tag. With Kustomize you'd build an overlays/ tree. With kdef you write one override file per environment.

The pattern

k8s/
├── vars.kdef
├── images.kdef
├── api.kdef
└── environments/
    ├── staging.kdef
    └── production.kdef

environments/production.kdef

use_vars {
  environment = "production"
  image_tag   = "v2.4.1"
}

override "app" "api" {
  scale {
    replicas = 5
  }
}

environments/staging.kdef

use_vars {
  environment = "staging"
  image_tag   = "staging-latest"
}

override "app" "api" {
  scale {
    replicas = 1
  }
}

Render and deploy

# Default (no env flag): uses vars.kdef defaults
kdef render --dir k8s/

# Staging
kdef render --dir k8s/ --env staging
kdef diff   --dir k8s/ --env staging
kdef apply  --dir k8s/ --env staging

# Production
kdef render --dir k8s/ --env production
kdef apply  --dir k8s/ --env production

What goes where

Belongs in Example
vars.kdef Variable declarations with defaults. Ingress defaults. Imports.
environments/*.kdef Per-environment variable values (use_vars) and per-deployment override blocks.
values/<env>.json Complex values: lists, maps, multi-line strings. Load with --values.
CLI flags One-off overrides: --set image_tag=v1.2.3.

Precedence, highest wins:

  1. --set / --values CLI flags
  2. use_vars in the loaded environments/<env>.kdef
  3. Per-deployment env / set in root.kdef
  4. Global env / set in root.kdef
  5. default on the variable declaration

override blocks

override "app" "<name>" targets a deployment (or statefulset) by name. As of kdef v0.7.5 an override changes the replica count only:

override "app" "api" {
  scale {
    replicas = 5
  }
}

Containers, env vars and other nested blocks can't be overridden this way; an override file that contains them fails to parse. Make the value a variable in the base file instead and set it per environment.

Tips

  • Keep environments/*.kdef small. If it's getting long, your base file is probably missing an abstraction: pull the shared parts up.
  • CI pipelines usually pass --env from the branch name or a pipeline parameter: kdef apply --dir k8s/ --env "$DEPLOY_ENV".
  • Combine with GitOps: commit environments/production.kdef, let Flux/ArgoCD apply it on merge to main. See GitOps → Flux.