I’ve been experimenting with various approaches to generate Kubernetes configuration using AI. Is it better than writing the configuration by hand? Better than kubectl create? Better than traditional UI forms? Better than starting from an existing configuration and changing it?

On the last question, it definitely helps tremendously to have some content to start from, whether Kubernetes resources, schemas, or other information about the workload. A Helm chart was my starting point for vLLM, and that required very little prompting. But most of the work was already done when creating the Helm chart, so that’s cheating, really. I’ll discuss other sources of information in a bit.

In my first attempt, I just asked Claude Code to generate a Kubernetes Service and Deployment for my application. It created a minimalistic pair of resources with dummy values that needed to be edited. That was not better than kubectl create.

I created an agent skill for creating resources. It generated some example resources to start from, but they were mostly similarly fairly minimalistic. For example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: confighubplaceholder
  labels:
    app: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: main
          image: ghcr.io/myorg/my-app:v1.2.3
          ports:
            - containerPort: 8080

The main benefits of the skill were that I added instructions for how to use ConfigHub functions to set additional default values, as shown below, and how to use ConfigHub functions, such as vet-schemas, to validate the resources.

cub function set --space myapp-dev --where "Slug = 'my-app'" \
  set-container-resources-defaults --change-desc "Fill resource defaults"
cub function set --space myapp-dev --where "Slug = 'my-app'" \
  set-container-probe-defaults --change-desc "Fill probe defaults"
cub function set --space myapp-dev --where "Slug = 'my-app'" \
  set-pod-container-security-context-defaults --change-desc "Fill security context defaults"

I concluded that the example resources themselves weren’t of much value unless a user were able to curate their own customized versions of them beyond what Claude would generate on its own, so I created an installer package to upload the examples into ConfigHub for customization. That still left the user to edit the resources to fill in the many details after copying the examples, however.

I then started over from scratch using Claude Code’s AskUserQuestion tool, and it was like a game of 20 questions. The first couple of questions were fairly high-level, but already required significant Kubernetes knowledge:

What kind of workload is this application?

 1. Stateless web/API ✔
     A standard Deployment — replicas are interchangeable, no per-pod persistent identity or storage. Most web servers and APIs fit here.
  2. Stateful service
     A StatefulSet — stable network identity and per-pod persistent volumes. Databases, queues, and clustered systems fit here.
  3. Batch / scheduled job
     A Job (run-to-completion) or CronJob (scheduled). For data migrations, ETL, periodic tasks.
  4. Node-level daemon
     A DaemonSet — one pod per node. For log collectors, monitoring agents, CNI components.
  5. Type something.
  6. Chat about this

How should the application be exposed?

 1. Internal only (ClusterIP)
     Reachable only inside the cluster via a Service. Good for backend services other pods call.
  2. External via Ingress
     ClusterIP Service plus an Ingress with a hostname/path for HTTP(S) traffic from outside.
  3. External via LoadBalancer
     A cloud LoadBalancer Service that gets a public IP. Good for non-HTTP or direct exposure.
  4. No network exposure
     No Service at all — for workers/jobs that only make outbound calls.
  5. It's external. We use Traefik IngressRoute for ingress. ✔
  6. Chat about this

How is the app configured and what does it need for secrets/config?

 1. [ ] Environment variables
  Plain env vars set directly in the pod spec.
  2. [ ] ConfigMap
  Non-sensitive config (files or env) mounted/injected from a ConfigMap.
  3. [ ] Secret
  Sensitive values (API keys, passwords) from a Secret.
  4. [ ] None
  No external configuration needed.
  5. [ ] Type something: We want to use a ConfigMap for environment variables and ExternalSecretOperator to pull secrets from AWS SSM
  6. Chat about this

From there, it dove into details. In the interest of space, I won’t present all of the options it offered or my responses.

What resource and scaling profile do you want?
What's the app name, namespace, and container image (with tag)?
What port does the container listen on, and what hostname should the IngressRoute match?
For the ExternalSecret: which SecretStore and AWS SSM paths?
How should the ConfigMap and Secret reach the container?
I also need the actual values. These are free-form, so just type them in your reply.

At that point, I was copy/pasting lines from a local env file.

It then asked about probe endpoints and certificate details. I also requested the addition of an emptyDir volume, and it took multiple iterations to get that exactly the way I needed. One advantage of a tool is that it can explicitly require or guide you to provide the necessary details. I stopped before getting to the command line, security best practices, RBAC, and variants for multiple environments.

There are a lot of details in Kubernetes configuration, but, other than security-related properties, which could have different defaults if not for backward compatibility and usability concerns, most settings depend on details of the application and underlying infrastructure. That did not seem much better than a guided set of UI forms, except that it was able to handle some non-standard choices I requested, such as the use of External Secrets. It also allowed me to change my mind without backtracking, though it didn’t call me out on that either, so I’m not sure that was a good thing, since it could have indicated a mistake or led to inconsistencies.

In order to address the issue of providing details about the application, I provided specifications of an application’s interfaces: commands and flags, environment variables, ports, probe endpoints, and filesystem paths written, with the agent skill installed. I also asked it to use security best practices. Because I was generating configuration for a ConfigHub component, it inferred other details from the content of other skills. Other kinds of technical documents describing the component could have played a similar role. Claude tried to validate the resources using dry run applies with a cluster, but I hadn’t given it up-to-date credentials for any.

Claude correctly added pod-security labels to the Namespace, created a ConfigMap with valid environment variables, wired the Deployment to the ConfigMap and to a Secret, set the security context, added liveness and readiness probes pointed at the correct endpoints, mounted an emptyDir volume for /tmp, set minimal resource requests, set the port consistently in multiple fields and resources including a ConfigMap value, and created a NetworkPolicy that allowed egress to DNS and to ConfigHub’s server and ingress allowing monitoring of metrics. The result was a much more complete starting point with no back and forth required. An excerpt from the Deployment’s pod spec template follows:

      # Pod-level hardening (satisfies the "restricted" Pod Security Standard).
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
        seccompProfile:
          type: RuntimeDefault
      # Give the worker time to drain in-flight work after SIGTERM
      # (GRACE_PERIOD_DELAY + shutdown timeout, with headroom).
      terminationGracePeriodSeconds: 30
      containers:
        - name: worker
          image: ghcr.io/confighubai/confighub-worker:v0.1.90
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 9090
              protocol: TCP
          envFrom:
            - configMapRef:
                name: confighub-worker
          env:
            - name: CONFIGHUB_WORKER_ID
              valueFrom:
                secretKeyRef:
                  name: confighub-worker
                  key: CONFIGHUB_WORKER_ID
            - name: CONFIGHUB_WORKER_SECRET
              valueFrom:
                secretKeyRef:
                  name: confighub-worker
                  key: CONFIGHUB_WORKER_SECRET
          livenessProbe:
            httpGet:
              path: /internal/ok
              port: http
            initialDelaySeconds: 10
            periodSeconds: 15
            timeoutSeconds: 3
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /internal/ready
              port: http
            initialDelaySeconds: 5
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 3
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              # Intentionally no CPU limit (avoids throttling); memory limit caps blast radius.
              memory: 256Mi
          # Container-level hardening.
          securityContext:
            allowPrivilegeEscalation: false
            privileged: false
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            capabilities:
              drop:
                - ALL
            seccompProfile:
              type: RuntimeDefault
          volumeMounts:
            # Root FS is read-only; /tmp is the worker's required writable scratch space.
            - name: tmp
              mountPath: /tmp
      volumes:
        - name: tmp
          emptyDir: {}

Additionally providing the Dockerfile would have enabled the agent to choose the expected user and group IDs. They could also be added to the RuntimeSpec. If the agent had used the set-pod-container-security-context-defaults function, as the skill recommended, it also would have set the correct values, since I adopted the same values in our Dockerfile as reasonable defaults. Agents still don’t always do as they are told.

From there, I could use the policy and operational tools and corresponding agent skills I created to configure the RBAC, autoscaling, PodDisruptionBudget, scheduling constraints, and so on. For opinionated operational environments it should be possible to create skills that convey more of the necessary decisions up front.

For this particular component, I used AI to create an installer package. The package captured those decisions and included the application specs for context and for validation. It also added a “fact collector” to discover some necessary variable values, including the current image release, the ability to change the namespace, and deterministic validation steps, further automating customization of the configuration. (Such packages are really only necessary for components that will be installed by multiple teams or organizations for multiple use cases. ConfigHub has other ways to manage variants of a configuration.)

I could imagine going a step farther, by generating a management tool just for a specific component, though this particular workload is simple enough that general operational tools and schema-driven tools would be sufficient. However, for an application with many more configuration options, I could imagine some guidance, progressive disclosure, consistency checking, and other early validation would be helpful. Using ConfigHub’s filters, it could find all instances of configurations for the same component, and provide an opinionated, selected view on top of them. Let me know if you are interested in an experiment along those lines.

I haven’t seen much discussion of this topic in any forums or blog posts yet, and I found just a handful of agent skills with simple manifest examples, so it’s still early in the development of best practices in this area. I found that a combination of information extracted from application source code or generated from the application, architectural documents, infrastructure context, deterministic AI-generated tools, and agent skills was most effective so far.

Have you used AI agents to generate Kubernetes configuration for any workloads? What approaches did you try? Which ones worked best? What information did you provide to the agent? What information did it, perhaps unexpectedly, discover on its own? How many iterations were necessary? Do you think the process was faster or resulted in fewer errors than non-AI-based approaches?

Reply here, or send me a message on LinkedIn, X/Twitter, or Bluesky, where I plan to crosspost this.

You could also try out ConfigHub, which is now in preview.

If you found this interesting, you may be interested in other posts in my Kubernetes series.