šŸŽ‰ DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Build AI-Powered Kubernetes Policy Enforcer with OPA and Claude

Build an intelligent Kubernetes admission controller that uses OPA for policy enforcement and Claude AI to explain violations, suggest fixes, and auto-generate Rego policies from plain English.

DevOpsBoys4 min read
Share:Tweet

OPA + Gatekeeper enforces Kubernetes policies. But when a policy blocks a deploy, developers get cryptic Rego errors. This project adds Claude AI to explain violations in plain English and even generate new policies from descriptions.


What You're Building

A Kubernetes admission webhook that:

  1. Validates resources with OPA Gatekeeper
  2. When a policy is violated → sends context to Claude
  3. Returns a human-readable explanation + fix suggestion to the developer
  4. Accepts plain-English policy descriptions → generates Rego automatically

Architecture

kubectl apply → API Server → Gatekeeper (OPA)
                                    ↓ violation
                              AI Policy Explainer Service
                                    ↓ Claude API
                              Human-readable error + fix
                                    ↓
                              returned to kubectl (AdmissionReview)

Prerequisites

bash
# Install Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
 
# Verify
kubectl get pods -n gatekeeper-system

Step 1 — OPA Policy (Rego)

Standard constraint template blocking containers without resource limits:

yaml
# constraint-template-require-limits.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: requireresourcelimits
spec:
  crd:
    spec:
      names:
        kind: RequireResourceLimits
  targets:
  - target: admission.k8s.gatekeeper.sh
    rego: |
      package requireresourcelimits
 
      violation[{"msg": msg}] {
        container := input.review.object.spec.containers[_]
        not container.resources.limits.cpu
        msg := sprintf("Container '%v' in pod '%v' is missing CPU limits. Set resources.limits.cpu",
          [container.name, input.review.object.metadata.name])
      }
 
      violation[{"msg": msg}] {
        container := input.review.object.spec.containers[_]
        not container.resources.limits.memory
        msg := sprintf("Container '%v' in pod '%v' is missing memory limits. Set resources.limits.memory",
          [container.name, input.review.object.metadata.name])
      }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequireResourceLimits
metadata:
  name: must-have-resource-limits
spec:
  match:
    kinds:
    - apiGroups: [""]
      kinds: ["Pod"]
    namespaces: ["production", "staging"]

Step 2 — AI Policy Explainer Service

python
# policy_explainer.py
import anthropic
import json
from flask import Flask, request, jsonify
 
app = Flask(__name__)
client = anthropic.Anthropic()
 
SYSTEM_PROMPT = """You are a Kubernetes policy enforcement expert. When given a policy violation,
explain it clearly for a developer in 2-3 sentences. Then provide the exact YAML fix.
Format your response as:
EXPLANATION: <plain English explanation>
FIX:
<yaml code block with the fix>
Keep the fix minimal — only change what's needed."""
 
 
def explain_violation(resource_yaml: str, violation_message: str) -> dict:
    yaml_block = "```yaml\n" + resource_yaml + "\n```"
    user_content = (
        f"Policy violation occurred:\n\nViolation message: {violation_message}\n\n"
        "Resource that triggered it:\n" + yaml_block + "\n\nExplain what's wrong and show the exact fix."
    )
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": user_content}],
    )
 
    text = response.content[0].text
    parts = text.split("FIX:", 1)
 
    return {
        "explanation": parts[0].replace("EXPLANATION:", "").strip(),
        "fix": parts[1].strip() if len(parts) > 1 else "",
    }
 
 
@app.route("/explain", methods=["POST"])
def explain():
    data = request.json
    result = explain_violation(
        resource_yaml=data.get("resource", ""),
        violation_message=data.get("violation", ""),
    )
    return jsonify(result)
 
 
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

Step 3 — Plain English to Rego Generator

python
# rego_generator.py
import anthropic
 
client = anthropic.Anthropic()
 
REGO_SYSTEM = """You are a Rego policy expert for OPA Gatekeeper.
Convert plain English policy descriptions into valid Gatekeeper ConstraintTemplate + Constraint YAML.
Always include proper violation messages that help developers understand what to fix.
Output only valid YAML, no explanation."""
 
 
def generate_policy(description: str, constraint_name: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2048,
        system=REGO_SYSTEM,
        messages=[
            {
                "role": "user",
                "content": f"""Create a Gatekeeper ConstraintTemplate and Constraint for this policy:
 
Policy: {description}
Constraint name: {constraint_name}
 
Apply to: pods in production namespace""",
            }
        ],
    )
    return response.content[0].text
 
 
# Example usage
if __name__ == "__main__":
    policy = generate_policy(
        description="All pods must have a 'team' label with a non-empty value",
        constraint_name="require-team-label",
    )
    print(policy)

Step 4 — Kubernetes Deployment

yaml
# policy-explainer-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-policy-explainer
  namespace: gatekeeper-system
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ai-policy-explainer
  template:
    metadata:
      labels:
        app: ai-policy-explainer
    spec:
      containers:
      - name: explainer
        image: your-registry/ai-policy-explainer:latest
        ports:
        - containerPort: 8080
        env:
        - name: ANTHROPIC_API_KEY
          valueFrom:
            secretKeyRef:
              name: anthropic-secret
              key: api-key
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
---
apiVersion: v1
kind: Secret
metadata:
  name: anthropic-secret
  namespace: gatekeeper-system
type: Opaque
stringData:
  api-key: "your-anthropic-api-key"

Step 5 — kubectl Plugin for AI Explanations

bash
# kubectl-policy-explain plugin
#!/usr/bin/env python3
# Save as /usr/local/bin/kubectl-policy_explain and chmod +x
 
import sys
import subprocess
import requests
import json
 
def get_last_admission_error():
    """Get the last admission webhook error from events"""
    result = subprocess.run(
        ["kubectl", "get", "events", "--field-selector", "reason=FailedCreate",
         "-o", "json", "--all-namespaces"],
        capture_output=True, text=True
    )
    events = json.loads(result.stdout)
    if events["items"]:
        return events["items"][-1]["message"]
    return None
 
if __name__ == "__main__":
    resource_file = sys.argv[1] if len(sys.argv) > 1 else None
    if not resource_file:
        print("Usage: kubectl policy-explain <resource.yaml>")
        sys.exit(1)
 
    with open(resource_file) as f:
        resource_yaml = f.read()
 
    # Try applying and catch the error
    result = subprocess.run(
        ["kubectl", "apply", "--dry-run=server", "-f", resource_file],
        capture_output=True, text=True
    )
 
    if result.returncode != 0:
        violation = result.stderr
        resp = requests.post(
            "http://ai-policy-explainer.gatekeeper-system.svc/explain",
            json={"resource": resource_yaml, "violation": violation}
        )
        data = resp.json()
        print(f"\n🚫 Policy Violation\n")
        print(f"Explanation: {data['explanation']}\n")
        print(f"Fix:\n{data['fix']}")

Testing

bash
# This should fail policy and return AI explanation
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: test-no-limits
  namespace: production
spec:
  containers:
  - name: nginx
    image: nginx:latest
EOF
 
# With kubectl plugin:
kubectl policy-explain my-pod.yaml
# Output:
# 🚫 Policy Violation
# Explanation: Your container 'nginx' doesn't have CPU or memory limits set.
# Without limits, this pod can consume all available node resources and crash other pods.
# Fix:
# resources:
#   limits:
#     cpu: "500m"
#     memory: "512Mi"

Tools Used

  • OPA Gatekeeper — Kubernetes-native policy enforcement
  • Kyverno — Alternative policy engine (easier syntax than Rego)
  • Claude API — AI-powered violation explanations
  • Conftest — Test Kubernetes configs with OPA policies locally

This combination means developers get actionable feedback instead of cryptic Rego errors — dramatically reducing the friction around policy enforcement adoption.

šŸ”§

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

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

Comments