Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 10 min read

Converting Raw Kubernetes Manifests Into a Helm Chart With AI

Got a folder of plain YAML you redeploy by hand? Use AI to templatize it into a parameterized Helm chart, then verify the render matches the originals.

  • #kubernetes
  • #helm
  • #templating
  • #ai

We had a k8s/ directory full of plain manifests that we deployed to three environments by copy-pasting the folder and hand-editing the image tag, the replica count, and the ingress host every single time. It worked until someone edited the wrong copy and pushed a staging hostname to production. The right answer was to fold those manifests into a single parameterized Helm chart. The grunt work of templatizing — pulling the environment-specific bits into values.yaml, wrapping fields in {{ }}, getting the indentation right — is exactly what an AI model does quickly, while I stay responsible for deciding what should be a value and verifying the result renders identically.

Why templatize at all

Raw manifests are fine until you need the same app in more than one place. The moment you do, you’re choosing between maintaining N copies that drift apart or having one source of truth with the differences pulled out as parameters. Helm is the parameterized-source-of-truth option. The conversion is mechanical but fiddly, and getting the templating wrong produces invalid YAML — which is why it’s a good delegation with a tight verification loop.

Hand the model your manifests

The manifests are config and code, safe to share after I scrub any inline secrets or internal hostnames I’d rather not expose. The model never sees my cluster — converting manifests to a chart is a pure text transformation that happens entirely locally. My prompt sets the boundaries of what becomes a parameter:

Here are four Kubernetes manifests: a Deployment, Service, Ingress, and ConfigMap. Convert them into a Helm chart. Parameterize image repository and tag, replica count, ingress host, and resource requests/limits into values.yaml with sensible defaults. Keep everything else as static template files. Generate Chart.yaml, values.yaml, and the templated files under templates/.

I’m explicit about what to parameterize because, left to its own judgment, a model will either over-parameterize (turning every field into a value, which makes the chart unusable) or under-parameterize (hard-coding the things that actually differ between environments). I want a deliberate, short list.

What the chart scaffold looks like

The model produces the standard chart layout. A templated Deployment field comes back like this:

spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

And the matching values.yaml:

replicaCount: 2
image:
  repository: registry.example.com/app
  tag: "1.4.0"
ingress:
  host: app.example.com
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 256Mi

The nindent 12 for the resources block is the kind of detail that’s easy to get wrong by hand and that the model usually gets right — but I verify it, because off-by-one indentation is the most common failure in templatized charts.

The critical verification: render must match the original

This is the step that makes the whole thing trustworthy. A converted chart is only correct if, with the original values, it renders byte-for-byte equivalent to the manifests you started from. I check that directly:

# Render the new chart with defaults matching the original
helm template ./app-chart > /tmp/rendered.yaml

# Compare against the original manifests (normalized)
diff <(kubectl apply --dry-run=client -f k8s/ -o yaml) \
     <(kubectl apply --dry-run=client -f /tmp/rendered.yaml -o yaml)

If that diff is empty, the conversion preserved behavior and I can trust the parameterization. If it isn’t, every difference is a bug introduced by templating — a dropped field, a changed default, a botched indent. I don’t move on until the diff is clean.

Pro Tip: Normalize both sides through kubectl apply --dry-run=client -o yaml before diffing. It sorts keys and fills defaults consistently, so the diff shows real differences instead of cosmetic ordering noise that would otherwise bury the one field that actually changed.

Build the per-environment values files

Once the chart renders cleanly, the payoff is replacing those copy-pasted folders with small overrides files:

# values-prod.yaml — only the differences
replicaCount: 5
image:
  tag: "1.4.0"
ingress:
  host: app.example.com
# values-staging.yaml
replicaCount: 1
ingress:
  host: app.staging.example.com

Now there’s one chart and one tiny file per environment, and the “wrong hostname in prod” mistake becomes structurally hard to make. I have the model draft these from the original per-environment manifests and verify each renders to match what that environment runs today.

Decide how far to go with helpers and conditionals

Once a chart works, there’s a temptation to keep templatizing — wrap optional resources in {{- if }} blocks, add a _helpers.tpl with named templates, parameterize the ingress on and off. Some of that is genuinely useful; some of it is complexity for its own sake. I let the model propose the additions but I gate them on a simple test: does this conditional correspond to a real difference between my environments, today? An {{- if .Values.ingress.enabled }} guard earns its place if one environment has no ingress. A helper that builds a fully-qualified app name earns its place if the chart will be installed multiple times in one namespace. Anything that doesn’t map to a concrete, current need, I leave out.

The reason for the discipline is that every conditional is a code path the render-diff has to cover. A chart with five if blocks has thirty-two possible render outputs, and I can only claim the conversion is faithful for the combinations I actually test. So I keep the conditional surface small, and for each flag I do add, I render the chart both ways and diff each against the corresponding original. The model is happy to generate elaborate, “flexible” charts; my job is to keep the chart no more flexible than the environments demand, because flexibility I can’t verify is just risk I can’t see.

What AI gets wrong converting manifests

On review, the recurring issues:

  • Over-parameterization. The model turns labels, annotations, and port numbers into values nobody will ever change, cluttering values.yaml. Push back and keep the parameter list short.
  • Lost fields. Occasionally a less common field — terminationGracePeriodSeconds, a specific securityContext setting — gets dropped in the templating. The render-diff catches these.
  • Helpers gone too far. The model may introduce a _helpers.tpl with elaborate name templates that change the rendered object names, breaking the match with the originals. Keep it simple until the diff is clean.

Keep the cluster out of it

This whole workflow is offline. Converting manifests to a chart, rendering, and diffing all happen locally with no cluster access — the model never needs and never gets a kubeconfig. When the chart is verified, a human installs it, in staging first, with helm install or helm upgrade run by a person holding the real credentials. The model drafted; the human deploys.

Wrap up

Folding raw manifests into a Helm chart kills config drift and the copy-paste mistakes that come with it. The templatizing is mechanical work AI handles fast, and the verification is unusually clean: render the chart with original values and diff against the originals — empty diff means a faithful conversion. The model transforms text locally; it never touches your cluster or holds prod credentials.

Keep going with the Kubernetes & Helm category, reach for charting prompts or the Kubernetes prompt pack, and run the new chart through the code review dashboard to catch dropped fields before the first release.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.