My last post introduced the concept of Configuration as Data (CaD), but it was admittedly abstract. Here’s a more concrete, if simple, example.
Helm (Infrastructure as Code)
Let’s say you want to automatically update a container image tag to rollout each new release of your application. With Helm, you’d template that field of the Kubernetes Deployment something like this:
containers:
- image: {{ .Values.deployment.main.image }}
And add a parameter to the values.yaml file for that environment like this:
deployment:
main:
image: ghcr.io/myorg/myapp:release12345
Now if you wanted to set that image automatically in CI/CD, there are a few potential approaches:
-
You could set it on the
helm upgradecommand line with--set "deployment.main.image=ghcr.io/myorg/myapp:$TAG". -
You could use
yq,sed,awk, or a similar tool to change thevalues.yamlfile:yq -i ".deployment.main.image = ghcr.io/myorg/myapp:$TAG" values.yaml -
You could template the
values.yamlfile and useenvsubstor similar tool to set the value from an environment variable. -
You could write a file that set just that one input value, and use it to override the value in the main
values.yamlfile.
Additional steps would be needed to record the value in git, to enable rollback.
Because the Helm chart template syntax is no longer just YAML, it’s harder to check it for correctness. It could be misindented, contain invalid properties, specify invalid values, be templated incorrectly, violate organizational policies, etc. It needs to be rendered to YAML first using helm template. The output can then be run through validation tools like kubeconform and/or policy tools like kyverno.
If a problem is found after deployment, it needs to be traced back to the template and/or values, and fixed manually (or with AI) due to the unidirectional approach of IaC and the lack of an explicit relationship between deployed resources and the configuration sources. If a change were made directly to the clusters or other systems under management, it would be considered to be drift.
Configuration as Data
With Configuration as Data, the full standard Kubernetes Deployment YAML would be stored, including the image.
apiVersion: apps/v1
kind: Deployment
...
containers:
- name: main
image: ghcr.io/myorg/myapp:release12345
...
You could change the image by executing a command like:
set-image myapp main "ghcr.io/myorg/myapp:$TAG"
And the change could be stored, versioned, and validated automatically. You wouldn’t need to deal with complicated templates. You wouldn’t need to worry about messing up the YAML indentation. You wouldn’t need to perform 10 git commands to make a one-line change.
If you wanted to search for where a specific release was deployed, you could execute a command like:
search-where "apiVersion = 'apps/v1' AND kind = 'Deployment' AND \
spec.template.spec.containers.*.image#reference = ':$TAG'"
You could also get the current image value to see what was currently deployed:
get-image myapp main
In general, you could build tools — CLIs, UIs, and automation systems — to perform common configuration tasks instead of editing templates and values. You could compose multiple reusable tools to edit configuration rather than maintain monolithic templates.
I’ve been managing our own service using this approach for the past several months, and I prefer it to Infrastructure as Code. It’s more transparent, with no obfuscating layers. When I find myself performing the same steps repeatedly, I can write code to reduce friction and toil, and it doesn’t have the built-in toil that git does. When I’m concerned about making mistakes, I can add validation checks. When there’s some part of the configuration I want to see before I make a change, I can extract and display it. When I’m concerned about whether there’s configuration drift, I can refresh the configuration from the live state.
I’ll show what this looks like in more detail in future posts.
Wrap Up
There have been some tools that have modified configuration files locally, but just saving a little editing time is a micro-optimization rather than a macro-optimization. More of the end-to-end workflow needs to be addressed in order for the approach to have enough benefit to consider adopting it over more prevalent and mature alternatives. Making the functionality available through a control plane significantly expands what can be done with the approach.
Have you sought alternatives to existing Kubernetes configuration tools? Have you built a developer portal or platform CLI on top of Helm charts and/or git and wished for less complexity or more flexibility? Have you built such tools on top of cdk8s or Pulumi? If so, what do you think about that approach? Was it for fire-and-forget use cases, or were updates also supported? Were input values stored somewhere?
Feel free to email us at hello@confighub.com, or send me a message on LinkedIn, X/Twitter, or Bluesky.
If you found this interesting, you may be interested in other posts in my Infrastructure as Code and Declarative Configuration series or in my Kubernetes series.
