
Kubernetes Operations
- 81 installs
- 14 repo stars
- Updated April 20, 2026
- nodnarbnitram/claude-code-extensions
Helps with devops & ci/cd tasks during AI-assisted development.
About
kubernetes-operations is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted coding.
- kubernetes-operations
- DevOps & CI/CD
- AI-coding skill
Kubernetes Operations by the numbers
- 81 all-time installs (skills.sh)
- Ranked #587 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/nodnarbnitram/claude-code-extensions --skill kubernetes-operationsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 81 |
|---|---|
| repo stars | ★ 14 |
| Last updated | April 20, 2026 |
| Repository | nodnarbnitram/claude-code-extensions ↗ |
What it does
Helps with devops & ci/cd tasks during AI-assisted development.
Files
Kubernetes Operations
Comprehensive kubectl assistance for debugging, resource management, and cluster operations with token-efficient scripts.
BEFORE YOU START
This skill prevents 5 common errors and saves ~70% tokens.
| Metric | Without Skill | With Skill |
|---|---|---|
| Pod Debugging | ~1200 tokens | ~400 tokens |
| Resource Listing | ~800 tokens | ~200 tokens |
| Cluster Health | ~1500 tokens | ~300 tokens |
Known Issues This Skill Prevents
1. Running kubectl commands in wrong namespace/context 2. Verbose output flooding context with unnecessary data 3. Missing critical debugging steps (events, previous logs) 4. Exposing secrets in plain text output 5. Destructive operations without dry-run verification
Quick Start
Step 1: Verify Context
kubectl config current-context
kubectl config get-contextsWhy this matters: Running commands in the wrong cluster can cause production incidents.
Step 2: Debug a Pod
uv run scripts/debug_pod.py <pod-name> [-n namespace]Why this matters: The script combines describe, logs, and events into a condensed summary, saving ~800 tokens.
Step 3: Check Cluster Health
uv run scripts/cluster_health.pyWhy this matters: Quick overview of node status and unhealthy pods without verbose output.
Critical Rules
Always Do
- Always verify
kubectl config current-contextbefore operations - Always use
-n namespaceto be explicit about target - Always use
--dry-run=client -o yamlbefore applying changes - Always check events when debugging:
kubectl get events --sort-by='.lastTimestamp' - Always use
--previousflag when pod is in CrashLoopBackOff
Never Do
- Never run
kubectl deletewithout--dry-runfirst in production - Never output secrets without filtering: avoid
kubectl get secret -o yaml - Never assume default namespace - always specify
-n - Never ignore resource limits when debugging OOMKilled pods
- Never skip
describewhen logs show no errors
Common Mistakes
Wrong:
kubectl logs my-podCorrect:
kubectl logs my-pod -n my-namespace --tail=100 --timestampsWhy: Default namespace may not be correct, unlimited logs flood context, timestamps help correlate with events.
Known Issues Prevention
| Issue | Root Cause | Solution |
|---|---|---|
| CrashLoopBackOff | App crash on startup | Check kubectl logs --previous and describe for exit codes |
| ImagePullBackOff | Registry auth or image tag | Verify image exists and check pull secrets |
| Pending pods | No schedulable nodes | Check node resources and pod affinity/tolerations |
| OOMKilled | Memory limit exceeded | Check container limits vs actual usage with kubectl top |
| Connection refused | Service selector mismatch | Verify pod labels match service selector |
Debugging Workflows
Pod Not Starting
# 1. Get pod status and events
kubectl describe pod <name> -n <namespace>
# 2. Check logs (current or previous)
kubectl logs <name> -n <namespace> --tail=100
kubectl logs <name> -n <namespace> --previous # If restarting
# 3. Check events for scheduling issues
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | grep <name>
# 4. Interactive debugging
kubectl exec -it <name> -n <namespace> -- /bin/shService Connectivity
# 1. Verify service exists and has endpoints
kubectl get svc <name> -n <namespace>
kubectl get endpoints <name> -n <namespace>
# 2. Check pod labels match service selector
kubectl get pods -n <namespace> --show-labels
# 3. Test from within cluster
kubectl run debug --rm -it --image=busybox -- wget -qO- http://<service>:<port>
# 4. Port-forward for local testing
kubectl port-forward svc/<name> 8080:80 -n <namespace>Resource Management
Deployments
# List deployments
kubectl get deployments -n <namespace>
# Scale
kubectl scale deployment <name> --replicas=3 -n <namespace>
# Rollout status
kubectl rollout status deployment/<name> -n <namespace>
# Rollback
kubectl rollout undo deployment/<name> -n <namespace>
# History
kubectl rollout history deployment/<name> -n <namespace>ConfigMaps and Secrets
# List
kubectl get configmaps -n <namespace>
kubectl get secrets -n <namespace>
# View ConfigMap data
kubectl get configmap <name> -n <namespace> -o jsonpath='{.data}'
# View Secret keys (NOT values)
kubectl get secret <name> -n <namespace> -o jsonpath='{.data}' | jq 'keys'
# Create from file
kubectl create configmap <name> --from-file=<path> -n <namespace> --dry-run=client -o yamlCluster Operations
Node Management
# List nodes with status
kubectl get nodes -o wide
# Node details
kubectl describe node <name>
# Cordon (prevent scheduling)
kubectl cordon <node>
# Drain (evict pods)
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# Uncordon
kubectl uncordon <node>Resource Usage
# Node resources
kubectl top nodes
# Pod resources
kubectl top pods -n <namespace>
# Sort by memory
kubectl top pods -n <namespace> --sort-by=memoryBundled Resources
Scripts
Located in scripts/:
debug_pod.py- Comprehensive pod debugging with condensed outputget_resources.py- Resource summary using jsonpath for minimal tokenscluster_health.py- Quick cluster status overview
References
Located in references/:
- `kubectl-cheatsheet.md` - Condensed command reference
- `jsonpath-patterns.md` - Common JSONPath expressions
- `debugging-flowchart.md` - Decision tree for pod issues
Note: For deep dives on specific topics, see the reference files above.
Dependencies
Required
| Package | Version | Purpose |
|---|---|---|
| kubectl | 1.25+ | Kubernetes CLI |
| jq | 1.6+ | JSON parsing for scripts |
Optional
| Package | Version | Purpose |
|---|---|---|
| k9s | 0.27+ | Terminal UI for Kubernetes |
| stern | 1.25+ | Multi-pod log tailing |
Official Documentation
Troubleshooting
kubectl command not found
Symptoms: command not found: kubectl
Solution:
# macOS
brew install kubectl
# Verify
kubectl version --clientContext not set
Symptoms: error: no context is currently set
Solution:
# List available contexts
kubectl config get-contexts
# Set context
kubectl config use-context <context-name>Permission denied
Symptoms: Error from server (Forbidden)
Solution:
# Check current user
kubectl auth whoami
# Check permissions
kubectl auth can-i get pods -n <namespace>
kubectl auth can-i --list -n <namespace>Timeout connecting to cluster
Symptoms: Unable to connect to the server: dial tcp: i/o timeout
Solution:
# Check cluster endpoint
kubectl cluster-info
# Verify network connectivity
curl -k https://<cluster-api-endpoint>/healthz
# Check kubeconfig
cat ~/.kube/configSetup Checklist
Before using this skill, verify:
- [ ]
kubectlinstalled (kubectl version --client) - [ ] Kubeconfig configured (
~/.kube/configexists) - [ ] Context set to correct cluster (
kubectl config current-context) - [ ] Permissions verified (
kubectl auth can-i get pods) - [ ]
jqinstalled for JSON parsing (jq --version)
Kubernetes Operations
Comprehensive kubectl assistance for debugging, resource management, and cluster operations with token-efficient scripts.
| Status | Active |
| Version | 1.0.0 |
| Last Updated | 2025-11-22 |
| Confidence | 4/5 |
| Production Tested | Yes |
What This Skill Does
Provides intelligent assistance for Kubernetes operations using kubectl. Includes token-efficient Python scripts that condense verbose kubectl output into actionable summaries.
Core Capabilities
- Debug pods with condensed status, events, and logs
- Manage resources (deployments, services, configmaps, secrets)
- Monitor cluster health and resource usage
- Troubleshoot common Kubernetes issues
Auto-Trigger Keywords
Primary Keywords
Exact terms that strongly trigger this skill:
- kubectl
- kubernetes
- k8s
- pods
- deployments
Secondary Keywords
Related terms that may trigger in combination:
- cluster
- namespace
- service
- configmap
- secret
- nodes
- replicas
- rollout
Error-Based Keywords
Common error messages that should trigger this skill:
- "CrashLoopBackOff"
- "ImagePullBackOff"
- "Pending"
- "OOMKilled"
- "connection refused"
- "no endpoints available"
- "forbidden"
Known Issues Prevention
| Issue | Root Cause | Solution |
|---|---|---|
| Wrong cluster context | Not verifying before commands | Always check kubectl config current-context |
| Verbose output flooding | Using default kubectl output | Use scripts or jsonpath for minimal output |
| Missing debug info | Incomplete investigation | Use debug_pod.py for comprehensive view |
| Secret exposure | Outputting secrets as YAML | Never output secrets in plain text |
When to Use
Use This Skill For
- Debugging pod startup issues
- Checking cluster health
- Managing Kubernetes resources
- Troubleshooting service connectivity
- Viewing logs and events
Don't Use This Skill For
- Creating Helm charts (use helm-chart-scaffolding skill)
- ArgoCD/GitOps workflows (use argocd agents)
- Terraform/IaC for cluster provisioning
- Custom Resource Definition development
Quick Usage
# Debug a pod
uv run scripts/debug_pod.py my-pod -n my-namespace
# List resources compactly
uv run scripts/get_resources.py pods -n my-namespace
# Check cluster health
uv run scripts/cluster_health.pyToken Efficiency
| Approach | Estimated Tokens | Time |
|---|---|---|
| Manual kubectl commands | ~1200 | 5+ min |
| With This Skill | ~400 | 1 min |
| Savings | 67% | 4 min |
File Structure
kubernetes-operations/
├── SKILL.md # Detailed instructions and patterns
├── README.md # This file - discovery and quick reference
├── scripts/ # Token-efficient automation scripts
│ ├── debug_pod.py
│ ├── get_resources.py
│ └── cluster_health.py
├── references/ # Supporting documentation
│ ├── kubectl-cheatsheet.md
│ ├── jsonpath-patterns.md
│ └── debugging-flowchart.md
└── assets/ # Templates and resourcesDependencies
| Package | Version | Verified |
|---|---|---|
| kubectl | 1.25+ | 2024-11-22 |
| jq | 1.6+ | 2024-11-22 |
Official Documentation
Related Skills
helm-chart-scaffolding- Helm chart creation and managementk8s-manifest-generator- Generate Kubernetes YAML manifestsgitops-workflow- ArgoCD/Flux GitOps patterns
---
License: MIT
Kubernetes Debugging Flowchart
Decision tree for common pod issues.
Pod Not Starting
Pod Status?
├── Pending
│ ├── Check: kubectl describe pod <name>
│ ├── Look for: "Events" section
│ └── Common causes:
│ ├── Insufficient resources → Check node capacity, adjust requests/limits
│ ├── No matching nodes → Check nodeSelector, affinity, tolerations
│ ├── PVC not bound → Check PVC status and StorageClass
│ └── Image pull issues → Check imagePullSecrets
│
├── ContainerCreating
│ ├── Check: kubectl describe pod <name>
│ └── Common causes:
│ ├── Image pull error → Verify image name and registry auth
│ ├── ConfigMap/Secret missing → Verify referenced resources exist
│ └── Volume mount issues → Check PVC and volume configuration
│
├── CrashLoopBackOff
│ ├── Check: kubectl logs <name> --previous
│ ├── Check: kubectl describe pod <name> (exit code)
│ └── Common causes:
│ ├── Exit code 1 → Application error, check logs
│ ├── Exit code 137 → OOMKilled, increase memory limit
│ ├── Exit code 143 → SIGTERM, check liveness probe
│ └── Missing config → Check env vars and mounts
│
├── ImagePullBackOff
│ ├── Check: kubectl describe pod <name>
│ └── Common causes:
│ ├── Image not found → Verify image:tag exists
│ ├── Auth error → Check imagePullSecrets
│ └── Network error → Check registry connectivity
│
└── Running but not working
├── Check: kubectl logs <name>
├── Check: kubectl exec -it <name> -- /bin/sh
└── Common causes:
├── Readiness probe failing → Check probe config and endpoint
├── Wrong command/args → Verify entrypoint
└── Missing dependencies → Check service connectivityService Not Accessible
Can't reach service?
│
├── Check service exists
│ kubectl get svc <name> -n <ns>
│
├── Check endpoints
│ kubectl get endpoints <name> -n <ns>
│ └── Empty? → Pod labels don't match service selector
│
├── Check pod labels match selector
│ kubectl get svc <name> -o jsonpath='{.spec.selector}'
│ kubectl get pods -l <selector> -n <ns>
│
├── Test from within cluster
│ kubectl run debug --rm -it --image=busybox -- wget -qO- http://<svc>:<port>
│
└── Check NetworkPolicy
kubectl get networkpolicy -n <ns>
└── Blocking traffic? → Update policy or test without itHigh Resource Usage
Resource issues?
│
├── Check current usage
│ kubectl top pods -n <ns>
│ kubectl top nodes
│
├── OOMKilled containers
│ ├── Check: kubectl describe pod <name> (look for OOMKilled)
│ ├── Solution: Increase memory limits
│ └── Investigate: Profile application memory usage
│
├── CPU throttling
│ ├── Check: kubectl describe pod <name> (look for CPU limits)
│ └── Solution: Increase CPU limits or optimize application
│
└── Node pressure
├── Check: kubectl describe node <name>
├── Look for: MemoryPressure, DiskPressure, PIDPressure
└── Solution: Add nodes, evict pods, or clean up diskQuick Diagnosis Commands
# 1. Get overview
kubectl get pods -n <ns> -o wide
# 2. Check specific pod
kubectl describe pod <name> -n <ns>
# 3. Get logs
kubectl logs <name> -n <ns> --tail=100
# 4. Get previous logs (if restarting)
kubectl logs <name> -n <ns> --previous
# 5. Check events
kubectl get events -n <ns> --sort-by='.lastTimestamp' | tail -20
# 6. Shell into pod
kubectl exec -it <name> -n <ns> -- /bin/sh
# 7. Check resource usage
kubectl top pod <name> -n <ns>Exit Code Reference
| Code | Signal | Meaning |
|---|---|---|
| 0 | - | Success |
| 1 | - | General error |
| 126 | - | Command not executable |
| 127 | - | Command not found |
| 128+n | Signal n | Killed by signal |
| 137 | SIGKILL (9) | OOMKilled or force killed |
| 143 | SIGTERM (15) | Graceful termination |
| 255 | - | Exit status out of range |
JSONPath Patterns for kubectl
Reference for kubectl JSONPath support.
Basic Syntax
kubectl get <resource> -o jsonpath='{.field.subfield}'Common Patterns
Pod Status
# Pod phase
kubectl get pod <name> -o jsonpath='{.status.phase}'
# Container status
kubectl get pod <name> -o jsonpath='{.status.containerStatuses[0].state}'
# Restart count
kubectl get pod <name> -o jsonpath='{.status.containerStatuses[0].restartCount}'
# Pod IP
kubectl get pod <name> -o jsonpath='{.status.podIP}'
# Node name
kubectl get pod <name> -o jsonpath='{.spec.nodeName}'Multiple Values
# Name and status for all pods
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
# With custom separator
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}|{.status.phase}\n{end}'Filtering
# Pods with specific label
kubectl get pods -o jsonpath='{.items[?(@.metadata.labels.app=="nginx")].metadata.name}'
# Ready nodes only
kubectl get nodes -o jsonpath='{.items[?(@.status.conditions[?(@.type=="Ready")].status=="True")].metadata.name}'
# Non-running pods
kubectl get pods -o jsonpath='{.items[?(@.status.phase!="Running")].metadata.name}'Node Information
# Node capacity
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.capacity.cpu}{"\t"}{.status.capacity.memory}{"\n"}{end}'
# Node conditions
kubectl get nodes -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}'
# Allocatable resources
kubectl get node <name> -o jsonpath='{.status.allocatable}'Service & Endpoints
# Service ClusterIP
kubectl get svc <name> -o jsonpath='{.spec.clusterIP}'
# Service ports
kubectl get svc <name> -o jsonpath='{.spec.ports[*].port}'
# Endpoint addresses
kubectl get endpoints <name> -o jsonpath='{.subsets[*].addresses[*].ip}'ConfigMaps & Secrets
# ConfigMap data keys
kubectl get configmap <name> -o jsonpath='{.data}' | jq 'keys'
# Specific ConfigMap value
kubectl get configmap <name> -o jsonpath='{.data.key-name}'
# Secret keys (not values)
kubectl get secret <name> -o jsonpath='{.data}' | jq 'keys'
# Decode secret value
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -dDeployments
# Replica count
kubectl get deployment <name> -o jsonpath='{.spec.replicas}'
# Ready replicas
kubectl get deployment <name> -o jsonpath='{.status.readyReplicas}'
# Container images
kubectl get deployment <name> -o jsonpath='{.spec.template.spec.containers[*].image}'
# Deployment conditions
kubectl get deployment <name> -o jsonpath='{.status.conditions[?(@.type=="Available")].status}'Events
# Recent event messages
kubectl get events -o jsonpath='{range .items[*]}{.reason}: {.message}{"\n"}{end}'
# Events for specific object
kubectl get events --field-selector involvedObject.name=<pod> -o jsonpath='{range .items[*]}{.reason}: {.message}{"\n"}{end}'Output Formatting
Custom Columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,IP:.status.podIPSorted Output
# Sort by creation time
kubectl get pods --sort-by='.metadata.creationTimestamp'
# Sort by restart count
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'Tips
1. Test incrementally: Start with '{.metadata}' then drill down 2. Use jq for complex parsing: Pipe JSON output to jq 3. Escape special characters: Use \" inside jsonpath strings 4. Range for iteration: {range .items[*]}...{end} for lists 5. Filters use ?(@): {.items[?(@.field=="value")]}
kubectl Cheatsheet
Condensed from official quick reference.
Context & Config
kubectl config current-context # Show current context
kubectl config get-contexts # List all contexts
kubectl config use-context <name> # Switch context
kubectl config set-context --current --namespace=<ns> # Set default namespaceGet Resources
kubectl get <resource> -n <ns> # List resources
kubectl get <resource> -o wide # More columns
kubectl get <resource> -o yaml # YAML output
kubectl get <resource> -o json # JSON output
kubectl get <resource> --show-labels # Show labels
kubectl get <resource> -l key=value # Filter by label
kubectl get <resource> --all-namespaces # All namespacesDescribe & Logs
kubectl describe <resource> <name> -n <ns> # Detailed info
kubectl logs <pod> -n <ns> # Pod logs
kubectl logs <pod> -c <container> # Specific container
kubectl logs <pod> --tail=100 # Last 100 lines
kubectl logs <pod> -f # Follow logs
kubectl logs <pod> --previous # Previous container
kubectl logs <pod> --timestamps # With timestampsCreate & Apply
kubectl create -f <file.yaml> # Create from file
kubectl apply -f <file.yaml> # Apply (create or update)
kubectl apply -f <dir>/ # Apply all in directory
kubectl apply -k <dir>/ # Apply with kustomize
kubectl create configmap <name> --from-file=<path>
kubectl create secret generic <name> --from-literal=key=valueEdit & Patch
kubectl edit <resource> <name> -n <ns> # Edit in editor
kubectl patch <resource> <name> -p '{"spec":{"replicas":3}}'
kubectl set image deployment/<name> <container>=<image>Delete
kubectl delete <resource> <name> -n <ns>
kubectl delete -f <file.yaml>
kubectl delete <resource> --all -n <ns>
kubectl delete pod <name> --force --grace-period=0 # Force deleteExec & Debug
kubectl exec -it <pod> -- /bin/sh # Shell into pod
kubectl exec -it <pod> -c <container> -- /bin/sh # Specific container
kubectl run debug --rm -it --image=busybox -- /bin/sh # Debug pod
kubectl cp <pod>:<path> <local-path> # Copy from pod
kubectl cp <local-path> <pod>:<path> # Copy to podPort Forward
kubectl port-forward <pod> 8080:80 # Pod
kubectl port-forward svc/<name> 8080:80 # Service
kubectl port-forward deploy/<name> 8080:80 # DeploymentScaling & Rollouts
kubectl scale deployment <name> --replicas=3
kubectl autoscale deployment <name> --min=2 --max=10 --cpu-percent=80
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
kubectl rollout restart deployment/<name>Labels & Annotations
kubectl label <resource> <name> key=value
kubectl label <resource> <name> key- # Remove label
kubectl annotate <resource> <name> key=valueResource Usage
kubectl top nodes
kubectl top pods -n <ns>
kubectl top pods --sort-by=memory
kubectl top pods --sort-by=cpuEvents
kubectl get events -n <ns>
kubectl get events --sort-by='.lastTimestamp'
kubectl get events --field-selector reason=FailedAuth & RBAC
kubectl auth whoami
kubectl auth can-i get pods -n <ns>
kubectl auth can-i --list -n <ns>
kubectl get roles,rolebindings -n <ns>
kubectl get clusterroles,clusterrolebindingsDry Run
kubectl apply -f file.yaml --dry-run=client -o yaml
kubectl create deployment <name> --image=<img> --dry-run=client -o yaml#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Quick Kubernetes cluster health check.
Usage:
uv run cluster_health.py
Output:
Condensed cluster status with node health and unhealthy pod count.
Saves ~1200 tokens compared to running multiple commands.
"""
import subprocess
import sys
def run_kubectl(args: list[str]) -> tuple[str, int]:
"""Run kubectl command and return output and exit code."""
try:
result = subprocess.run(
["kubectl"] + args,
capture_output=True,
text=True,
timeout=30
)
return result.stdout + result.stderr, result.returncode
except subprocess.TimeoutExpired:
return "Command timed out", 1
except FileNotFoundError:
return "kubectl not found", 1
def get_current_context() -> str:
"""Get current kubectl context."""
output, code = run_kubectl(["config", "current-context"])
if code != 0:
return "unknown"
return output.strip()
def get_node_status() -> list[dict]:
"""Get node status summary."""
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.status.conditions[?(@.type=="Ready")].status}|'
'{.status.allocatable.cpu}|{.status.allocatable.memory}\n'
'{end}'
)
output, code = run_kubectl(["get", "nodes", "-o", f"jsonpath={jsonpath}"])
if code != 0:
return []
nodes = []
for line in output.strip().split("\n"):
if not line.strip():
continue
parts = line.split("|")
if len(parts) >= 4:
nodes.append({
"name": parts[0],
"ready": parts[1] == "True",
"cpu": parts[2],
"memory": parts[3]
})
return nodes
def get_unhealthy_pods() -> list[dict]:
"""Get pods that are not Running or Succeeded."""
output, code = run_kubectl([
"get", "pods", "--all-namespaces",
"--field-selector", "status.phase!=Running,status.phase!=Succeeded",
"-o", "jsonpath={range .items[*]}{.metadata.namespace}/{.metadata.name}|{.status.phase}\n{end}"
])
if code != 0:
return []
pods = []
for line in output.strip().split("\n"):
if not line.strip():
continue
parts = line.split("|")
if len(parts) >= 2:
pods.append({
"name": parts[0],
"phase": parts[1]
})
return pods
def get_resource_pressure() -> dict:
"""Check for resource pressure conditions on nodes."""
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|'
'{.status.conditions[?(@.type=="MemoryPressure")].status}|'
'{.status.conditions[?(@.type=="DiskPressure")].status}|'
'{.status.conditions[?(@.type=="PIDPressure")].status}\n'
'{end}'
)
output, code = run_kubectl(["get", "nodes", "-o", f"jsonpath={jsonpath}"])
if code != 0:
return {}
pressure = {
"memory": [],
"disk": [],
"pid": []
}
for line in output.strip().split("\n"):
if not line.strip():
continue
parts = line.split("|")
if len(parts) >= 4:
name = parts[0]
if parts[1] == "True":
pressure["memory"].append(name)
if parts[2] == "True":
pressure["disk"].append(name)
if parts[3] == "True":
pressure["pid"].append(name)
return pressure
def main():
context = get_current_context()
print(f"## Cluster Health: {context}\n")
# Node status
nodes = get_node_status()
if not nodes:
print("**Error:** Could not get node status")
sys.exit(1)
ready_count = sum(1 for n in nodes if n["ready"])
total_count = len(nodes)
print("### Nodes")
print(f"- Ready: {ready_count}/{total_count}")
if ready_count < total_count:
not_ready = [n["name"] for n in nodes if not n["ready"]]
print(f"- Not Ready: {', '.join(not_ready)}")
# Resource pressure
pressure = get_resource_pressure()
has_pressure = any(pressure.values())
if has_pressure:
print("\n### Resource Pressure")
if pressure["memory"]:
print(f"- Memory: {', '.join(pressure['memory'])}")
if pressure["disk"]:
print(f"- Disk: {', '.join(pressure['disk'])}")
if pressure["pid"]:
print(f"- PID: {', '.join(pressure['pid'])}")
else:
print("- Pressure: None")
# Unhealthy pods
unhealthy = get_unhealthy_pods()
print("\n### Pods")
if unhealthy:
print(f"- Unhealthy: {len(unhealthy)}")
# Show first 5
for pod in unhealthy[:5]:
print(f" - {pod['name']}: {pod['phase']}")
if len(unhealthy) > 5:
print(f" - ... and {len(unhealthy) - 5} more")
else:
print("- Unhealthy: 0")
# Summary
print("\n### Summary")
if ready_count == total_count and not unhealthy and not has_pressure:
print("Cluster is healthy")
else:
issues = []
if ready_count < total_count:
issues.append(f"{total_count - ready_count} nodes not ready")
if unhealthy:
issues.append(f"{len(unhealthy)} unhealthy pods")
if has_pressure:
issues.append("resource pressure detected")
print(f"Issues: {', '.join(issues)}")
if __name__ == "__main__":
main()
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Debug a Kubernetes pod with condensed output.
Usage:
uv run debug_pod.py <pod-name> [-n namespace]
Output:
Condensed summary with status, events, and log tail.
Saves ~800 tokens compared to running commands separately.
"""
import subprocess
import sys
import argparse
def run_kubectl(args: list[str]) -> tuple[str, int]:
"""Run kubectl command and return output and exit code."""
try:
result = subprocess.run(
["kubectl"] + args,
capture_output=True,
text=True,
timeout=30
)
return result.stdout + result.stderr, result.returncode
except subprocess.TimeoutExpired:
return "Command timed out", 1
except FileNotFoundError:
return "kubectl not found", 1
def get_pod_status(pod: str, namespace: str) -> dict:
"""Get pod status using jsonpath for minimal output."""
jsonpath = (
'{.metadata.name}|'
'{.status.phase}|'
'{.status.containerStatuses[0].restartCount}|'
'{.status.containerStatuses[0].state}|'
'{.status.containerStatuses[0].lastState}'
)
args = ["get", "pod", pod, "-n", namespace, "-o", f"jsonpath={jsonpath}"]
output, code = run_kubectl(args)
if code != 0:
return {"error": output.strip()}
parts = output.split("|")
if len(parts) >= 5:
return {
"name": parts[0],
"phase": parts[1],
"restarts": parts[2],
"state": parts[3][:100] if parts[3] else "unknown",
"lastState": parts[4][:100] if parts[4] else "none"
}
return {"error": "Could not parse pod status"}
def get_events(pod: str, namespace: str) -> list[str]:
"""Get recent events for the pod."""
args = [
"get", "events", "-n", namespace,
"--field-selector", f"involvedObject.name={pod}",
"--sort-by", ".lastTimestamp",
"-o", "jsonpath={range .items[-5:]}{.reason}: {.message}\n{end}"
]
output, code = run_kubectl(args)
if code != 0 or not output.strip():
return ["No recent events"]
return [line.strip() for line in output.strip().split("\n") if line.strip()]
def get_logs(pod: str, namespace: str, previous: bool = False) -> str:
"""Get last 20 lines of logs."""
args = ["logs", pod, "-n", namespace, "--tail=20"]
if previous:
args.append("--previous")
output, code = run_kubectl(args)
if code != 0:
return f"Could not get logs: {output.strip()[:100]}"
return output.strip() if output.strip() else "No logs available"
def main():
parser = argparse.ArgumentParser(description="Debug a Kubernetes pod")
parser.add_argument("pod", help="Pod name")
parser.add_argument("-n", "--namespace", default="default", help="Namespace")
args = parser.parse_args()
print(f"## Pod Debug: {args.pod} (ns: {args.namespace})\n")
# Status
status = get_pod_status(args.pod, args.namespace)
if "error" in status:
print(f"**Error:** {status['error']}")
sys.exit(1)
print("### Status")
print(f"- Phase: {status['phase']}")
print(f"- Restarts: {status['restarts']}")
print(f"- State: {status['state']}")
if status['lastState'] != "none":
print(f"- Last State: {status['lastState']}")
# Events
print("\n### Recent Events")
events = get_events(args.pod, args.namespace)
for event in events[-5:]:
print(f"- {event}")
# Logs
print("\n### Logs (last 20 lines)")
# Check if we need previous logs
restarts = int(status['restarts']) if status['restarts'] else 0
need_previous = "CrashLoopBackOff" in status['state'] or restarts > 0
if need_previous:
print("*(showing previous container logs due to restarts)*\n")
logs = get_logs(args.pod, args.namespace, previous=True)
else:
logs = get_logs(args.pod, args.namespace)
print("```")
print(logs)
print("```")
if __name__ == "__main__":
main()
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Get Kubernetes resources in compact format.
Usage:
uv run get_resources.py <resource-type> [-n namespace] [-l label-selector]
Output:
Compact table with name, status, age.
Saves ~600 tokens compared to default kubectl output.
"""
import subprocess
import sys
import argparse
from datetime import datetime, timezone
def run_kubectl(args: list[str]) -> tuple[str, int]:
"""Run kubectl command and return output and exit code."""
try:
result = subprocess.run(
["kubectl"] + args,
capture_output=True,
text=True,
timeout=30
)
return result.stdout + result.stderr, result.returncode
except subprocess.TimeoutExpired:
return "Command timed out", 1
except FileNotFoundError:
return "kubectl not found", 1
def get_resources(resource_type: str, namespace: str, selector: str | None) -> str:
"""Get resources using jsonpath for minimal output."""
# Different jsonpath based on resource type
if resource_type in ["pods", "pod", "po"]:
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.status.phase}|{.metadata.creationTimestamp}\n'
'{end}'
)
elif resource_type in ["deployments", "deployment", "deploy"]:
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.status.readyReplicas}/{.spec.replicas}|{.metadata.creationTimestamp}\n'
'{end}'
)
elif resource_type in ["services", "service", "svc"]:
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.spec.type}|{.spec.clusterIP}|{.metadata.creationTimestamp}\n'
'{end}'
)
elif resource_type in ["configmaps", "configmap", "cm"]:
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.metadata.creationTimestamp}\n'
'{end}'
)
elif resource_type in ["secrets", "secret"]:
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.type}|{.metadata.creationTimestamp}\n'
'{end}'
)
else:
# Generic fallback
jsonpath = (
'{range .items[*]}'
'{.metadata.name}|{.metadata.creationTimestamp}\n'
'{end}'
)
args = ["get", resource_type, "-n", namespace, "-o", f"jsonpath={jsonpath}"]
if selector:
args.extend(["-l", selector])
output, code = run_kubectl(args)
if code != 0:
return f"Error: {output.strip()}"
return output.strip()
def format_age(timestamp: str) -> str:
"""Convert ISO timestamp to human-readable age."""
if not timestamp:
return "unknown"
try:
created = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
now = datetime.now(timezone.utc)
delta = now - created
if delta.days > 0:
return f"{delta.days}d"
elif delta.seconds >= 3600:
return f"{delta.seconds // 3600}h"
elif delta.seconds >= 60:
return f"{delta.seconds // 60}m"
else:
return f"{delta.seconds}s"
except (ValueError, TypeError):
return timestamp[:10] if len(timestamp) > 10 else timestamp
def main():
parser = argparse.ArgumentParser(description="Get Kubernetes resources")
parser.add_argument("resource", help="Resource type (pods, deployments, services, etc.)")
parser.add_argument("-n", "--namespace", default="default", help="Namespace")
parser.add_argument("-l", "--selector", help="Label selector")
args = parser.parse_args()
print(f"## {args.resource} (ns: {args.namespace})\n")
output = get_resources(args.resource, args.namespace, args.selector)
if output.startswith("Error:"):
print(output)
sys.exit(1)
if not output:
print("No resources found")
sys.exit(0)
# Parse and format output
lines = output.strip().split("\n")
# Determine header based on resource type
if args.resource in ["pods", "pod", "po"]:
print("| Name | Status | Age |")
print("|------|--------|-----|")
elif args.resource in ["deployments", "deployment", "deploy"]:
print("| Name | Ready | Age |")
print("|------|-------|-----|")
elif args.resource in ["services", "service", "svc"]:
print("| Name | Type | ClusterIP | Age |")
print("|------|------|-----------|-----|")
elif args.resource in ["secrets", "secret"]:
print("| Name | Type | Age |")
print("|------|------|-----|")
else:
print("| Name | Age |")
print("|------|-----|")
for line in lines:
if not line.strip():
continue
parts = line.split("|")
# Format age from timestamp
if len(parts) >= 2:
parts[-1] = format_age(parts[-1])
print(f"| {' | '.join(parts)} |")
if __name__ == "__main__":
main()