Per-tenant loops
One block, N tenants. Drive a list of deployments from a JSON values file.
Multi-tenant SaaS, per-region deployments, per-customer demo instances: whenever you want the same shape repeated with different parameters, use a for block.
The values file
// values/tenants.json
{
"tenants": [
{ "name": "acme", "domain": "acme.example.com", "plan": "enterprise" },
{ "name": "demo", "domain": "demo.example.com", "plan": "starter" },
{ "name": "beta", "domain": "beta.example.com", "plan": "starter" }
]
}
The variable declaration
# vars.kdef
variable "tenants" {
type = "any"
default = []
}
The loop
# booking.kdef
for "tenant" "var.tenants" {
deployment "booking" {
name = "booking-${tenant.name}"
namespace = "production"
container "booking" {
image = image("booking")
env {
TENANT_ID = tenant.name
TENANT_PLAN = tenant.plan
}
resources {
cpu = tenant.plan == "enterprise" ? "500m..2000m" : "100m..500m"
memory = tenant.plan == "enterprise" ? "512Mi..2Gi" : "128Mi..512Mi"
}
}
scale {
replicas = tenant.plan == "enterprise" ? 3 : 1
}
service {
port "80" "http" {}
}
ingress {
host = tenant.domain
tls = true
}
}
}
Render it
kdef render --dir k8s/ --values values/tenants.json
Output: three full app stacks, each with its own Deployment, Service, Ingress, Certificate, named booking-acme, booking-demo, booking-beta.
Adding a tenant
Edit values/tenants.json, add an entry, run kdef diff: only the new tenant's resources show up in the diff.
Tips
- Keep
values/files in git. They're not secrets. - A
forbody holdsdeployment,daemonset,statefulset,cronjob,configmapandingressblocks, but noifblocks. To vary what a tenant gets, use ternaries on attributes as above; for resources only some tenants need, keep those tenants in a separate list in the values file and give it its ownforblock. - For many tenants (dozens+), render with
kdef render > out.yamlonce and inspect to make sure the output is what you expect before applying.