Kubernetes Network Policy: Microsegmentation Implementation Guide

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
A newly created Kubernetes namespace has no network restrictions. Every pod can reach every other pod, every service in every namespace, and every external IP address. When a container in a compromised pod attempts lateral movement, nothing in the default Kubernetes network model prevents it from reaching the database, the secrets store, or the Kubernetes API server. NetworkPolicy is Kubernetes's built-in mechanism for microsegmentation, but it requires explicit implementation, a CNI that actually enforces it, and ongoing maintenance as your application topology changes. This guide gives you the exact manifests, verification tests, and Cilium extensions you need to implement real network segmentation.
Step 1: Verify Your CNI Enforces NetworkPolicy
Before writing any policies, confirm your CNI actually enforces them. This is the most commonly skipped step.
Identify your CNI plugin
kubectl get pods -n kube-system | grep -E 'calico|cilium|weave|flannel|antrea|canal'. If you see flannel with no other CNI: NetworkPolicy is not enforced, you need to install Calico or Cilium. If you see calico-node or cilium: you have enforcement capability. EKS defaults to AWS VPC CNI + Calico (optional); GKE defaults to Calico; AKS supports Azure CNI or Calico.
Test enforcement with a canary policy
Deploy two pods (a client and a server). Verify connectivity without any policy: kubectl exec client -- curl -s server-service. Apply a NetworkPolicy that denies all ingress to the server pod. Re-test: kubectl exec client -- curl -s --connect-timeout 3 server-service. If the request succeeds despite the deny policy, your CNI is not enforcing NetworkPolicy, stop here and fix the CNI before writing any more policies.
Install Cilium for Layer 7 enforcement
If you need Layer 7 (HTTP/gRPC/Kafka) policies or eBPF-based observability: cilium install --version 1.15.0. Cilium replaces or wraps your existing CNI. For EKS: use the AWS-specific Cilium installation that co-exists with the VPC CNI for IPAM while using Cilium for policy enforcement. Verify: cilium status --wait.
Step 2: Default-Deny Baseline
Apply a default-deny policy to each namespace before allowing specific traffic. This inverts the Kubernetes default (allow all) into a zero-trust posture.
Default-deny ingress and egress
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress Apply to every namespace: for ns in $(kubectl get ns -o name | cut -d/ -f2 | grep -v kube-system); do kubectl apply -f default-deny.yaml -n $ns; done. Note: this will break all pod-to-pod communication in the namespace, apply allow rules first in a test environment.
Allow DNS egress for all pods
After applying default-deny, pods cannot resolve DNS. Add this policy to every namespace alongside default-deny: spec: podSelector: {} policyTypes: [Egress] egress: [{ports: [{protocol: UDP, port: 53}, {protocol: TCP, port: 53}], to: [{namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: kube-system}}}]}]. Without DNS, nearly all services break immediately, this is the first allow rule to apply.
Allow Kubernetes API server egress
Pods that communicate with the Kubernetes API server (operators, controllers, admission webhooks) need egress to the API server IP. Get it: kubectl get endpoints kubernetes -n default. Add an egress rule for that IP on port 443 for pods that need API access. Do NOT add this for application pods that have no reason to talk to the API server.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Step 3: Least-Privilege Allow Rules for Common Patterns
These policy templates cover the most common application connectivity patterns. Adapt namespace and pod selectors to your labels.
Frontend to backend service
Allow frontend pods to reach the backend service on port 8080: ingress rule on the backend NetworkPolicy with podSelector matchLabels: app: frontend and port 8080. Deny all other ingress to the backend pod. This means a compromised pod with a different label cannot reach the backend, even within the same namespace.
Backend to database
Allow backend pods to reach the database (port 5432 for PostgreSQL, 3306 for MySQL): egress rule on the backend NetworkPolicy allowing traffic to namespaceSelector: database-namespace on port 5432. Ingress rule on the database NetworkPolicy allowing from podSelector: app: backend on port 5432. Block all other ingress to the database pod, particularly from the frontend and ingress namespaces.
Namespace-level isolation
To prevent any cross-namespace traffic by default: apply a NetworkPolicy to each namespace that denies ingress from other namespaces. Then explicitly allow specific cross-namespace flows as needed. This contains a namespace compromise to that namespace rather than allowing it to reach adjacent services. namespaceSelector with no matchLabels selects all namespaces, use matchLabels to scope cross-namespace allows precisely.
Allow monitoring scraping
Prometheus needs to scrape metrics endpoints in other namespaces. Create a NetworkPolicy in each application namespace allowing ingress from the monitoring namespace on the metrics port: ingress from namespaceSelector: matchLabels: kubernetes.io/metadata.name: monitoring, port: 9090 (or your metrics port). This is a common omission that breaks Prometheus after default-deny is applied.
Step 4: Cilium Layer 7 Policies
Standard NetworkPolicy can only restrict at the port level, it cannot distinguish GET /healthz from DELETE /admin. Cilium CiliumNetworkPolicy adds this capability.
Subscribe to unlock Remediation & Mitigation steps
Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.
Step 5: Verify Segmentation Is Actually Working
Writing policies is not enough, you must verify they enforce correctly. These tests confirm your segmentation is real.
Netshoot-based connectivity tests
Deploy a netshoot pod (nicolaka/netshoot) and test connectivity between namespaces: kubectl run netshoot --image=nicolaka/netshoot -n {SOURCE_NS} --rm -it -- curl -sv --connect-timeout 3 {TARGET_SERVICE}.{TARGET_NS}.svc.cluster.local:{PORT}. Document expected results (block vs allow) for every test case. Run this test suite after every NetworkPolicy change.
Automate with Sonobuoy or Network Policy validator
The network-policy-validator tool (github.com/UK-IPOP/network-policy-validator) tests NetworkPolicy rules automatically. Add it to your CI pipeline: after any NetworkPolicy change, run the validator suite that tests all defined connectivity expectations. A failed test means a policy change introduced unintended blocking or allowed traffic that should be blocked.
Confirm default-deny is enforced in new namespaces
When a new namespace is created (by a developer, a Helm chart, or an operator), there is a window before the default-deny policy is applied. Automate this: use a Kyverno ClusterPolicy or an operator that watches for namespace creation events and automatically applies the default-deny NetworkPolicy immediately. This eliminates the open window between namespace creation and policy application.
The bottom line
The default Kubernetes network model is trust-all, every pod can reach every other pod. That is not a zero-trust posture. Apply a default-deny policy to every production namespace, allow only the explicit flows your applications need, verify enforcement with connectivity tests, and automate policy application to new namespaces. If you need HTTP-level control, deploy Cilium. A compromised pod in a properly segmented cluster is contained; in a flat-network cluster, it is a foothold into everything.
Frequently asked questions
Does creating a NetworkPolicy automatically enforce it?
No. NetworkPolicy enforcement depends entirely on your CNI (Container Network Interface) plugin. If your cluster uses a CNI that does not support NetworkPolicy enforcement, like Flannel in its default configuration, NetworkPolicy objects are accepted by the API server but have no effect. Calico, Cilium, Weave Net, and Antrea all support NetworkPolicy enforcement. Verify by creating a test NetworkPolicy and confirming it actually blocks traffic.
What is the difference between Kubernetes NetworkPolicy and Cilium NetworkPolicy?
Standard Kubernetes NetworkPolicy operates at Layer 3/4, it can restrict traffic by IP address, CIDR range, namespace selector, and pod selector, using TCP/UDP port numbers. Cilium's CiliumNetworkPolicy extends this to Layer 7, it can restrict specific HTTP methods, URL paths, Kafka topics, gRPC methods, and DNS hostnames. For zero-trust application segmentation where you want to allow GET /api/health but deny POST /api/admin, you need Layer 7 policy which requires Cilium or a similar eBPF-based CNI.
Will a default-deny NetworkPolicy break my existing workloads?
Yes, in a flat-network cluster, applying a default-deny policy will immediately break any pod-to-pod communication not explicitly allowed. The safe approach: first apply the default-deny policy in a new test namespace, verify everything required is explicitly allowed, then roll out to production namespaces one by one with adequate testing between each. Do not apply default-deny cluster-wide simultaneously, it will cause an outage.
How do I allow pod access to external internet while restricting internal traffic?
Use a NetworkPolicy with egress rules that permit traffic to specific external CIDRs or to 0.0.0.0/0 (all external) while denying internal cluster CIDR ranges. Example: allow egress to 0.0.0.0/0 except 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. This lets pods make outbound internet calls while blocking lateral movement to internal services. Combine with DNS policy to restrict which hostnames can be resolved.
What is a Kubernetes NetworkPolicy and does it apply to existing connections?
A Kubernetes NetworkPolicy is an object that specifies which pods can send and receive network traffic, based on pod labels, namespace selectors, and IP CIDR ranges. NetworkPolicies are stateful: they apply to new connections only -- existing connections established before the policy was created are not terminated. This means that if a pod has an active connection to another service when a default-deny NetworkPolicy is applied, that connection continues until it is closed normally. To terminate existing connections, you would need to restart the pods or use a CNI plugin that supports connection tracking reset (most do not provide this via NetworkPolicy). This is relevant for incident response: applying a deny NetworkPolicy to isolate a compromised pod will prevent new connections but will not immediately cut active C2 channels.
How do I write a NetworkPolicy that allows egress to external APIs while blocking access to the Kubernetes API server and cluster internal services?
Use a combined egress NetworkPolicy that explicitly allows external HTTPS traffic while blocking the RFC 1918 ranges and the Kubernetes API server IP. The policy structure: allow egress on port 443 to ipBlock 0.0.0.0/0 with except blocks for 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and your cluster API server CIDR. Also add a separate allow rule for UDP port 53 to your CoreDNS pod selector (needed for DNS resolution). Without the except blocks, the allow-all-443 rule also permits access to internal services that happen to run on port 443. If you use Cilium, replace the IP-based exception with a toFQDNs rule that explicitly allows only the external API hostnames your application needs -- this is more maintainable and provides stronger control than CIDR-based exceptions as your cluster network topology changes.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
