Network Policies de Kubernetes: Segmentando el Tráfico del Clúster
Cómo las network policies de Kubernetes segmentan el tráfico del clúster con default-deny, podSelector y egress para proteger la comunicación entre pods.
Levanta un clúster de Kubernetes nuevo, despliega un puñado de servicios y algo sorprendente ya es cierto: cada pod puede hablar con cualquier otro pod. Tu servicio de pagos alcanza al sidecar de logging, un pod de marketing comprometido puede abrir una conexión con tu base de datos, y el tráfico cruza los límites de namespace sin pedir permiso. Este es el comportamiento predeterminado plano y permisivo de las network policies de Kubernetes y de la red del clúster, y es una de las brechas más comunes que vemos cuando los equipos empiezan a llevar workloads a producción. Esta guía detallada forma parte de nuestra guía de seguridad de Kubernetes y se centra en una sola palanca: usar network policies para segmentar el tráfico del clúster de modo que los pods solo alcancen aquello que realmente necesitan.
El problema: la red de Kubernetes es plana y permite todo de forma predeterminada
El modelo de red de Kubernetes es deliberadamente simple. Cada pod recibe su propia dirección IP, y cada pod alcanza directamente la IP de cualquier otro pod, sin NAT de por medio. Esa simplicidad es excelente para la velocidad de desarrollo y el descubrimiento de servicios, pero significa que la red, por sí sola, no ofrece aislamiento. No hay un firewall implícito entre namespaces, ninguna barrera entre la capa de frontend y la capa de datos, y nada que impida que un workload realice conexiones salientes hacia donde quiera.
La consecuencia de seguridad aparece durante los incidentes. Si un atacante logra ejecución de código en un solo pod, esa red plana se convierte en su patio de juegos. El movimiento lateral, el acceso a endpoints administrativos internos y la exfiltración de datos hacia un host externo están todos trivialmente disponibles, porque la red nunca dice que no. El principio de mínimo privilegio, que aplicamos con cuidado a las identidades mediante el RBAC de Kubernetes y a los workloads mediante la pod security, necesita un equivalente en la capa de red. Ese equivalente es la NetworkPolicy.
Qué es una NetworkPolicy (y por qué necesita una CNI que la aplique)
Una NetworkPolicy es un recurso de Kubernetes con alcance de namespace que describe qué conexiones se permiten hacia y desde un conjunto de pods. La escribes de forma declarativa, igual que escribes un Deployment o un Service, y vive junto a los workloads que protege.
Hay una salvedad crucial. El servidor de API de Kubernetes aceptará y almacenará de buena gana una NetworkPolicy, pero el servidor de API no la aplica. La aplicación es tarea de tu plugin de Container Network Interface (CNI). Si la CNI instalada en tu clúster no implementa network policy, tus reglas cuidadosamente escritas quedan inertes: existen como objetos, pero no cambian nada del tráfico real. Varias CNIs ampliamente usadas aplican políticas y varias no, así que, antes de confiar en la segmentación, confirma que la capa de red de tu clúster realmente aplique los recursos de NetworkPolicy. Una forma rápida de ganar confianza es aplicar una regla de denegación y verificar que el tráfico bloqueado realmente se detenga.
Los bloques de construcción: podSelector, ingress, egress y peers
Toda NetworkPolicy tiene una anatomía pequeña y consistente.
podSelector elige a qué pods del namespace se aplica la política, según sus labels. Un podSelector: {} vacío selecciona todos los pods del namespace, que es exactamente lo que quieres para una base que abarque todo el namespace.
policyTypes declara si la política gobierna Ingress (conexiones entrantes), Egress (conexiones salientes) o ambas. Esto importa: una política que enumera Ingress pero ninguna regla de ingress niega todo el tráfico entrante hacia los pods seleccionados, dejando el egress intacto.
Peers describen el otro extremo de una conexión permitida. Tienes tres maneras de nombrar un peer:
podSelectorcoincide con pods por label dentro del mismo namespace.namespaceSelectorcoincide con namespaces enteros por sus labels, que es como permites flujos entre namespaces.ipBlockcoincide con rangos CIDR, útil para nodos en el clúster o sistemas externos, con una listaexceptopcional para recortar rangos.
ports restringen un flujo permitido a puertos y protocolos específicos (TCP, UDP, SCTP), de modo que puedas permitir conexiones al puerto 5432 sin abrir todo lo demás.
Un detalle sutil pero importante: dentro de una sola regla, varias entradas de peer se combinan con OR, pero un namespaceSelector y un podSelector escritos dentro de la misma entrada de peer se combinan con AND, lo que significa "pods con este label, pero solo en namespaces con aquel label". Acertar esa distinción es la diferencia entre una regla estricta y una accidentalmente abierta.
El patrón default-deny
El hábito más valioso con las network policies es empezar por la denegación y abrir de forma deliberada, en lugar de empezar abierto e intentar cerrar las brechas. Este es el patrón default-deny, y es la base de la microsegmentación práctica.
Empiezas negando todo el tráfico en un namespace y luego superpones políticas explícitas de permiso. Como las network policies son aditivas, una regla de permiso en cualquier parte del namespace concede ese flujo; no existe una regla de "denegación" que anule un permiso. Ese modelo aditivo es la razón por la cual la denegación de base se expresa como una política sin reglas de permiso, en lugar de un bloqueo explícito.
Aquí tienes una política que niega todo el ingress y todo el egress para cada pod de un namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payments
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Con esto en su lugar, nada entra ni sale de ningún pod del namespace payments hasta que digas lo contrario. Esto se siente agresivo, y lo es, pero convierte cada flujo permitido en una decisión consciente que puedes revisar.
Ejemplos prácticos
Permitir ingress solo desde una app específica. Supón que un pod api debe aceptar conexiones solo desde los pods frontend, y únicamente en el puerto 8080. Una vez que el default-deny está en su lugar, agregas:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: payments
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Ahora los pods api aceptan tráfico del frontend en el 8080 y nada más, mientras que el default-deny sigue bloqueando cualquier otro origen.
Restringir el egress, incluido el DNS. El control de egress es donde los equipos tropiezan con más frecuencia, porque casi todo pod necesita DNS para resolver nombres de servicio, y el DNS corre en el namespace kube-system. Si aplicas una denegación de egress sin permitir el DNS, tus pods se rompen de maneras confusas. Esta política permite que los pods api resuelvan DNS y alcancen una base de datos en el puerto 5432, y nada más:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: payments
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
La regla de DNS es la línea nada glamorosa que impide que las políticas de egress se conviertan en una caída del servicio.
Aislamiento de namespaces y multitenancy
Los namespaces son un límite organizativo en Kubernetes, pero, de forma predeterminada, no son un límite de red. Si alojas varios equipos, entornos o tenants en un clúster, las network policies son la manera de hacer que los namespaces se comporten como segmentos aislados.
Un patrón común es dar a cada namespace de tenant una base default-deny y, luego, permitir ingress solo desde pods dentro del mismo namespace usando un podSelector vacío dentro del from del ingress. El tráfico entre tenants pasa entonces a ser imposible, a menos que una política específica, apoyada en un namespaceSelector, lo permita explícitamente. Etiquetar los namespaces de forma consistente (muchos clústeres exponen el label incorporado kubernetes.io/metadata.name) hace que estas reglas entre namespaces sean legibles y auditables. El resultado es microsegmentación de verdad: cada tenant vive en su propia isla de red, con los puentes entre islas registrados como política explícita y revisable.
Limitaciones a tener en cuenta
Las network policies son potentes, pero no son una historia completa de seguridad de red, y conviene ser honesto sobre sus límites.
- Solo L3/L4. Las network policies estándar coinciden con direcciones IP y puertos. No pueden, por sí solas, permitir "GET /health pero no POST /admin", coincidir con hostnames o SNI, ni inspeccionar cabeceras HTTP. El filtrado en la capa 7 requiere herramientas adicionales, como un service mesh o una CNI que ofrezca extensiones conscientes de L7.
- Alcance de namespace. Una NetworkPolicy solo selecciona pods de su propio namespace. No existe un objeto de política a nivel de todo el clúster incorporado en el Kubernetes central, así que proteger un clúster grande implica gestionar políticas en muchos namespaces, lo cual es un fuerte argumento a favor de las plantillas y la automatización.
- Dependiente de la CNI. Como se explicó arriba, la aplicación vive en la CNI. El comportamiento ante casos límite y cualquier característica de L7 o a nivel de todo el clúster puede variar entre plugins, así que valida contra la CNI que de verdad ejecutas.
Ninguna de estas es razón para saltarse las network policies. Son razones para tratar la segmentación como una capa dentro de un enfoque de defensa en profundidad que también incluya RBAC, pod security y el escaneo de imágenes y manifests.
Probando y validando tus políticas
Una network policy que no has probado es una hipótesis, no un control. Como el efecto de una política es "tráfico que solía funcionar ahora falla", la única manera de estar seguro es ejercitar las rutas.
Empieza confirmando el caso negativo: desde un pod que debería estar bloqueado, intenta alcanzar el servicio protegido y verifica que la conexión dé timeout o sea rechazada. Un pod de depuración liviano que ejecute curl, wget o nc contra el objetivo suele ser suficiente. Luego, confirma el caso positivo: desde un pod que debería estar permitido, verifica que la conexión tenga éxito. Haz esto tanto para ingress como para egress, y recuerda probar explícitamente la resolución de DNS, ya que una regla de egress de DNS rota es el fallo silencioso más común.
Más allá de las comprobaciones manuales, mantén una pequeña biblioteca de pruebas de conectividad que puedas ejecutar tras cualquier cambio de política, y trata un éxito inesperado (tráfico que debería denegarse pero no lo hace) con la misma seriedad que un fallo inesperado. Como las políticas son aditivas, una sola regla de permiso demasiado amplia en otra parte del namespace puede deshacer silenciosamente un aislamiento que creías tener.
Shift left: revisa las network policies como código
Las network policies son YAML que vive en tus repositorios, lo que significa que pueden revisarse, probarse y bloquearse antes de que siquiera toquen un clúster. Aquí es donde la segmentación deja de ser un combate a incendios del "día dos" y pasa a formar parte de cómo construyes.
Trata cada cambio de política como cualquier otro cambio de código. Exige revisión en los pull requests que modifiquen o agreguen manifests de NetworkPolicy, y mantente especialmente atento a cambios que amplíen un selector, agreguen un ipBlock con un CIDR amplio o eliminen un default-deny. En CI, escanea tus manifests de Kubernetes y tu infraestructura como código, de modo que un namespace que se envíe sin un default-deny, o una política que abra el egress al mundo, se marque automáticamente en lugar de descubrirse durante un incidente. Detectar una política ausente o demasiado permisiva en un pull request es dramáticamente más barato que detectarla en producción, y mantiene la conversación de seguridad cerca de los desarrolladores que son dueños del workload.
Cómo ayuda Rainforest
Rainforest lleva la revisión de network policies al mismo flujo shift-left que tu equipo ya usa para el código. Nuestro escaneo de infraestructura como código y manifests analiza los manifests de Kubernetes y la IaC en tus pipelines, de modo que las bases default-deny ausentes, los selectors demasiado amplios y las reglas de egress riesgosas surjan como hallazgos en el pull request, con el contexto que los desarrolladores necesitan para corregirlos. Como parte de la plataforma más amplia de testing de seguridad de aplicaciones, conecta esas comprobaciones de configuración del clúster con el resto de tu programa de AppSec, dándote un único lugar para ver y priorizar el riesgo en el código y la infraestructura.
Si quieres ver cómo la revisión de policy-as-code encaja en tu flujo de seguridad de Kubernetes, agenda una demostración y la recorreremos con tus propios manifests.
Preguntas frecuentes
¿Qué es una network policy de Kubernetes?
Una network policy de Kubernetes es un recurso con alcance de namespace que define qué conexiones de red se permiten hacia y desde un grupo de pods, seleccionados por sus labels. Controla el tráfico a nivel de IP y puerto (L3/L4) y la aplica el plugin de CNI de tu clúster, y no el propio servidor de API de Kubernetes.
¿Kubernetes niega el tráfico de forma predeterminada?
No. De forma predeterminada, la red de Kubernetes es plana y permite todo: cada pod puede comunicarse con cualquier otro pod, incluso entre namespaces, sin restricciones. Solo obtienes el comportamiento de denegación una vez que aplicas network policies que seleccionen esos pods.
¿Qué es una network policy default-deny?
Una network policy default-deny selecciona todos los pods de un namespace (usando un podSelector vacío) y declara los tipos de política de ingress o egress sin ninguna regla de permiso, lo que bloquea todo el tráfico correspondiente. Luego agregas políticas explícitas de permiso por encima para los flujos específicos que cada workload necesita, ya que las políticas son aditivas.
¿Las network policies necesitan una CNI especial?
Sí. El servidor de API de Kubernetes almacena los objetos de NetworkPolicy, pero no los aplica. La aplicación la maneja el plugin de CNI, y no toda CNI implementa network policy. Confirma que tu CNI admita y aplique las políticas, idealmente aplicando una regla de denegación y verificando que el tráfico realmente se detenga.
¿Las network policies pueden filtrar por hostname o L7?
No por sí solas. Las network policies estándar de Kubernetes operan en L3/L4, coincidiendo con direcciones IP, rangos CIDR y puertos. No pueden coincidir con hostnames, SNI, métodos HTTP ni rutas. El filtrado en la capa 7 requiere herramientas adicionales, como un service mesh o una CNI con extensiones conscientes de L7.

Escrito por
Bruno Baldo
CMO
Um pouco de marketing e um pouco de curiosidade e temos a receita pra criar um apaixonado por cyber!

Seguridad en Kubernetes: la guía completa
Guía completa de seguridad en Kubernetes: el modelo de las 4C, superficie de ataque, RBAC, pods, network policies, secrets, cadena de suministro y shift-left.

Kubernetes Pod Security: Standards, Admission y securityContext
Una guía práctica de Kubernetes Pod Security: los Pod Security Standards, el Pod Security Admission y los ajustes de securityContext que mantienen protegidos los pods.

RBAC en Kubernetes: el control de acceso basado en roles explicado
RBAC en Kubernetes explicado: cómo funcionan Roles, bindings y ServiceAccounts, cómo se evalúa el acceso y buenas prácticas de mínimo privilegio.
