DEV Community

Cover image for Using Claude Code to Pilot Kubernetes on Autodock
Mike Solomon
Mike Solomon

Posted on

Using Claude Code to Pilot Kubernetes on Autodock

At AIATELLA, we recently split our (massive) AortaAIM codebase into two repos:

  • Repo A: ML-powered AortaAIM, the part getting reviewed by the FDA. 6-month review cycles, highly-regulated, big testing burden.
  • Repo B: All of the infrastructure and deployment code. Needs to be agile and nimble to respond to hospitals' unique setups.

Repo B inherited an early PoC that can only be described as a 50k+ LoC Helm briar patch. YAMLs nested in YAMLs patched by other YAMLs. Helm charts that rendered other Helm charts that conditionally included still more YAML.

As they say, the cat's meow! The elephants instep! Oh wait, that's what k8s devs said in the 1920s, and it's the 2020s. But they probably say the same thing now. At least I do.

So I asked myself:

Could Autodock and Claude Code do this better?
Could an agent pilot Kubernetes cleanly enough to replace Helm entirely?

The verdict is a big yes. After this experiment, I probably won't write another Helm chart for a long while.

This article recaps:

  • How I spun up a fresh Autodock box
  • How Claude Code fumbled, learned, debugged, and eventually deployed Argo
  • How it pulled in AortaAIM, wired a webhook, and exposed endpoints
  • How all of this collapsed into a single, human-readable AUTODOCK.md
  • And finally, how Claude redeployed the whole thing perfectly using that md file

In we shall dig!


Spinning Up a Fresh Autodock Box

I started with the naive one-shot hubris befitting of a lazy dev like myself:

"Claude, launch a new Autodock box called argo-dev and bring up Argo Workflows."

Claude cheerfully obliged, and then proceeded to go down a rabbit hole that can only be described as a "hot mess."

Before I show you the final working sequence, here is what it looked like in practice during that first pass.


Claude Code: The Learning on the Job Phase

Below are excepts of Claude failing hard to deploy Argo. I'll spare you the gory details of everything, but pluck out the juicy parts that show, in general, what makes this exercise challenging.


1. k3s install: smooth sailing

Claude starts strong out the gate:

Claude: Installing k3s...

[INFO]  Using v1.33.6+k3s1 as release
[INFO]  systemd: Starting k3s
Enter fullscreen mode Exit fullscreen mode

Then:

Claude: Verifying the node is ready...
NAME     STATUS   ROLES    AGE   VERSION
ip-10-0  Ready    master   21s   v1.33.6+k3s1
Enter fullscreen mode Exit fullscreen mode

So far so good.


2. Installing Argo: also smooth... until it's not

Claude then gets to applying the official Argo manifests:

Claude: Argo installed. Starting port-forward for UI on 2746...
Enter fullscreen mode Exit fullscreen mode

Then it melts down.

error: unable to listen on any of the requested ports: [{2746 2746}]
Enter fullscreen mode Exit fullscreen mode

Claude uses Autodock's env.observe to gather logs.

Claude: Something is already bound to 80/443. 
Checking kube-system...
Enter fullscreen mode Exit fullscreen mode

And it discovers Traefik, k3s's built-in ingress, which I didn't even know about. k3s is sweet, but I don't need that bit of it.


3. The Traefik vs. Caddy Battle

Autodock environments already have a reverse proxy (Caddy) that terminates TLS. k3s ships Traefik, which also wants to terminate TLS. Also called "Two Terminators", not to be confused with "Terminator Two", the 1991 Arnold Schwarzenegger film.

Claude eventually connects the dots:

Claude: Ah, Traefik is conflicting with the machine's reverse proxy. 
We need to remove it entirely.
Enter fullscreen mode Exit fullscreen mode

Then:

kubectl -n kube-system delete pod -l app.kubernetes.io/name=traefik
kubectl -n kube-system delete svc traefik
Enter fullscreen mode Exit fullscreen mode

So now the ports are free and the UI is ready to bind. Someone at Anthropic is drooling over the new training data I'm generating for them, which is fine, as I'm unblocked.


4. Patching Argo for HTTP

Claude tries:

kubectl -n argo patch deployment argo-server --type='json' -p='[
  {"op": "replace", "path": "/spec/template/spec/containers/0/args",
   "value": ["server", "--secure=false", "--auth-mode=server"]}
]'
Enter fullscreen mode Exit fullscreen mode

Fails due to JSON escaping. Claude corrects it, then realizes the readinessProbe also needs to be HTTP.

After a few tries:

... readinessProbe/httpGet/scheme = HTTP
Enter fullscreen mode Exit fullscreen mode

The rollout succeeds and the UI boots. Otherwise known as progress.


5. Exposing the Argo UI

After disabling auth:

Claude: Exposed port 2746 at https://2746--useful-blackbird.autodock.io
Enter fullscreen mode Exit fullscreen mode

Argo is officially alive.


Bringing AortaAIM Into the Cluster

My next challenge is to deploy a workflow that runs AortaAIM, our ML-powered inference engine.

Claude applies the WorkflowTemplate:

Failed to pull image "registry.aiatella.com/aortaaim:latest": authentication required
Enter fullscreen mode Exit fullscreen mode

Claude:

Claude: Right. No registry credentials. 
Let me request .env variables for REGISTRY_USER and REGISTRY_PASS.
Enter fullscreen mode Exit fullscreen mode

After I provide them:

kubectl create secret docker-registry aortaaim-pull-secret \
  --docker-username="$REGISTRY_USER" \
  --docker-password="$REGISTRY_PASS" \
  --docker-server=registry.aiatella.com \
  -n argo
Enter fullscreen mode Exit fullscreen mode

Claude then patches the workflow thusly:

imagePullSecrets:
  - name: aortaaim-pull-secret
Enter fullscreen mode Exit fullscreen mode

Now AortaAIM pulls cleanly.


Adding a Webhook for Ingestion

AortaAIM needs an ingestion endpoint for patient metadata or DICOM pointers.

Claude proposes:

  1. Argo Events EventSource on port 12000
  2. Sensor triggering AortaAIM workflow
  3. Autodock port exposure
  4. Callback step posting artifacts back to the caller

Initially Claude misnames an event key, then patches it after checking logs and context7.

Finally:

Claude: Webhook available at https://12000--useful-blackbird.autodock.io/json
Enter fullscreen mode Exit fullscreen mode

POSTing to this URL triggers AortaAIM end to end.


Enter AUTODOCK.md

Once everything worked, Claude used Autodock MCP to write out the whole environment configuration, problems, and fixes in a single file. This is a new feature in Autodock called env.save which it was smart enough to use automatically in my session.

A few highlights:

### Traefik conflicts with Caddy TLS

Why:
k3s installs Traefik by default, which binds 80/443 and terminates TLS.
Autodock uses Caddy for TLS termination.

Fix:
kubectl -n kube-system delete pod -l app.kubernetes.io/name=traefik
kubectl -n kube-system delete svc traefik
Enter fullscreen mode Exit fullscreen mode

And then there's:

### AortaAIM Registry Authentication

Why:
Argo could not pull the aortaaim image because no registry credentials were present.

What Autodock did:
- Requested REGISTRY_USER and REGISTRY_PASS
- Created aortaaim-pull-secret
- Patched WorkflowTemplate with imagePullSecrets
Enter fullscreen mode Exit fullscreen mode

Compared to a Helm chart, AUTODOCK.md is small, readable, explicit, and most importantly, contains all the "why" behind the "what" and its buddy "how." I mean, I love Helm and have used it for years, but AUTODOCK.md is pretty frickin sweet.


The Real Test: Can Claude Reproduce Everything in One Shot?

Of course, none of this means diddly squat unless we can spin it up from scratch.

So spin I did. I asked autodock.

"Using AUTODOCK.md, deploy the whole environment into argo-test."

It then one-shot the entire thing! The session ends with:

Claude: Argo Workflows is live:

https://2746--happy-panda.autodock.io/workflows?namespace=argo

k3s cluster running with Argo deployed. No Helm needed!
Enter fullscreen mode Exit fullscreen mode

I use to feel a sense of victory after like 2 weeks of struggling with k8s and helm to do this sort of thing. Now I'm, well, probably soon unemployed, but being a developer was nice while it lasted!


The Verdict

Helm has been the standard way to package Kubernetes apps for a decade.

It works, but it cannot express:

  • why certain patches exist
  • why you are disabling TLS in one layer but not another
  • why a registry secret must exist
  • why an ingress controller should be removed
  • why a webhook should be wired a particular way

I'm a softie for declarative programming, and Helm is a declarative renderer, so in that way it gels well with my natural proclivities. But I found that AUTODOCK.md is equally declarative and gives room to the LLM to get out of knots, which invariably happen in k8s deployments.

For our internal deployments of AortaAIM, a single AUTODOCK.md replaced tens of thousands of lines of Helm templates and conditional YAML.

In production, we might still need Helm for customers who expect it. If so, we will generate Helm charts from AUTODOCK.md, not vice versa.

If you're developing for Kubernetes, try this workflow:

  • Spin up an Autodock box
  • Let Claude struggle a bit
  • Get it over the line
  • Use Autodock's env.save
  • Then let it redeploy on a new Autodock box cleanly from scratch and validate that there's parity.

And if the future of cloud infra is AI-assisted, then this feels like the right abstraction boundary. All the intent with none of the YAML.

I've developed a very caring, near-parental instinct to take care of poor future-me that invariably forgets why I wrote thousands of lines of Helm charts. I feel like AUTODOCK.md is a gift to future-me from present-me, and I think k8s development may soon be trending in this direction.

Top comments (1)

Collapse
 
bassg0navy profile image
bassg0navy

3 things:

  1. I felt this:

I use to feel a sense of victory after like 2 weeks of struggling with k8s and helm to do this sort of thing. Now I'm, well, probably soon unemployed, but being a developer was nice while it lasted!

  1. I get how this was a massive improvement over current your current process, but fine-tuning your charts could’ve achieved the same results, no? You can provide relevant “why” and “how” in comments.

  2. I love Claude, but are we really ready for him to deploy our Prod infrastructure now?