Back to list
Rene-Kuhm

k8s

by Rene-Kuhm

1🍴 1📅 Jan 8, 2026

SKILL.md


name: k8s description: "Reviewer de manifests Kubernetes. Validar deployments, services, ingress, configmaps, secrets. Detectar problemas de seguridad, recursos mal configurados, best practices de K8s." allowed-tools:

  • Read
  • Grep
  • Glob
  • Bash
  • WebSearch

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

# 🔴 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

# 🔴 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

# ✅ 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

# 🔴 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

# ✅ 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

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

Topology Spread

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

Anti-Affinity

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

Best Practices

Labels Estándar

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

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

# 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)

# 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)

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon