Seguridad en Kubernetes 2026: Pod Security Admission, Kyverno y Gatekeeper

Guía práctica de seguridad Kubernetes 2026: configura Pod Security Admission, compara Kyverno vs OPA Gatekeeper y migra desde PodSecurityPolicy con ejemplos YAML probados en producción.

Kubernetes 2026: PSA, Kyverno y Gatekeeper

Actualizado: 24 de mayo de 2026

La seguridad en Kubernetes 2026 se construye sobre tres pilares complementarios: Pod Security Admission (PSA) integrado en el API server desde la versión 1.25, y dos motores de políticas externos (Kyverno y OPA Gatekeeper) que extienden esos controles con reglas personalizadas, mutaciones y validación de imágenes. Esta guía explica cuándo usar cada uno, cómo aplicar los perfiles baseline y restricted, y cómo migrar desde el ya eliminado PodSecurityPolicy con ejemplos YAML probados en clústeres reales.

Sinceramente, cuando migré mi primer clúster de PSP a PSA en 2024 me lo tomé a la ligera y rompí tres deployments del equipo de pagos en menos de cinco minutos. Por eso casi todo lo que leerás aquí incluye una fase de warn antes de cualquier enforce. La prisa, en admission control, se paga caro.

  • PodSecurityPolicy fue eliminado definitivamente en Kubernetes 1.25; Pod Security Admission es el reemplazo nativo y se configura con tres etiquetas por namespace.
  • Los perfiles baseline y restricted cubren el 80% de los controles que antes requerían PSP, sin recursos personalizados ni webhooks externos.
  • Kyverno usa YAML declarativo idéntico a manifiestos Kubernetes; Gatekeeper usa el lenguaje Rego de OPA, más potente pero con curva de aprendizaje mayor.
  • Para mutación de pods (inyectar seccomp, etiquetas, sidecars), Kyverno es la elección recomendada en 2026; Gatekeeper añadió mutación en v3.14 pero sigue siendo limitada.
  • La defensa en profundidad combina PSA en modo enforce para baseline + Kyverno/Gatekeeper para reglas específicas de la organización (firma de imágenes, registros permitidos, etiquetas obligatorias).
  • Habilita siempre los modos audit y warn antes de aplicar enforce en producción para evitar bloquear cargas legítimas.

¿Qué es Pod Security Admission y por qué reemplazó a PodSecurityPolicy?

Pod Security Admission es un admission controller integrado en el API server de Kubernetes que valida pods contra los Pod Security Standards definidos por el grupo SIG-Auth. Se habilita automáticamente desde la versión 1.25 y se configura por namespace mediante tres etiquetas: pod-security.kubernetes.io/enforce, audit y warn. Cada etiqueta acepta uno de los tres perfiles (privileged, baseline, restricted) y, opcionalmente, una versión (v1.29, latest).

La razón principal de la sustitución fue que PodSecurityPolicy (PSP) tenía un modelo de autorización confuso basado en RBAC sobre el recurso PSP en lugar del pod, lo que generaba comportamientos inesperados cuando un ServiceAccount tenía acceso a múltiples políticas. PSA simplifica el modelo: el namespace declara su perfil y el controlador aplica las reglas. Según la documentación oficial de Kubernetes, el cambio también permite combinar PSA con motores externos sin solapamiento.

PSA no permite mutación ni reglas personalizadas: solo valida contra los tres perfiles predefinidos. Por eso, en clústeres con requisitos avanzados (firma de imágenes con Cosign, registros permitidos, etiquetas obligatorias) se combina con Kyverno o Gatekeeper. Esta arquitectura en capas es la práctica recomendada en 2026 y reemplaza el modelo monolítico de PSP. Si te interesa el contexto general de aislamiento de contenedores, revisa nuestra guía de hardening de contenedores Docker y Podman.

Perfiles baseline, restricted y privileged explicados

Los tres perfiles de los Pod Security Standards funcionan como niveles acumulativos de restricción. Entender exactamente qué bloquea cada uno es esencial antes de etiquetar namespaces de producción, porque aplicar restricted sin preparación romperá cargas que dependan de capabilities Linux o volúmenes hostPath.

Controlprivilegedbaselinerestricted
HostPath volumesPermitidoBloqueadoBloqueado
Privileged containersPermitidoBloqueadoBloqueado
Host networking/PID/IPCPermitidoBloqueadoBloqueado
Linux capabilities añadidasCualquieraLista cortaSolo NET_BIND_SERVICE
runAsNonRootNo requeridoNo requeridoObligatorio
seccompProfileOpcionalOpcionalRuntimeDefault o Localhost
allowPrivilegeEscalationPermitidoPermitidoDebe ser false
Volúmenes permitidosTodosTodos excepto host*Lista restringida (configMap, secret, emptyDir)

El perfil baseline es el mínimo recomendado para cualquier namespace de aplicación: bloquea las escapadas más comunes (hostPath, privileged, hostNetwork) sin romper la mayoría de cargas estándar. Restricted, en cambio, aplica el principio de mínimo privilegio: requiere usuarios no-root, sistema de ficheros raíz de solo lectura cuando es posible, y un perfil seccomp explícito.

¿Y qué hacemos con las cargas legacy que aún no cumplen restricted? Mantener baseline y endurecer progresivamente con Kyverno o Gatekeeper es una estrategia perfectamente viable. Una cosa más: privileged no debe usarse en namespaces de aplicación. Se reserva para componentes del plano de control y agentes de nodo (CNI, CSI, monitoring) que legítimamente requieren acceso al host.

Cómo configurar Pod Security Admission paso a paso

La activación de PSA en un namespace se hace etiquetándolo. Empieza siempre con warn y audit antes de aplicar enforce, esto te permite ver qué pods violarían el perfil sin bloquear despliegues en marcha. La progresión típica desde un namespace sin políticas hasta uno con enforcement completo toma entre 1 y 4 semanas dependiendo del número de cargas.

# 1. Listar namespaces actuales
kubectl get namespaces

# 2. Aplicar baseline en modo audit + warn (no bloquea)
kubectl label namespace production \
  pod-security.kubernetes.io/audit=baseline \
  pod-security.kubernetes.io/warn=baseline \
  pod-security.kubernetes.io/audit-version=latest \
  pod-security.kubernetes.io/warn-version=latest

# 3. Revisar violaciones en los logs del API server o audit log
kubectl get events -n production --field-selector reason=FailedCreate

# 4. Una vez verificado, activar enforce
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/enforce-version=latest --overwrite

# 5. Para namespaces críticos (zero-trust), aplicar restricted
kubectl label namespace payments \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/enforce-version=latest --overwrite

Para excluir namespaces del sistema (kube-system, kube-public) o aplicar una política por defecto a todo el clúster, configura el AdmissionConfiguration en el API server.

# /etc/kubernetes/admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: ["kube-system", "kube-public"]

Luego inicia el kube-apiserver con --admission-control-config-file=/etc/kubernetes/admission-config.yaml. Este enfoque garantiza que cualquier namespace nuevo herede baseline por defecto, cerrando la ventana de exposición típica al crear espacios temporales para pruebas o pull requests. (Es justo el patrón que me hubiera salvado en aquella migración fallida.)

Kyverno vs Gatekeeper: comparativa práctica 2026

Ambos son admission webhooks que extienden las capacidades de PSA, pero difieren en lenguaje, ergonomía y madurez de funcionalidades. La decisión no es puramente técnica: depende del perfil del equipo de plataforma y de qué otras herramientas ya tienes en producción.

CaracterísticaKyverno (v1.13)OPA Gatekeeper (v3.18)
Lenguaje de políticasYAML declarativo nativo KubernetesRego (lenguaje de OPA)
Curva de aprendizajeBaja (si conoces Kubernetes)Media-alta (Rego es nuevo)
Mutación de recursosCompleta, maduraDisponible desde v3.14, en desarrollo
Validación de imágenes (Cosign)Integrada nativamenteVía Sigstore policy-controller separado
Generación de recursosSí (NetworkPolicy, ConfigMap por namespace)No nativa
Reportes de cumplimientoPolicyReport CRD integradoConstraint status
Comunidad y CNCFGraduated (CNCF)Graduated (CNCF)
Caso de uso idealEquipos enfocados en KubernetesOrganizaciones con OPA en otros sistemas

En 2026, la recomendación general para equipos de plataforma que solo gestionan Kubernetes es Kyverno: las políticas son YAML, no requiere aprender Rego, y tanto la mutación como la integración con Cosign están maduras.

Gatekeeper, por su parte, sigue siendo la mejor opción si tu organización ya usa OPA para autorización en gateways API, Terraform o microservicios, porque reutilizas el ecosistema Rego. Si tu pipeline ya incluye análisis estático con herramientas como Semgrep o Trivy, revisa nuestra guía de pipeline DevSecOps con GitHub Actions para alinear las políticas de admisión con los gates de CI.

Políticas Kyverno listas para producción

Instalar Kyverno es directo con Helm. Una vez desplegado, las políticas son ClusterPolicy o Policy (namespace-scope) en YAML nativo de Kubernetes. El siguiente ejemplo exige que todas las imágenes provengan de un registro corporativo y estén firmadas con Cosign.

# Instalación con Helm
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

# Política: solo imágenes del registro corporativo
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-corporate-registry
spec:
  validationFailureAction: Enforce
  background: true
  rules:
  - name: check-registry
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "Imagenes solo desde registry.corp.example.com permitidas."
      pattern:
        spec:
          containers:
          - image: "registry.corp.example.com/*"

---
# Política: verificar firma Cosign con clave pública
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-signed-images
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
  - name: verify-signature
    match:
      any:
      - resources:
          kinds: [Pod]
    verifyImages:
    - imageReferences:
      - "registry.corp.example.com/*"
      attestors:
      - entries:
        - keys:
            publicKeys: |
              -----BEGIN PUBLIC KEY-----
              MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
              -----END PUBLIC KEY-----

Para mutación, Kyverno destaca. El siguiente ejemplo inyecta automáticamente un perfil seccomp RuntimeDefault en cualquier pod que no lo defina, cerrando una brecha común de hardening sin tocar los manifiestos de las aplicaciones.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-seccomp
spec:
  rules:
  - name: inject-seccomp
    match:
      any:
      - resources:
          kinds: [Pod]
    mutate:
      patchStrategicMerge:
        spec:
          securityContext:
            seccompProfile:
              type: RuntimeDefault

Las políticas Kyverno también pueden generar recursos. Un patrón frecuente, y honestamente uno de mis favoritos, es crear automáticamente una NetworkPolicy de denegación por defecto en cada namespace nuevo, complementando el aislamiento que ya proporciona SELinux y AppArmor en los nodos host. La documentación completa de patrones está en kyverno.io/docs.

Políticas OPA Gatekeeper con Rego

Gatekeeper separa la plantilla (ConstraintTemplate, define la lógica Rego) del constraint (instancia con parámetros). Esto permite reutilizar la misma plantilla con distintos valores y mantener las políticas versionadas independientemente. La separación resulta especialmente útil cuando varias unidades de negocio necesitan la misma regla con umbrales distintos.

# Instalación
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper gatekeeper/gatekeeper -n gatekeeper-system --create-namespace

# ConstraintTemplate: prohibir capabilities peligrosas
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8spspcapabilities
spec:
  crd:
    spec:
      names:
        kind: K8sPSPCapabilities
      validation:
        openAPIV3Schema:
          type: object
          properties:
            forbiddenCapabilities:
              type: array
              items:
                type: string
  targets:
  - target: admission.k8s.gatekeeper.sh
    rego: |
      package k8spspcapabilities
      violation[{"msg": msg}] {
        container := input.review.object.spec.containers[_]
        cap := container.securityContext.capabilities.add[_]
        forbidden := input.parameters.forbiddenCapabilities
        cap == forbidden[_]
        msg := sprintf("Capability %v no permitida en contenedor %v",
                       [cap, container.name])
      }

---
# Constraint: instancia que prohibe SYS_ADMIN y NET_ADMIN
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
  name: prohibit-dangerous-caps
spec:
  match:
    kinds:
    - apiGroups: [""]
      kinds: [Pod]
    excludedNamespaces: [kube-system, gatekeeper-system]
  parameters:
    forbiddenCapabilities: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE]

La librería oficial gatekeeper-library incluye decenas de ConstraintTemplates probadas que cubren la mayoría de los controles equivalentes a PSP: límites de recursos, imágenes permitidas, etiquetas obligatorias, host paths, etc. Mi consejo: empieza por importarlas en lugar de escribir Rego desde cero. Aprenderás los patrones idiomáticos del lenguaje mientras cubres los controles fundamentales.

Cómo migrar de PodSecurityPolicy a PSA + Kyverno

La eliminación de PSP en Kubernetes 1.25 dejó a muchos clústeres dependiendo de webhooks externos no mantenidos. La migración estructurada en 2026 sigue cuatro fases:

  1. Inventario: exporta todas las PSP activas con kubectl get psp -o yaml en clústeres aún en 1.24, o recupera los manifiestos de tu control de versiones. Clasifica cada PSP según equivalencia con baseline, restricted o si requiere reglas personalizadas.
  2. Mapeo: los controles que coinciden con los Pod Security Standards (hostPath, privileged, runAsUser) se reemplazan directamente por la etiqueta PSA correspondiente. Los controles personalizados (registros permitidos, etiquetas obligatorias) se convierten en ClusterPolicy de Kyverno.
  3. Despliegue paralelo: aplica PSA en modo warn y despliega Kyverno con validationFailureAction: Audit. Durante 2 a 4 semanas, recolecta el reporte PolicyReport para identificar pods no conformes y trabaja con los equipos de aplicaciones para remediarlos.
  4. Enforcement: cambia las etiquetas PSA a enforce y Kyverno a Enforce. Mantén audit con un perfil más estricto (p. ej., enforce=baseline, audit=restricted) para ver qué cargas podrían endurecerse a continuación.

Auditoría, métricas y monitoreo de violaciones

Activar políticas sin observabilidad genera ceguera operativa. PSA emite eventos al audit log de Kubernetes con la anotación pod-security.kubernetes.io/audit-violations. Recoge esos eventos hacia tu stack de observabilidad (Loki, Elasticsearch, Wazuh) y crea alertas por violaciones repetidas, especialmente cuando provienen de ServiceAccounts que no deberían crear pods directamente.

# Filtro de audit policy para capturar violaciones PSA
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  omitStages: ["RequestReceived"]
  resources:
  - group: ""
    resources: ["pods"]
  namespaces: ["production", "payments"]

# Consulta Loki para violaciones PSA
{job="kube-audit"} |= "pod-security.kubernetes.io/audit-violations"
| json
| audit_violations != ""

Kyverno expone métricas Prometheus en /metrics: kyverno_policy_results_total, kyverno_admission_requests_total y kyverno_policy_execution_duration_seconds son las más útiles para dashboards. Gatekeeper, por su parte, expone gatekeeper_violations y gatekeeper_audit_duration_seconds. Combina estas métricas con detección runtime usando eBPF, Falco y Tetragon para correlacionar admission violations con comportamiento anómalo en ejecución.

Para auditorías de cumplimiento (PCI-DSS, SOC 2, CIS Kubernetes Benchmark), genera reportes periódicos con kyverno-cli: kyverno apply policies/ --cluster --policy-report > reporte-trimestral.yaml. Este artefacto, junto con los logs de audit, sustenta evidencia ante auditores externos sin esfuerzo manual.

Preguntas frecuentes

¿Qué reemplaza a PodSecurityPolicy en Kubernetes 2026?

Pod Security Admission (PSA), integrado en el API server desde 1.25, es el reemplazo nativo oficial. Para reglas más allá de los perfiles baseline/restricted/privileged, se complementa con Kyverno u OPA Gatekeeper como admission webhooks externos.

¿Kyverno o Gatekeeper, cuál debo elegir en 2026?

Si tu equipo se centra exclusivamente en Kubernetes y prefiere YAML declarativo, elige Kyverno: políticas más simples, mutación madura e integración Cosign nativa. Si ya usas OPA en otros sistemas (gateways API, Terraform), Gatekeeper te permite reutilizar el ecosistema Rego.

¿Pod Security Admission puede mutar pods para añadir securityContext?

No. PSA solo valida; no muta. Para inyectar campos como seccompProfile: RuntimeDefault o runAsNonRoot: true automáticamente, necesitas Kyverno (mutate rules) o Gatekeeper Mutation (v3.14+).

¿Cómo aplico el perfil restricted sin romper aplicaciones legacy?

Aplica primero warn=restricted y audit=restricted manteniendo enforce=baseline. Esto revela qué pods incumplen restricted sin bloquearlos. Trabaja con los equipos durante 2 a 4 semanas para añadir runAsNonRoot, seccompProfile y allowPrivilegeEscalation: false, luego sube enforce a restricted.

¿Es seguro excluir kube-system de Pod Security Admission?

Sí, es la práctica recomendada. Los componentes del plano de control y add-ons (CNI, CSI, kube-proxy) requieren capabilities elevadas o hostNetwork legítimamente. Excluirlos en AdmissionConfiguration evita bloqueos del sistema, pero limita la exclusión solo a namespaces administrados por operadores de plataforma.

Sobre el Autor Editorial Team

Our team of expert writers and editors.