Implementing Kubernetes Network Policies for Strict Pod-to-Pod Isolation
Enforce zero-trust pod communication within your Kubernetes cluster using declarative NetworkPolicy rules to block unauthorized ingress and egress.
Netbay Infrastructure Team
Netbay Engineering
On this page
By default, the Kubernetes network model is completely open: every pod can communicate with every other pod across all namespaces without restriction. In a multi-service or multi-tenant deployment, this lack of boundary means that a vulnerability in a public-facing web tier grants immediate network access to private database instances and internal telemetry endpoints.
Kubernetes NetworkPolicies provide declarative firewalling at the pod level using label selectors. Enforcing a default-deny posture and selectively allowlisting necessary ingress and egress flows establishes a robust zero-trust security perimeter.
Network policies are enforced by the cluster's Container Network Interface (CNI) provider, such as Calico, Cilium, or Kube-Router. When you apply a NetworkPolicy manifest, the CNI controller translates the high-level podSelector stanzas into underlying Linux kernel packet filtering rules (using iptables, ipset, or modern eBPF maps). Traffic that does not match an explicit allow rule is dropped at the virtual network interface level before reaching the container's socket layer.
Enforcing a Default-Deny Security Baseline
The foundational principle of zero-trust networking is default-deny. Applying this policy instructs the CNI plugin to drop all ingress and egress traffic for pods in the target namespace unless explicitly authorized:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
egress:
# Always allow DNS resolution to CoreDNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53A critical operational detail when establishing a default-deny egress policy is explicitly allowing DNS traffic to kube-dns or CoreDNS on port 53. If this rule is omitted, pods will be unable to resolve internal service names or external APIs, triggering silent connection timeouts throughout the application stack.
Creating Granular Ingress Allow Policies for Databases
Next, create targeted allow rules. The following policy allows incoming connections on port 5432 to PostgreSQL pods only when originating from pods labeled app: api-backend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-backend
ports:
- protocol: TCP
port: 5432Verifying Policy Enforcement and Dropped Packets
Validate that non-authorized pods are blocked from connecting to the database:
# Attempt connection from an authorized API pod (succeeds)
kubectl exec -it $(kubectl get pod -l app=api-backend -n production -o jsonpath='{.items[0].metadata.name}') -n production -- nc -zv postgres 5432
# Attempt connection from an unauthorized frontend pod (hangs and times out)
kubectl exec -it $(kubectl get pod -l app=frontend -n production -o jsonpath='{.items[0].metadata.name}') -n production -- nc -zv -w 3 postgres 5432When the unauthorized frontend pod attempts to connect to port 5432, the CNI kernel filter drops the initial TCP SYN packet silently. The netcat command times out after 3 seconds, confirming that the database port is completely invisible to the frontend tier.
Implementing declarative NetworkPolicies turns the Kubernetes flat network into an isolated multi-tier fortress.
You can spin up an Ubuntu 24.04 instance on Netbay in under 60 seconds with Intel Xeon Platinum compute and high-speed SSD storage in Lucknow — netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance