Deploy to Kubernetes
This guide shows you how to containerize an app and run it on Kubernetes, connected to Catalyst Cloud. It works the same for an AI agent, a workflow app and an app that uses the Dapr APIs.
Your code runs in a Kubernetes pod. There is no sidecar to install. The pod connects to Catalyst Cloud with the three environment variables from Connect to Catalyst, which you store as a Kubernetes Secret.
Prerequisites
- Diagrid Catalyst account
- Diagrid CLI
- Docker
- A container registry (Docker Hub, ECR, GCR, ACR, etc.)
- A Kubernetes cluster with
kubectlconfigured
1. Create a Catalyst project and app
If you don't already have a project and app from a previous tutorial:
diagrid project create my-project
diagrid app create my-app --project my-project
Use descriptive names that match your application. You can reuse a project you already created in a previous tutorial. Create a new app for the Kubernetes deployment.
2. Retrieve Catalyst credentials
You need three values to connect your pod to Catalyst: the project's HTTP endpoint, the project's gRPC endpoint, and the app's API token.
Get the project endpoints:
diagrid project get my-project -o json
Look for status.endpoints.http.url and status.endpoints.grpc.url in the output:
{
"status": {
"endpoints": {
"http": { "url": "https://http-prj123456.cloud.r1.diagrid.io:443" },
"grpc": { "url": "https://grpc-prj123456.cloud.r1.diagrid.io:443" }
}
}
}
Get the app API token:
diagrid app get my-app --project my-project -o yaml
Look for status.apiToken in the output:
status:
apiToken: diagrid://v1/...
Save all three values. You'll store them as a Kubernetes Secret in a later step.
3. Write a Dockerfile
Create a Dockerfile in your project directory. Pick your language:
- Python
- .NET
- Java
- JavaScript
- Go
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "agent.py"]
Replace agent.py with your app's entry point.
Create a requirements.txt with your framework's dependencies:
- LangGraph
- CrewAI
- OpenAI Agents
- Pydantic AI
- Google ADK
- Strands
- Dapr Agents
- Deep Agents
- Claude Agents
- HolmesGPT
diagrid[langgraph]
fastapi
uvicorn
diagrid[crewai]
fastapi
uvicorn
diagrid[openai_agents]
fastapi
uvicorn
diagrid[pydantic_ai]
fastapi
uvicorn
diagrid[adk]
fastapi
uvicorn
diagrid[strands]
fastapi
uvicorn
dapr-agents
fastapi
uvicorn
diagrid[deepagents]
fastapi
uvicorn
diagrid[claude_agents]
fastapi
uvicorn
diagrid[holmesgpt]
fastapi
uvicorn
If your app does not use the diagrid SDK (e.g. a plain access policy service invocation app), just list your direct dependencies: fastapi, uvicorn, httpx, etc.
For a workflow or Dapr API app, list dapr and dapr-ext-workflow (workflows) plus your web framework instead.
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Replace MyApp.dll with your project's assembly name.
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /src
COPY . .
RUN mvn -q package -DskipTests
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /src/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
This assumes your build produces one executable jar, as Spring Boot does.
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "index.js"]
For a TypeScript app, run it with tsx: CMD ["npx", "tsx", "index.ts"] (keep tsx in dependencies), or add a tsc build step.
FROM golang:1.26 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app .
FROM gcr.io/distroless/static
COPY --from=build /app /app
ENTRYPOINT ["/app"]
4. Build and push the image
Replace your-registry and my-app with your registry path and image name.
docker build -t your-registry/my-app:latest .
docker push your-registry/my-app:latest
5. Store credentials as a Kubernetes Secret
Create a Kubernetes Secret with the three Catalyst credentials you retrieved in step 2:
kubectl create secret generic catalyst-credentials \
--from-literal=http-endpoint="https://http-prj123456.cloud.r1.diagrid.io:443" \
--from-literal=grpc-endpoint="https://grpc-prj123456.cloud.r1.diagrid.io:443" \
--from-literal=api-token="diagrid://v1/..."
Replace the placeholder values with the real ones from diagrid project get and diagrid app get.
6. Create a Kubernetes Deployment
Create deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: your-registry/my-app:latest
ports:
- containerPort: 8001
env:
- name: DAPR_HTTP_ENDPOINT
valueFrom:
secretKeyRef:
name: catalyst-credentials
key: http-endpoint
- name: DAPR_GRPC_ENDPOINT
valueFrom:
secretKeyRef:
name: catalyst-credentials
key: grpc-endpoint
- name: DAPR_API_TOKEN
valueFrom:
secretKeyRef:
name: catalyst-credentials
key: api-token
If your app needs other secrets, such as an LLM API key, add them to the Secret and reference them the same way:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: catalyst-credentials
key: openai-api-key
7. Let Catalyst reach your app (if it receives calls)
Skip this step if your app only calls Catalyst, for example a workflow worker or an agent that you start through the Catalyst APIs. Leave the app connection unset; see When to leave the app connection unset. If people or other services call your app directly, still give it a Kubernetes Service.
If Catalyst calls your app, for pub/sub deliveries, service invocation, input bindings or health checks, the app needs an endpoint Catalyst can reach:
-
Expose the pod's port with a Kubernetes Service and an ingress or load balancer that has a public address.
-
Point the app at that address, and set an application token so your app can check that the call comes from Catalyst:
diagrid app update my-app --project my-project \--endpoint https://my-app.example.com \--endpoint-token "<a-secret-you-choose>" -
In your app, reject requests whose
dapr-api-tokenheader doesn't match that token. See Secure the application connection for why this is not the same value asDAPR_API_TOKEN, and to allowlist the project's egress address.
8. Apply and verify
Deploy to your cluster:
kubectl apply -f deployment.yaml
Check that the pod is running:
kubectl get pods
Stream the logs to verify the app connected to Catalyst:
kubectl logs -f deployment/my-app
You should see the app start. A workflow app logs that its workflow worker connected to Catalyst. To check an app that receives calls, publish a test message or invoke it with diagrid call.
Summary
In this guide, you:
- Created a Catalyst project and app for Kubernetes use
- Retrieved the HTTP endpoint, gRPC endpoint, and API token
- Containerized your app
- Stored Catalyst credentials as a Kubernetes Secret
- Deployed the app with the three environment variables your code reads from
Next steps
- Watch your app's runs: Operate workflows or Operate agents.
- See metrics, API logs and the app topology in Observability.
- Decide which apps may call each other with service invocation policies.
- Scale out with Horizontal Pod Autoscaling.
- Keep traffic inside your own network: compare the hosting options.