by zbentley | 2026-01-21 19:52:06+00:00
This is the way. If you manage as much as possible via Terraform with the hashicorp/kubernetes provider, you also get:

- Destruction of obsoleted/destroyed resources.

- Control over apply ordering if the k8s default doesn't do it for you.

- Resource control as granular (or not, if you just want to write big multi-resource "kubernetes_manifest" blocks) as you want.

- A coherent story for moving ownership/grouping of k8s resources between different logical groups of stuff via terraform import/moved blocks.

- Vastly more accurate proposed-changes diff than Argo, Helm, or even Kubernetes itself can provide (Terraform's core execution model is plan-as-canonical-changelist, k8s/helm/argo instead added noop/proposed diffs as an ancillary feature with variable quality).

- The ability to mix in management of non-k8s resources (AWS/GCP/Azure/etc. stuff that k8s resources talk to), which is often simpler than deploying complex Kubernetes controllers that manage those same external resources. Controllers are great if you need lots of complex or self-serve management of external resources, but if you are only ever managing e.g. load balancers in one way in a few places, they can be overkill versus doing it by hand.

The only big drawback of this approach is with CRDs. There's no way to have Terraform that deploys CRDs in the same plan as Terraform that refers to resources of those CRDs' types--not even if you conditionally "count = 0" deactivate management of the CRD resources based on variables or whatnot. To cope with this, you either have to get very good at targeted plan/applies (yuck), or plan/apply multiple Terraform modules in order (which is simple and a good practice, but results in more code and can be unwieldy at first).

All the other drawbacks I've heard to doing it this way are pretty silly, and boil down to:

1. "but everyone uses Argo/Helm!" Okay, lots of people smoke cigarettes too--and if you're deploying charts complex enough that you're having to get into the weeds with 'em, you've already gotten enough familiarity to easily port them into kubernetes-provider HCL anyway.

2. "I don't like terraform/HCL". You do you, I guess, but 90% of the reasons people hate it boil down to either "you're using Terraform like it's 2016 and a lot of massive improvements were released circa 2018-2020", or "the Terraform model forces you to be rigorous and explicit rather than approximate and terse you're mad about it".

Relatedly, I was not impressed with the hashicorp/helm provider and routinely push for folks to go back to the regular Kubernetes provider instead. Architecturally the Helm provider is bad (let's indirect the already-too-complex templating constructs through another templating language! What could go wrong?), and its implementation is also not great--getting diagnostics/log output is harder than it should be, whether old resources are destroyed/replaced/updated-in-place is left left up to Helm itself in complex ways that break with the usual Terraform assumptions, and getting meaningful diffs is tricky (the "manifest" provider experiment exists but is experimental for a reason and causes operational problems--not just erroneous diff output--often).