Build an AI Kubernetes Pod Debugger with Claude API
Build a CLI tool using Claude API that automatically collects kubectl logs, events, describe output, and resource metrics from broken pods — then generates root cause analysis and step-by-step fix commands in plain English.
Debugging a CrashLoopBackOff pod means running 5 different kubectl commands, reading noisy output, and guessing what matters. This tool collects everything automatically and lets Claude explain what is wrong and how to fix it.
Setup
pip install anthropic subprocess-run rich
# kubectl must be configured and pointed at your clusterPod Debugger
import anthropic
import subprocess
import json
import sys
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
client = anthropic.Anthropic()
console = Console()
def run_kubectl(args: list[str]) -> tuple[str, str]:
"""Run kubectl and return (stdout, stderr)."""
result = subprocess.run(
["kubectl"] + args,
capture_output=True,
text=True,
timeout=30
)
return result.stdout, result.stderr
def collect_pod_context(pod_name: str, namespace: str) -> dict:
"""Collect all diagnostic info for a pod."""
console.print(f"[dim]Collecting data for pod: {pod_name} in {namespace}[/dim]")
context = {}
# Pod describe
stdout, _ = run_kubectl(["describe", "pod", pod_name, "-n", namespace])
context["describe"] = stdout[:5000] # Limit to avoid token waste
# Pod logs (current)
stdout, stderr = run_kubectl(["logs", pod_name, "-n", namespace, "--tail=100"])
context["logs_current"] = stdout or stderr
# Pod logs (previous container if crashed)
stdout, stderr = run_kubectl(["logs", pod_name, "-n", namespace, "--previous", "--tail=100"])
context["logs_previous"] = stdout or "No previous container logs"
# Pod events
stdout, _ = run_kubectl([
"get", "events", "-n", namespace,
"--field-selector", f"involvedObject.name={pod_name}",
"--sort-by=.metadata.creationTimestamp"
])
context["events"] = stdout
# Pod resource usage (requires metrics-server)
stdout, stderr = run_kubectl(["top", "pod", pod_name, "-n", namespace, "--containers"])
context["resource_usage"] = stdout or "Metrics server not available"
# Pod status JSON (structured data)
stdout, _ = run_kubectl(["get", "pod", pod_name, "-n", namespace, "-o", "json"])
try:
pod_json = json.loads(stdout)
# Extract just the status fields we need
context["status"] = {
"phase": pod_json.get("status", {}).get("phase"),
"conditions": pod_json.get("status", {}).get("conditions", []),
"containerStatuses": pod_json.get("status", {}).get("containerStatuses", []),
"initContainerStatuses": pod_json.get("status", {}).get("initContainerStatuses", []),
}
# Also get resource requests/limits
containers = pod_json.get("spec", {}).get("containers", [])
context["resource_config"] = [
{
"name": c["name"],
"resources": c.get("resources", {}),
"readinessProbe": c.get("readinessProbe"),
"livenessProbe": c.get("livenessProbe"),
}
for c in containers
]
except json.JSONDecodeError:
context["status"] = "Could not parse pod JSON"
return context
def analyze_with_claude(pod_name: str, namespace: str, context: dict) -> str:
"""Send pod context to Claude for root cause analysis."""
prompt = f"""You are a senior Kubernetes SRE. Analyze this broken pod and identify the root cause.
## Pod: {pod_name} in namespace: {namespace}
## Current Status
{json.dumps(context.get('status', {}), indent=2)}
## Resource Configuration
{json.dumps(context.get('resource_config', {}), indent=2)}
## Pod Events
{context.get('events', 'No events')}
## Current Container Logs (last 100 lines)
~~~
{context.get('logs_current', 'No logs')}
~~~
## Previous Container Logs (if crashed)
~~~
{context.get('logs_previous', 'No previous logs')}
~~~
## Resource Usage
{context.get('resource_usage', 'Unknown')}
## Pod Describe (partial)
{context.get('describe', '')[:2000]}
Provide:
1. **Root Cause** (1-2 sentences, be specific — e.g., "OOMKilled: container exceeded 256Mi memory limit" not just "memory issue")
2. **Evidence** (which log line or event proves this)
3. **Fix Commands** (exact kubectl or YAML changes to resolve, copy-paste ready)
4. **Prevention** (what change prevents this in future)
Be direct. If you see a crash, name the error. If it's an OOMKill, say the memory numbers. If it's a readiness probe failing, show the exact path and what it returned."""
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=2000,
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
def debug_pod(pod_name: str, namespace: str = "default"):
"""Main debug function."""
console.print(Panel(f"[bold]AI Pod Debugger[/bold]\nAnalyzing: [cyan]{pod_name}[/cyan] in [green]{namespace}[/green]"))
# Verify pod exists
_, stderr = run_kubectl(["get", "pod", pod_name, "-n", namespace])
if stderr and "not found" in stderr:
console.print(f"[red]Pod not found: {pod_name} in {namespace}[/red]")
sys.exit(1)
# Collect data
with console.status("Collecting pod diagnostics..."):
context = collect_pod_context(pod_name, namespace)
console.print("[green]Data collected. Analyzing with Claude...[/green]\n")
# Analyze
analysis = analyze_with_claude(pod_name, namespace, context)
console.print(Panel(Markdown(analysis), title="[bold green]Root Cause Analysis[/bold green]", border_style="green"))
def find_broken_pods(namespace: str = "default") -> list[str]:
"""Find pods that are not Running or Succeeded."""
stdout, _ = run_kubectl([
"get", "pods", "-n", namespace,
"--field-selector=status.phase!=Running,status.phase!=Succeeded",
"-o", "jsonpath={.items[*].metadata.name}"
])
return stdout.split() if stdout.strip() else []
if __name__ == "__main__":
if len(sys.argv) >= 2:
pod = sys.argv[1]
ns = sys.argv[2] if len(sys.argv) >= 3 else "default"
debug_pod(pod, ns)
else:
# Auto-discover broken pods
console.print("[yellow]No pod specified. Scanning for broken pods...[/yellow]\n")
broken = find_broken_pods()
if not broken:
console.print("[green]No broken pods found![/green]")
else:
console.print(f"Found {len(broken)} broken pods: {', '.join(broken)}")
for pod in broken[:3]: # Debug first 3
debug_pod(pod)
console.print()Usage
# Debug a specific pod
python pod_debugger.py myapp-xyz-abc production
# Auto-discover and debug broken pods
python pod_debugger.py
# Example output:
# Root Cause Analysis
# -------------------
# Root Cause: OOMKilled — the container exceeded its 256Mi memory limit.
# Redis is loading a 180MB dataset on startup, which combined with
# the Python process overhead exceeds the configured limit.
#
# Evidence: containerStatuses shows "reason: OOMKilled" and
# previous container logs end with "Loading RDB file" before kill signal.
#
# Fix Commands:
# kubectl patch deployment myapp -p '{"spec":{"template":{"spec":
# {"containers":[{"name":"api","resources":{"limits":{"memory":"512Mi"}}}]}}}}'
#
# Prevention: Set memory requests = limits (currently they differ by 4x).
# Add Vertical Pod Autoscaler to auto-tune resource limits.Kubernetes RBAC for the Tool
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-debugger
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "events"]
verbs: ["get", "list"]
- apiGroups: ["metrics.k8s.io"]
resources: ["pods"]
verbs: ["get", "list"]This tool saves 10-15 minutes per incident — the Claude analysis pinpoints root cause from 500 lines of logs that would take a human engineer several minutes to read.
More AI DevOps tools? Read our Build AI deployment validator with Claude API and OPA and Build AI runbook generator with Claude API.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Agentic DevOps: How AI Agents Will Autonomously Manage Infrastructure in 2026
AI agents that detect incidents, diagnose root causes, execute remediation, and write postmortems without human intervention are already running in production. Here is what agentic DevOps looks like and where it is heading.
Agentic Platform Engineering: AI Agents as the Self-Service Layer in 2026
Internal developer portals promised self-service infrastructure through forms and templates. The next iteration replaces the form with a conversational agent that understands intent, applies platform guardrails, and provisions correctly — closing the gap between what developers ask for and what golden paths actually need.
AI Agents Making Progressive Delivery Decisions: Where Canary Analysis Is Heading in 2026
Flagger and Argo Rollouts already automate canary promotion against fixed thresholds. The next step is agents that reason about canary metrics the way a human on-call engineer would — accounting for context a static threshold can't capture.