---
title: "AI Agents on Kubernetes 101: From Laptop Script to Production Pod"
source: "https://www.tigera.io/blog/ai-agents-on-kubernetes-101-from-laptop-script-to-production-pod/"
description: "A beginner's step-by-step guide to deploying AI agents on Kubernetes: containerize the agent, manage API keys with Secrets, set probes and limits, and lock down egress."
---

[Technical Blog](https://www.tigera.io/category/technical-blog/)

# AI Agents on Kubernetes 101: From Laptop Script to Production Pod

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/) on Sep 08, 2026 • 13 min read

In short, this is a beginner’s guide to deploying an AI agent on Kubernetes. You will containerize an agent, store its API key as a Kubernetes secret, write a deployment with health probes and resource limits, expose it with a service, and lock down its network egress, in that order, with a working manifest at every step. On a local kind cluster the whole walkthrough takes about an hour. At the end: the six mistakes almost every first agent deployment makes, and the questions a 101 deployment leaves open.

Every AI agent starts life the same way; a Python script on someone’s laptop, an API key in a `.env` file, a `while` loop around an LLM call. It works, it demos well. Then someone with a budget says “ship it,” and you, the engineer closest to the script, get to figure out what shipping an agent actually means.

This guide is that path, walked slowly. It assumes you know what a container is and have met `kubectl a`t least once, and it assumes nothing about agents. By the end you will have an agent running in a cluster with its key in a Secret, its resource usage capped, its health checked, and its network access reduced to the short list of places it has any business calling. That is still short of production-grade governance, but it is a deployment you could defend in a code review, which is more than most agents get.

## Why is Kubernetes a good place to run AI agents?

The short answer is, because an AI agent is a workload that needs supervision, and Kubernetes is the most widely used system for supervising workloads. It restarts the agent when it crashes, caps how much CPU and memory it can consume, injects its credentials (e.g. API keys) at runtime instead of baking them into the code, and describes all of it in version-controlled YAML manifest your team can review. Just as important, Kubernetes gives you control over the agent’s environment, such as, what it can reach on the network, what identity it carries, what happens when it misbehaves. That matters more for agents than for ordinary services, because an agent’s behavior is decided at runtime by a model, so the rules have to live outside the agent, where no prompt can talk its way past them. That argument deserves more than a paragraph, so we gave it a full post: [The Safest Place to Run an AI Agent Is a Cluster That Doesn’t Trust It](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/) makes the case with a year of real incidents as evidence.

## How is deploying an agent different from deploying a web service?

Mechanically, it barely is. An agent is a long-running process that speaks HTTP; Kubernetes has been running those for a decade. The difference is in what the workload does with its freedom:

- **A web service follows its code.** An agent follows a model. You can read a service’s code and know its behavior. An agent’s next action depends on whatever lands in its context window.

- **An agent holds credentials and acts.** It calls APIs, queries databases, sends messages. A wrong answer is a bug; a wrong*action* is an incident.

- **Every input is potentially an instruction.** Prompt injection is unsolved. Text the agent reads, from a user, a document, or another agent, can try to redirect it.

So the deployment steps below are the same ones you would use for any service. The difference is emphasis: the steps most tutorials treat as optional hardening (secrets, limits, egress control) are, for agents, the point.

## What you need before you start

Four things, all free:

- **A cluster**. Locally, [kind](https://kind.sigs.k8s.io/) runs Kubernetes inside Docker: `kind create cluster --name agents`. Any managed cluster (EKS, GKE, AKS) works the same way.

- **kubectl and Docker**, installed and talking to that cluster.

- **An agent that speaks HTTP**. Any framework is fine. LangGraph, CrewAI, Google ADK, etc all wrap into a web server; we compared them in [Six AI Agent SDKs for Enterprise Kubernetes](https://www.tigera.io/blog/six-ai-agent-sdks-for-enterprise-kubernetes-compared/). The walkthrough uses a generic Python agent served by FastAPI on port 8080, with two routes: `POST /chat` for work and `GET /healthz` that returns 200 when the process is up. If your agent lacks a health route, add one first. It is five lines, and step 4 depends on it.

- **An LLM API key.** From whichever provider your agent calls.

One namespace keeps the experiment contained:

```
`kubectl create namespace agents`
```

## Step 1: Containerize the agent

Kubernetes runs containers, so the script becomes an image. A minimal Dockerfile for a Python agent:

```
`FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . USER 1000 EXPOSE 8080 # change the command (to run agent) according to its framework documentation CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]`
```

Two lines here are security decisions. `USER 1000` runs the agent as a non-root user, so a compromised agent is not root inside its container. And notice what is *absent*: no API key. The key never enters the image. An image is copied to registries, cached on nodes, and pulled by anyone with access; a key baked into an image is a key you have already leaked, you just don’t know to whom yet.

Build it and, for kind, load it into the cluster:

```
`docker build -t support-agent:0.1.0 . kind load docker-image support-agent:0.1.0 --name agents`
```

On a real cluster you would push to a registry instead. Either way, tag with a version (e.g., `0.1.0`), never `latest`. You want to be able to say exactly what is running, and roll back to exactly what was running before.

## Step 2: Put the API key in a Secret

The`.env` file’s job is taken over by a Kubernetes Secret:

```
`kubectl -n agents create secret generic support-agent-secrets --from-literal=ANTHROPIC_API_KEY='sk-ant-...'`
```

The Secret lives in the cluster, is delivered to the pod as an environment variable at start time, and can be rotated without rebuilding the image. Two honest caveats for later: Secrets are base64-encoded, not encrypted, so real clusters enable encryption at rest and restrict who can read them with RBAC; and the agent’s own process can still read this variable, which matters once you worry about prompt injection. Hold that thought for the end of the article.

## Step 3: Write the Deployment

The Deployment is the contract: which image, how many copies, what resources, what health checks. Save this as `deployment.yaml`:

```
`apiVersion: apps/v1 kind: Deployment metadata: name: support-agent namespace: agents labels: app: support-agent spec: replicas: 1 selector: matchLabels: app: support-agent template: metadata: labels: app: support-agent spec: automountServiceAccountToken: false securityContext: runAsNonRoot: true containers: - name: agent image: support-agent:0.1.0 ports: - containerPort: 8080 envFrom: - secretRef: name: support-agent-secrets resources: requests: cpu: 100m memory: 256Mi limits: cpu: "1" memory: 512Mi readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 15 periodSeconds: 20 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"]`
```

Apply it with `kubectl apply -f deployment.yaml`, then read it back top to bottom, because every block answers a question a reviewer will ask:

- **`automountServiceAccountToken: false`:** By default every pod gets a token for the Kubernetes API mounted into its filesystem. Your agent doesn’t need to talk to the Kubernetes API, so it doesn’t get the token. For an agent this is not a nicety. It is the difference between “prompt injection stole a chat log” and “prompt injection got a foothold in my cluster’s control plane.”

- **resources**: Requests are what the scheduler reserves; limits are the ceiling. Agents fail in loops. A model that decides to retry forever, or to summarize a document by reading it into memory in one piece, will eat a node if you let it. Limits turn “the cluster is down” into “one pod got throttled.”

- **`readinessProbe` and `livenessProbe`**: Readiness controls whether traffic is sent to the pod; liveness restarts it when the process wedges. Without them, Kubernetes considers a hung agent healthy forever.

- **`envFrom.secretRef`**: The key from step 2 arrives as an environment variable. Code reads `ANTHROPIC_API_KEY` exactly as it did from the `.env` file. Nothing about the agent’s code had to change.

Check it comes up:

```
`kubectl -n agents get pods kubectl -n agents logs deploy/support-agent`
```

## Step 4: Expose it with a Service

Pods are ephemeral and their IPs change. A Service gives the agent a stable name:

```
`apiVersion: v1 kind: Service metadata: name: support-agent namespace: agents spec: selector: app: support-agent ports: - port: 80 targetPort: 8080`
```

Now anything inside the cluster can reach the agent at `http://support-agent.agents.svc`. From your laptop, test through a port-forward:

```
`kubectl -n agents port-forward svc/support-agent 8080:80 curl -X POST localhost:8080/chat -H 'Content-Type: application/json' -d '{"message": "hello"}'`
```

If you get an answer, you have an AI agent running on Kubernetes. Most tutorials stop here. Do not stop here.

## Step 5: Close the doors it doesn’t need

Right now your agent can open a connection to anything: every pod in the cluster, every address on the internet. For a web service that is untidy. For an agent it is the whole attack surface, because the standard end of a prompt-injection chain is exfiltration: the agent is talked into sending data somewhere it should never call. A NetworkPolicy makes egress deny by default:

```
`apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: support-agent-egress namespace: agents spec: podSelector: matchLabels: app: support-agent policyTypes: ["Egress"] egress: - to: - namespaceSelector: {} ports: - protocol: UDP port: 53 - protocol: TCP port: 53 - ports: - protocol: TCP port: 443`
```

This allows DNS lookups plus outbound HTTPS, and nothing else; a connection to another pod, or plaintext HTTP to anywhere, now fails at the network layer (Note for kind users: enforcing NetworkPolicy requires a network plugin that implements it, such as [Calico](https://docs.tigera.io/calico/latest/getting-started/kubernetes/kind); the kind default does not).

The policy still has one hole, and it is an instructive one: “TCP 443 to anywhere” lets the agent reach any HTTPS endpoint on the internet, including an attacker’s. Vanilla NetworkPolicy speaks IPs and ports; it cannot say “only `api.anthropic.com`.” Narrowing egress to named destinations takes either a DNS-aware policy engine (Calico can do this) or, better for agents, an egress gateway that all agent traffic must pass through. Remember this gap. It is where 101 ends and the last section of this article begins.

## The six mistakes every first agent deployment makes

The walkthrough above quietly avoided all six. Here they are in the open, because you will meet them in other people’s manifests:

**Mistake**
**Why it hurts an agent especially**
**Instead**

API key baked into the image
Images get pulled, cached, and shared; the agent’s key is its power
Kubernetes Secret, injected at runtime

No resource limits
Agents fail in loops; one runaway loop starves the node
Set `requests` and `limits`

`latest` image tag
You cannot say which agent behavior is running, or roll back
Version tags, ideally digests

No health probes
A wedged agent looks healthy and keeps receiving work
`readinessProbe + livenessProbe`

Default ServiceAccount token mounted
Injected agent inherits a path to the Kubernetes API
`automountServiceAccountToken: false`

Unrestricted egress
Prompt injection ends in exfiltration over open egress
Default-deny NetworkPolicy, then allowlist

Read the middle column again. None of these is an exotic agent problem; they are ordinary Kubernetes hygiene. Agents just raise the price of skipping them.

## What a 101 deployment still can’t answer

You now have one agent, contained and supervised. Before you call it production, try to answer three questions about it:

- **Who is this agent?** Your cluster knows it as a pod with a label. Nothing cryptographically distinguishes it from any other workload, so nothing downstream can grant it permissions *as an agent*, or refuse an impostor.

- **What exactly is it allowed to do?** Your NetworkPolicy says “HTTPS, somewhere.” It cannot see that the agent is calling an MCP tool, or with what arguments. “May this agent call `delete_records` on the billing server” is not a question any layer you have deployed can even parse. We walked through why the stock building blocks stop short in the [accountability gap post](https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/).

- **What did it do last Tuesday?** You have pod logs, written by the agent itself. An agent’s own narration is not an audit trail; the best-documented case of an agent deleting a production database came with the agent confidently reporting that rollback was impossible. It was not.

And this is with one agent. The moment there are two, they start talking to each other (that is the[A2A protocol](https://www.tigera.io/blog/how-ai-agents-communicate-understanding-the-a2a-protocol-for-kubernetes/)), and the questions multiply by every pair.

That missing layer (identity, per-request authorization, and audit across a fleet of agents) is what [Tigera Lynx](https://www.tigera.io/blog/why-we-built-lynx-bringing-control-to-the-age-of-ai-agents/) adds on top of exactly the deployment you just built. Lynx gives every agent a SPIFFE or OIDC workload identity, routes agent-to-agent, MCP, and LLM traffic through a gateway that authorizes each request under Cedar policy, and records every hop in an Agent Trail the agent cannot edit. Recent releases sharpened the credential story from this post’s step 2: provider keys attach at the gateway instead of living in the pod’s environment, per-hop tokens are minted with an audience of one target so a stolen token is nearly worthless, and an OAuth authorization-code flow can issue per-user credentials. Policies can require human approval before a risky MCP call proceeds. On the node, an eBPF detector spots agents nobody registered and can quarantine a compromised one down to blocking its network writes at the kernel, and a policy playground in the UI lets you test a Cedar policy against simulated requests before it ever gates real traffic.

## Frequently asked questions

- **Do I need a GPU to deploy an AI agent on Kubernetes?** No. An agent is orchestration code that calls a model over an API; the GPUs live with the model provider. You only need GPU nodes if you self-host the model itself, which is a separate project.

- **Is Kubernetes overkill for a single agent?** For a weekend experiment, yes; run it locally. But the reasons to move to Kubernetes (restarts, secrets, resource caps, network control) show up the first time the agent touches real credentials or real users, which happens earlier than most teams expect.

- **Can I do all of this on my laptop?** Yes. Everything above runs on a kind cluster in Docker, including the NetworkPolicy if you install a plugin like Calico that enforces it.

- **Which agent framework works best on Kubernetes?** Any framework that can serve HTTP deploys the same way. The differences show up in observability, state handling, and protocol support; our [six-SDK comparison](https://www.tigera.io/blog/six-ai-agent-sdks-for-enterprise-kubernetes-compared/) covers them.

- **How do I scale an agent to more replicas?** Set `replicas: 3` and Kubernetes load-balances across them, but only if the agent keeps its conversation state outside the pod (a database or cache), since any replica may serve the next request. Stateless agents scale for free; stateful ones need that refactor first.

- **How is deploying an agent different from deploying a model?** A model deployment serves inference (weights on GPUs behind an endpoint). An agent deployment runs the loop that calls models and tools to pursue a goal. This guide covers the agent; most teams consume the model as a managed API.

## Ship the pod, then ask the harder question

Back to that laptop script. The distance from `.env` file to the deployment in this article is five manifests and an afternoon, and every step was ordinary Kubernetes, applied with an agent’s failure modes in mind. That is the good news: you do not need new infrastructure to give an agent a safer home than a laptop. You need the infrastructure you already have, used deliberately.

The harder question arrives with agent number two: when they start acting on each other’s behalf, who is checking identity at the door, and where is the record? Deploying the agent was the easy 101. Trusting it is a course Kubernetes alone does not teach.

*Lynx is Tigera’s security and governance platform for AI agents on Kubernetes: identity, policy, detection, and audit for every agent in your cluster. Read [How Lynx Works](https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/) or request early access at [tigera.io/demo/](https://www.tigera.io/demo/?product=lynx).*

[Learn more about Lynx →](https://www.tigera.io/tigera-products/lynx/)

[AI Agent Security](https://www.tigera.io/tags/ai-agent-security/)

## Related posts

[![The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It](https://www.tigera.io/app/uploads/2026/08/The-Safest-Place-to-Run-an-AI-Agent-Is-On-a-Cluster-That-Doesnt-Trust-It.png)](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

#### [The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/)
on Aug 27, 2026

Every organization running AI agents has already made a hosting decision. Most made it by accident. The sales team switched on the agent built into their CRM. Engineering is piloting a coding agent in a...

[Read more](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

[![AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.](https://www.tigera.io/app/uploads/2026/08/AI-Red-Team-Agents-Automate-Attacks-on-your-AI-Agents.-Runtime-Policies-Automate-their-Defense.png)](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

#### [AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/)
on Aug 24, 2026

The AI red teaming market grew up fast this year. OpenAI bought Promptfoo, Cisco and Microsoft shipped automated attack suites, and a seed-stage startup publicly compromised 50 of 55 live customer service bots. These platforms...

[Read more](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

[![The New MCP Headers Are a Gift to Gateways](https://www.tigera.io/app/uploads/2026/08/The-New-MCP-Headers-Are-a-Gift-to-Gatewaysr.png)](https://www.tigera.io/blog/the-new-mcp-headers-are-a-gift-to-gateways/)

#### [The New MCP Headers Are a Gift to Gateways](https://www.tigera.io/blog/the-new-mcp-headers-are-a-gift-to-gateways/)

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/)
on Aug 6, 2026

In short, buried in the transport section of the MCP 2026-07-28 release candidate are three changes that matter more to infrastructure teams than to anyone else: mandatory Mcp-Method and Mcp-Name headers, cache-control-style ttlMs and cacheScope...

[Read more](https://www.tigera.io/blog/the-new-mcp-headers-are-a-gift-to-gateways/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=3319 metric#misses=41 metric#hit-ratio=98.8 metric#bytes=1462385 metric#prefetches=149 metric#store-reads=49 metric#store-writes=26 metric#store-hits=159 metric#store-misses=30 metric#sql-queries=38 metric#ms-total=594.01 metric#ms-cache=25.18 metric#ms-cache-avg=0.3402 metric#ms-cache-ratio=4.2 sample#redis-hits=25224241 sample#redis-misses=7299577 sample#redis-hit-ratio=77.6 sample#redis-ops-per-sec=189 sample#redis-evicted-keys=0 sample#redis-used-memory=87536792 sample#redis-used-memory-rss=88035328 sample#redis-memory-fragmentation-ratio=1.0 sample#redis-connected-clients=2 sample#redis-tracking-clients=0 sample#redis-rejected-connections=0 sample#redis-keys=36269 -->
