Configuring the NGINX Ingress Controller in Kubernetes With AI
Draft and decode NGINX Ingress manifests with AI: ingressClassName, pathType, cert-manager TLS, and annotations validated with kubectl and the rendered config.
- #nginx
- #ai
- #kubernetes
- #ingress
A teammate pinged me at 4:47 on a Friday because a new service kept returning 404s through the cluster’s load balancer, even though the pod was healthy and the Service had endpoints. The Ingress looked fine to him. It wasn’t. He’d written nginx.ingress.kubernetes.io/rewrite-target: /$1 but his path rule had no capture group, so the controller rewrote every request to a literal /$1. The pod never saw a valid path. He’d copied the annotation from a blog post that assumed a regex path he didn’t have. That bug is the whole reason I trust AI to draft Ingress manifests and explain annotations, and trust kubectl plus the rendered nginx.conf to tell me whether the draft is actually correct.
AI is genuinely good at the parts of Ingress that are tedious and error-prone: remembering which annotation prefix belongs to which controller, recalling that pathType: Prefix matches path segments and not substrings, and stubbing out a manifest with TLS wired to a cert-manager secret. It is not good at knowing what your controller actually rendered. So the loop is: prompt for a draft, read it like a code reviewer, apply it, then go look at the truth inside the controller pod.
Start With a Clear Prompt
The single biggest mistake people make is asking AI for “an Ingress” without telling it which controller they run. There are two completely different projects that both get called “the NGINX Ingress Controller,” and they do not share an annotation namespace. More on that below. Pin it down in the prompt:
Write a Kubernetes Ingress for the community ingress-nginx controller (kubernetes/ingress-nginx). Host
app.example.com. Route/to Servicewebport 80 and/apito Serviceapiport 8080. UseingressClassName: nginx. Terminate TLS using a cert-manager-issued secret namedapp-example-tls. Add annotations to force SSL redirect and set proxy body size to 25m. UsepathType: Prefix. Explain each annotation in a comment.
That prompt does the work for you: it names the controller, fixes the class, specifies the secret instead of letting the model invent one, and asks for inline explanations so you can sanity-check the reasoning. Here’s the kind of manifest that comes back, cleaned up to what I’d actually apply:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: storefront
annotations:
# Redirect HTTP to HTTPS (default true once TLS is set, but be explicit)
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# Allow larger uploads; maps to client_max_body_size in nginx.conf
nginx.ingress.kubernetes.io/proxy-body-size: "25m"
# cert-manager watches this Ingress and fills the TLS secret
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-example-tls
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Note the order: I put /api before /. With Prefix matching, the controller sorts by specificity, but I list the more specific path first anyway so the manifest reads the way the routing actually resolves. Small habit, fewer surprises.
pathType Is Where People Get Burned
pathType has three values and AI gets them right more often than humans do, but you still need to understand the call it’s making.
Prefixmatches by URL path segments./apimatches/apiand/api/v1but not/apidocs. This is what you want 90% of the time.Exactmatches the path with no trailing-slash forgiveness./healthmatches/healthonly, never/health/.ImplementationSpecifichands matching to the controller. On ingress-nginx this is where regex paths and capture groups live — and it’s the only placerewrite-targetwith a$1capture makes sense.
That last point is exactly the Friday-afternoon bug. If you ask AI for a path rewrite, make it show you both halves:
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /svc(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: 8080
Here $2 refers to the second capture group (.*), so /svc/users reaches the backend as /users. The capture group in the path and the $2 in the annotation are a matched pair. If AI hands you a rewrite-target with a $ variable, the very next thing you check is whether the path actually defines that group.
Apply, Then Go Find the Truth
Drafting is half the job. Validation is the half that keeps you out of the incident channel.
kubectl apply -f web-ingress.yaml
# Did the controller accept it and assign an address?
kubectl describe ingress web -n storefront
kubectl describe shows you the parsed rules, the events, and — critically — whether the controller logged a warning about an annotation it didn’t understand. A typo’d annotation key is silently ignored, not rejected, so the describe output and controller logs are your only signal.
Then dump what the controller actually rendered. The annotations are inputs; the generated nginx.conf is the output that serves traffic. They are not the same thing.
# Find the controller pod
POD=$(kubectl get pods -n ingress-nginx \
-l app.kubernetes.io/name=ingress-nginx -o name | head -n1)
# Dump the generated config and grep your host out of it
kubectl exec -n ingress-nginx "$POD" -- cat /etc/nginx/nginx.conf \
| grep -A 30 "app.example.com"
# Validate the rendered config syntax inside the pod
kubectl exec -n ingress-nginx "$POD" -- nginx -t
When I run that grep, I’m looking for the concrete directives my annotations were supposed to produce: a client_max_body_size 25m; for the proxy-body-size annotation, a return 308 redirect block for ssl-redirect, and a rewrite line that matches my capture group. If an annotation didn’t translate the way I expected, this is where it shows up — in plain nginx directives I can read. AI is a great pair for this step too: paste a confusing rendered server block into it and ask “explain what this location block does and which annotation produced it.” That round-trip is faster than digging through the controller’s templating source. If you want to go deeper on hardening the rendered output, I wrote up the review side in reviewing NGINX security configuration with AI.
Rate Limiting and Other Annotation Traps
Rate limiting is a good example of “AI saves you a docs trip, but you verify the number.” On ingress-nginx:
metadata:
annotations:
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/limit-connections: "20"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"
limit-rps is requests per second per client IP, and the burst multiplier controls how much short-term spikiness the controller tolerates before it starts returning 503s. Ask AI to explain the interaction and it’ll walk you through how those map to limit_req_zone and limit_req in the rendered config — then go confirm the zone size and burst in the actual nginx.conf, because the defaults around shared-memory zones are easy to get wrong at scale.
The ingress-nginx vs F5 NGINX Distinction
This trips up AI and humans equally, so call it out explicitly in every prompt. There are two controllers:
- Community ingress-nginx (
kubernetes/ingress-nginx) uses thenginx.ingress.kubernetes.io/annotation prefix. This is the one most clusters run, and everything above is written for it. - F5 NGINX Ingress Controller (
nginxinc/kubernetes-ingress) uses thenginx.org/prefix and its own VirtualServer/VirtualServerRoute CRDs. Its annotations and CRDs are not interchangeable with the community ones.
So nginx.ingress.kubernetes.io/rewrite-target and nginx.org/rewrites are different controllers’ takes on the same idea, with different syntax. If you copy a manifest from the wrong project’s docs, the annotations are silently dropped and your routing quietly does the default thing. When you prompt AI, name the repo, not just “NGINX Ingress.” I keep a couple of these prompts saved in my prompts collection so I don’t have to re-explain the distinction every time.
The Loop That Actually Works
AI drafts the manifest and explains the annotations. You read it like a reviewer, confirm the pathType and any capture groups line up, apply it, and then prove it with kubectl describe, a grep of the rendered nginx.conf, and nginx -t inside the controller pod. The model is fast at the parts your memory is bad at; the cluster is the only authority on what’s actually serving traffic. Keep both in the loop and Ingress stops being a Friday-afternoon mystery. For more in this vein, the rest of the AI for NGINX category goes deeper on configs, security, and tuning.
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.