Kubernetes Network Policies: Locking Down Pod-to-Pod Communication

Implement Kubernetes network policies from zero-trust to production. Covers default-deny, namespace isolation, egress control, debugging tools, and the common misconfigurations that leave clusters wide open.

Network policies in Kubernetes define how groups of pods are allowed to communicate with each other and with external endpoints. This capability becomes critical when you need to enforce strict network segmentation between application components, limit access to sensitive services, or implement zero-trust security models within your cluster.

Allow Traffic from Specific Pods

To permit traffic from one pod to another, create a policy that matches the source pod labels and allows communication to target pods:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-pod-to-pod
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend

This configuration allows pods labeled app=frontend to communicate with pods labeled app=backend. The policy applies only to pods matching the podSelector in the spec.

Restrict Ingress to Specific Ports

Limit ingress traffic to specific ports by specifying port numbers in the policy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-ingress-ports
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api
    ports:
    - protocol: TCP
      port: 5432

Only TCP traffic on port 5432 is allowed from pods labeled app=api to pods labeled app=database.

Block All Ingress Traffic by Default

To enforce a default-deny policy, create a network policy that blocks all ingress traffic unless explicitly allowed:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress

This policy applies to all pods in the namespace because podSelector is empty. It blocks all incoming connections to those pods, regardless of labels.

Allow Egress Traffic to Specific Services

Control outbound communication by defining egress rules that allow traffic to specific services:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-to-dns
spec:
  podSelector:
    matchLabels:
      app: app-pod
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53

This allows pods labeled app=app-pod to send UDP traffic to DNS services in the kube-system namespace.

Use Network Policy with Namespaces

Create policies that span multiple namespaces by using namespace selectors:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-namespace-to-namespace
spec:
  podSelector:
    matchLabels:
      app: service-a
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: frontend-ns

This policy allows pods labeled app=service-a to receive traffic from pods in namespaces labeled name=frontend-ns.

Deny Traffic Based on Labels

Block traffic from pods with certain labels by specifying a not operator:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-untrusted-pods
spec:
  podSelector:
    matchLabels:
      app: sensitive-service
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: untrusted
        matchExpressions:
        - key: role
          operator: NotIn
          values: [trusted]

This policy blocks traffic from pods labeled role=untrusted unless they also have a label that explicitly marks them as trusted.

Combine Multiple Network Policy Types

Use multiple types in a single policy to control both ingress and egress traffic:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: full-traffic-control
spec:
  podSelector:
    matchLabels:
      app: web-app
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: loadbalancer
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database

This policy controls both incoming and outgoing traffic for pods labeled app=web-app.

Apply Policy with Specific IP Ranges

Allow traffic from specific IP ranges using CIDR notation:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ip-range
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 10.0.0.0/8

This allows only pods in the 10.0.0.0/8 subnet to communicate with pods labeled app=api-server.

Combine Pod Selectors and Namespace Selectors

Use both pod selectors and namespace selectors in a single rule:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: cross-namespace-pod-selector
spec:
  podSelector:
    matchLabels:
      app: logging
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring-ns
      podSelector:
        matchLabels:
          app: collector

This allows pods labeled app=collector in the monitoring-ns namespace to communicate with pods labeled app=logging.

Network Policy Validation and Troubleshooting

Check if a network policy is applied by describing it:

kubectl describe networkpolicy allow-pod-to-pod

If no policy is defined, the command returns an error: Error from server (NotFound): networkpolicies.networking.k8s.io "allow-pod-to-pod" not found.

Use kubectl get networkpolicies to list all policies in a namespace:

kubectl get networkpolicies

The output shows policy names, creation timestamps, and their associated pod selectors.

Common Failure Modes

Network policies silently fail when applied without proper network plugin support. The networking.k8s.io/v1 API version requires a compatible CNI plugin (such as Calico or Cilium) to enforce rules. Without such a plugin, policies are stored but ignored.

A common mistake is applying a policy with an incorrect label selector that doesn't match any pods. This creates a policy without effect:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: bad-selector
spec:
  podSelector:
    matchLabels:
      app: nonexistent-app
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend

This policy creates a rule that affects no pods, as there are no pods labeled app=nonexistent-app.

Another silent failure occurs when the policy is applied to a namespace but no pods in that namespace match the selector. The policy itself becomes inactive.

Network Policy Enforcement Limitations

Network policies only affect traffic between pods. They do not control access to services or external endpoints. To block external access, you must combine network policies with ingress controllers or cloud load balancer rules.

Policies also do not apply to traffic from host network pods or to pods using host networking mode. Traffic from these pods bypasses network policy enforcement entirely.

A misconfigured policy that allows traffic from all pods (podSelector: {}) can create unexpected access patterns. This is often unintentional and leads to overly permissive networks.

Network Policy with Pod Disruption

When a pod is deleted, its network policy enforcement ceases immediately. A new pod with the same labels will inherit the network policy rules only after the policy controller has processed the update.

Network policies are applied at the pod level. If a pod has multiple containers, each container must be considered for communication restrictions. A policy that allows traffic to a specific pod does not automatically allow all containers within that pod to communicate with each other.

Policy Precedence and Conflict Resolution

Multiple network policies can coexist in a namespace, but conflicts are resolved by applying all matching policies. The last policy to match takes precedence in case of overlapping rules.

When a pod matches multiple network policies, the effective policy combines all allowed traffic rules. However, there's no single mechanism to define priority between policies; enforcement order depends on Kubernetes' internal processing.

Testing Network Policy Effectiveness

Verify that a network policy is working by creating test pods and attempting to connect:

kubectl run test-pod --image=busybox --rm -it -- sh

From within the pod, attempt to reach a target service:

wget --timeout=5 http://target-service:80

If the connection fails due to network policy restrictions, the error message is typically a timeout or connection refused.

Network Policy Limitations in Practice

Network policies only affect pod-to-pod communication. External traffic to services must be handled separately using ingress rules or cloud provider load balancer configurations.

The networking.k8s.io/v1 API version does not support all advanced features available in older versions. For example, the from field in ingress rules requires explicit namespace selectors, while older APIs allowed more flexible matching.

Network policies do not control traffic from host-level processes or services running outside of pods. To secure these, you must use host-level firewalling or cluster-level network security mechanisms.

Network Policy Implementation Details

Network policies are implemented by CNI plugins that enforce the rules at the node level. These plugins maintain state about which pods are allowed to communicate and apply iptables or eBPF rules accordingly.

The enforcement happens in the node's network stack. When a pod attempts to connect to another pod, the CNI plugin checks if the connection is permitted by any active policy before allowing the traffic to pass through.

Network policies do not provide detailed logging or audit trails for communication attempts. To track access patterns, you must implement external logging solutions or use monitoring tools that capture network events from the CNI plugin layer.

Network Policy Updates and Rollouts

Updating a network policy triggers re-evaluation of all matching pods. The change is propagated through the cluster's control plane to all nodes running the CNI plugin.

Policies are applied asynchronously, so immediate connectivity changes may not reflect policy updates immediately. This delay is usually minimal but can be noticeable during rapid configuration changes.

When applying multiple policies simultaneously, Kubernetes applies them in the order they were created. The final network state reflects the combined effect of all active policies in the namespace.

This page was rewritten on 15 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.