Guía Completa de Kubernetes security best practices
Kubernetes facilita el despliegue y la operación de aplicaciones a escala, pero su flexibilidad viene acompanada de una superficie de ataque considerable. Un cluster mal configurado puede exponer secrets, permitir escalación de privilegios y abrir puertas a movimientos laterales entre servicios. La seguridad en Kubernetes no es un componente que se agrega al final: debe integrarse en cada capa, desde la construcción de imagenes hasta el runtime de los contenedores. Esta guía cubre las prácticas esenciales para proteger clusters productivos de forma sistemática.
Pod Security Standards
Los Pod Security Standards (PSS) son el mecanismo nativo de Kubernetes para controlar la postura de seguridad de los pods. Reemplazan a las antiguas PodSecurityPolicies (removidas en v1.25) y definen tres niveles:
- Privileged: Sin restricciones. Solo para workloads de sistema como CNI plugins o logging agents.
- Baseline: Previene escalaciones de privilegio conocidas. Bloquea hostNetwork, hostPID, contenedores privilegiados y capabilities peligrosas.
- Restricted: Maximo nivel de seguridad. Requiere que los contenedores corran como non-root, con un seccomp profile y sin capabilities adicionales.
Aplicar PSS con Pod Security Admission
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Al etiquetar el namespace, Kubernetes rechaza automáticamente cualquier pod que no cumpla con el nivel restricted. Los modos audit y warn permiten detectar violaciones sin bloquear, útil durante la migración.
RBAC: control de acceso granular
Role-Based Access Control es la primera linea de defensa para controlar quien puede hacer que en el cluster. Errores comunes incluyen otorgar cluster-admin a cuentas de servicio o dejar bindings demasiado permisivos.
Principio de mínimo privilegio
Crea roles específicos por función:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: readonly-pods
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "services", "endpoints"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-readonly
namespace: production
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: readonly-pods
apiGroup: rbac.authorization.k8s.io
Auditar permisos existentes
Revisa regularmente los permisos asignados. Usa kubectl auth can-i --list --as=system:serviceaccount:default:mi-sa para verificar que permisos tiene una cuenta de servicio específica. Elimina ClusterRoleBindings innecesarios y evita usar wildcards (*) en las reglas.
Network Policies
Sin network policies, cualquier pod puede comunicarse con cualquier otro pod en el cluster. Esto es inaceptable en producción.
Estrategia default-deny
Comienza bloqueando todo el tráfico y luego abre solo lo necesario:
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-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-egress-db
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to: # Permitir DNS
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
No olvides permitir tráfico DNS en las políticas de egress; de lo contrario, la resolución de nombres dentro del cluster dejara de funcionar.
Gestión de secrets
Los secrets de Kubernetes se almacenan en etcd codificados en base64, pero no cifrados por defecto. Esto no es seguro.
Cifrado en reposo
Habilita encryption at rest para etcd en clusters autogestionados:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <clave-base64-de-32-bytes>
- identity: {}
Soluciones externas recomendadas
Para producción, integra un gestor de secrets externo:
- HashiCorp Vault: Inyecta secrets via sidecar (Vault Agent) o CSI driver. Soporta rotación automática y audit logging.
- AWS Secrets Manager / Parameter Store: Usa el CSI Secrets Store Driver con el provider de AWS para montar secrets como volumenes.
- Sealed Secrets (Bitnami): Permite cifrar secrets en el repositorio Git. Solo el controlador en el cluster puede descifrarlos.
La rotación periodica de credenciales es obligatoria. Automatizala para que no dependa de intervención manual.
Escaneo de imagenes y seguridad en el supply chain
Escaneo de vulnerabilidades
Integra escaneo de imagenes en el pipeline de CI/CD y como admission control en el cluster:
# Escanear imagen con Trivy antes del push al registry
trivy image --severity HIGH,CRITICAL --exit-code 1 mi-app:v2.1.0
# Escanear el Dockerfile en busca de misconfigurations
trivy config --severity HIGH,CRITICAL ./Dockerfile
Políticas de admision para imagenes
Usa un admission controller para bloquear imagenes no escaneadas o con vulnerabilidades criticas:
# Ejemplo con Kyverno
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "mi-registry.com/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Prácticas para imagenes seguras
- Usa imagenes base minimas: distroless, alpine o scratch.
- Nunca uses la tag
latest. Fija versiones especificas con digest SHA. - Ejecuta contenedores como usuario non-root.
- No incluyas herramientas de debug (curl, wget, shells) en imagenes de producción.
Seguridad en runtime con Falco
Falco es una herramienta open source de la CNCF que monitorea el comportamiento de los contenedores en tiempo real usando syscalls del kernel.
Que detecta Falco
- Ejecución de shells dentro de contenedores.
- Lectura de archivos sensibles (/etc/shadow, /etc/passwd).
- Conexiones de red inesperadas.
- Modificación de binarios del sistema.
- Escalación de privilegios.
Regla personalizada de ejemplo
- rule: Shell in Container
desc: Detecta ejecucion de shell interactivo en contenedores
condition: >
spawned_process and
container and
proc.name in (bash, sh, zsh) and
not proc.pname in (cron, supervisord)
output: >
Shell ejecutado en contenedor
(user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname
cmdline=%proc.cmdline)
priority: WARNING
tags: [container, shell]
Integra Falco con Alertmanager o un SIEM para recibir notificaciones inmediatas ante comportamiento anomalo.
SecurityContext en pods
Configura el security context para endurecer cada pod:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: mi-app:v2.1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Puntos clave: ejecutar como non-root, filesystem de solo lectura (montando /tmp como emptyDir si la aplicación necesita escribir), eliminar todas las capabilities de Linux y habilitar seccomp.
CIS Kubernetes Benchmark
El Center for Internet Security pública un benchmark específico para Kubernetes que cubre la configuración segura de todos los componentes del cluster. Usa herramientas automatizadas para evaluar el cumplimiento:
# Ejecutar kube-bench para evaluar conformidad CIS
kube-bench run --targets master,node,policies
# Verificar un nodo especifico
kube-bench run --targets node
Los hallazgos se clasifican en PASS, FAIL y WARN. Prioriza los FAIL críticos: permisos de archivos de configuración, cifrado de etcd, configuración de audit logging y políticas de autenticación del API server.
Conclusion
La seguridad en Kubernetes es un proceso continuo que abarca multiples capas: desde los Pod Security Standards y RBAC hasta network policies, gestión de secrets, escaneo de imagenes y monitoreo de runtime. No existe una sola herramienta que resuelva todo; se necesita un enfoque de defensa en profundidad donde cada capa complementa a las demas. La recomendación práctica es implementar estas medidas de forma incremental, comenzando por RBAC y PSS, luego network policies y secrets management, y finalmente runtime security con Falco y audit logging.