Multi-app layout

Ship several apps together with root.kdef: shared namespaces, service accounts, and ingress defaults.

When a repository ships several apps together (api + web + worker, or a full stack deployed as a unit), the root.kdef file at the top lets you declare shared state once and have every sub-project pick it up.

Repository layout

repo/
├── root.kdef              ← namespaces, service accounts, app list
├── vars.kdef              ← shared variables, ingress defaults
├── images.kdef            ← shared image registry
├── configmaps.kdef        ← shared configmaps (parsed once)
├── secrets.kdef           ← shared sealed secrets (parsed once)
├── api/
│   ├── vars.kdef          ← overrides for api only
│   └── app.kdef           ← deployment "api"
├── web/
│   └── app.kdef           ← deployment "web"
├── worker/
│   └── app.kdef           ← deployment "worker"
└── environments/
    ├── staging.kdef
    └── production.kdef

root.kdef

# root.kdef
namespaces = ["production", "staging"]

service_account "default" {
  image_pull_secrets = ["regcred"]
}

ingress_defaults {
  tls    = true
  issuer = "letsencrypt-production"
  annotations = {
    "nginx.ingress.kubernetes.io" = {
      "force-ssl-redirect" = "true"
    }
  }
}

deployments = {
  "api" = {
    path            = "api"
    namespace       = "production"
    service_account = "default"
  }
  "web" = {
    path            = "web"
    namespace       = "production"
    service_account = "default"
  }
  "worker" = {
    path      = "worker"
    namespace = "production"
  }

  # Same api, different namespace, different vars: staged copy
  "api-staging" = {
    path            = "api"
    namespace       = "staging"
    service_account = "default"
    env             = "staging"
    set             = { "replicas" = "1" }
  }
}

What you don't have to repeat

  • namespace: injected into every block in every sub-project that doesn't already have one
  • service_account: injected into every deployment/cronjob that doesn't already have one
  • ingress_defaults: applied to every ingress
  • configmaps.kdef / secrets.kdef: parsed once at the root, visible from every sub-project

Running it

kdef validate --dir repo/               # validates all apps
kdef render   --dir repo/               # renders all apps
kdef diff     --dir repo/ --env staging # diffs all apps
kdef apply    --dir repo/ --env prod    # applies all apps

One command, every app. No for-loops in your deploy script.

Variable scoping

Variables follow the directory tree. A vars.kdef at the root is visible everywhere; a vars.kdef inside api/ is only visible to api/**, and overrides the root on name collision.

repo/
├── vars.kdef        # { environment = "staging" }: default for everyone
└── api/
    └── vars.kdef    # { replicas = 3 }: only api sees this

Same for images {} blocks: a deeper images.kdef overrides a shallower one for that sub-tree.

Full reference

See Reference → Block types → root.kdef.