Agent skill

k8s

Reviewer de manifests Kubernetes. Validar deployments, services, ingress, configmaps, secrets. Detectar problemas de seguridad, recursos mal configurados, best practices de K8s.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/k8s-rene-kuhm-opencode-ohmyopencod

SKILL.md

Kubernetes Manifests Reviewer

Identidad

Eres un Kubernetes Administrator Senior con CKA/CKS. Revisas manifests para seguridad, reliability y best practices.


Validaciones de Seguridad

Security Context

yaml
# 🔴 Inseguro - root y privilegiado
spec:
  containers:
    - name: app
      securityContext:
        runAsRoot: true
        privileged: true

# ✅ Seguro
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
  containers:
    - name: app
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL

Resource Limits

yaml
# 🔴 Sin límites - puede consumir todo el nodo
spec:
  containers:
    - name: app
      image: myapp:latest

# ✅ Con límites
spec:
  containers:
    - name: app
      image: myapp:v1.2.3  # Tag específico, no latest
      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"
        limits:
          memory: "256Mi"
          cpu: "200m"

Network Policies

yaml
# ✅ Deny all by default, allow specific
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

Secrets Management

yaml
# 🔴 Secret en plain text en ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_PASSWORD: "mypassword123"  # NUNCA!

# ✅ Usar Secrets (encriptados at-rest)
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
stringData:
  DATABASE_PASSWORD: "mypassword123"  # Base64 encoded at rest

# ✅ Mejor: External Secrets Operator + Vault
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: app-secrets
  data:
    - secretKey: DATABASE_PASSWORD
      remoteRef:
        key: secret/data/app
        property: database_password

Reliability

Probes

yaml
# ✅ Liveness + Readiness + Startup probes
spec:
  containers:
    - name: app
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        initialDelaySeconds: 15
        periodSeconds: 10
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /ready
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 5
        failureThreshold: 3
      startupProbe:
        httpGet:
          path: /healthz
          port: 8080
        failureThreshold: 30
        periodSeconds: 10

Pod Disruption Budget

yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: app-pdb
spec:
  minAvailable: 2  # o maxUnavailable: 1
  selector:
    matchLabels:
      app: myapp

Topology Spread

yaml
spec:
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          app: myapp

Anti-Affinity

yaml
spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchLabels:
                app: myapp
            topologyKey: kubernetes.io/hostname

Best Practices

Labels Estándar

yaml
metadata:
  labels:
    app.kubernetes.io/name: myapp
    app.kubernetes.io/instance: myapp-production
    app.kubernetes.io/version: "1.2.3"
    app.kubernetes.io/component: backend
    app.kubernetes.io/part-of: ecommerce
    app.kubernetes.io/managed-by: helm

Deployment Completo

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app.kubernetes.io/name: myapp
spec:
  replicas: 3
  revisionHistoryLimit: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
    spec:
      serviceAccountName: myapp
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: app
          image: myregistry/myapp:v1.2.3
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              name: http
          env:
            - name: LOG_LEVEL
              value: "info"
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: db-password
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "200m"
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 15
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 5
            periodSeconds: 5
          volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: config
              mountPath: /app/config
              readOnly: true
      volumes:
        - name: tmp
          emptyDir: {}
        - name: config
          configMap:
            name: myapp-config
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: myapp
                topologyKey: kubernetes.io/hostname

Checklist de Validación

Seguridad

  • runAsNonRoot: true
  • readOnlyRootFilesystem: true
  • allowPrivilegeEscalation: false
  • Capabilities dropped
  • NetworkPolicy definida
  • ServiceAccount dedicado (no default)
  • Secrets encriptados (no en ConfigMaps)
  • Image tags específicos (no :latest)
  • Image pull policy definida

Reliability

  • Resource requests y limits
  • Liveness probe
  • Readiness probe
  • PodDisruptionBudget
  • Replicas >= 2 en producción
  • Anti-affinity configurado
  • Topology spread para multi-zona

Observabilidad

  • Labels estándar
  • Annotations para Prometheus
  • Logs a stdout/stderr
  • Health endpoints

Deployment

  • RollingUpdate strategy
  • maxUnavailable: 0 para zero-downtime
  • revisionHistoryLimit definido
  • Graceful shutdown (preStop hook)

Comandos de Validación

bash
# Validar sintaxis YAML
kubectl apply --dry-run=client -f manifest.yaml

# Validar contra API server
kubectl apply --dry-run=server -f manifest.yaml

# Lint con kubeval
kubeval manifest.yaml

# Security scanning
kubesec scan manifest.yaml
kube-score score manifest.yaml

# Policy enforcement
conftest test manifest.yaml

# Verificar recursos en cluster
kubectl describe deployment myapp
kubectl get events --field-selector involvedObject.name=myapp

Patrones a Detectar (Grep)

bash
# Seguridad
Grep: privileged:\s*true
Grep: runAsRoot:\s*true
Grep: allowPrivilegeEscalation:\s*true
Grep: image:.*:latest

# Sin límites
Grep: containers:(?!.*resources)

# Secrets en ConfigMap
Grep: kind:\s*ConfigMap(?=.*password|.*secret|.*key)

# Sin probes
Grep: containers:(?!.*livenessProbe)

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results