← News
/PLAYBOOK · 2026-09-03

NetworkPolicy in Practice: K8s Pod Microsegmentation Guide

Kubernetes NetworkPolicy tutorial: default-deny baseline, DNS allow, and label allowlists for Pod microsegmentation, with full YAML, connectivity tests, and common failure modes.

Scope

NetworkPolicy microsegmentation fits these cases:

Prerequisites

How it works

NetworkPolicy is Kubernetes native network ACL. Core rule: once a Pod is selected by a NetworkPolicy, it is default-deny—ingress and egress not explicitly allowed are dropped. Scope is set by three selectors:

The CNI compiles policies to iptables/eBPF on the node. No process inside the Pod is involved; the container cannot bypass it.

Steps

1. Deploy the demo app

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  labels:
    app: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    app: backend
  ports:
  - port: 80

2. Default-deny all ingress and egress

Apply full default-deny on the demo namespace as the security baseline:

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

Empty podSelector (`{}`) selects every Pod in the namespace. policyTypes includes both Ingress and Egress.

3. Allow DNS

Default-deny kills all egress. Allow DNS first or name resolution dies:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: demo
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

4. Allow only frontend to backend

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: demo
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80

5. Allow external sources by CIDR (optional)

To let an office network reach a service, use ipBlock:

  ingress:
  - from:
    - ipBlock:
        cidr: 10.20.0.0/16
        except:
        - 10.20.5.0/24

except carves holes out of the CIDR.

Verify

# Frontend Pod accessing backend: should return the nginx welcome page
kubectl -n demo run test-front --image=busybox -l app=frontend --rm -it --restart=Never -- wget -qO- --timeout=3 http://backend

# Pod without the frontend label accessing: should time out and fail
kubectl -n demo run test-other --image=busybox --rm -it --restart=Never -- wget -qO- --timeout=3 http://backend

First command returns HTML; second times out—policy is live. Also: `kubectl -n demo describe networkpolicy allow-frontend-to-backend` to inspect resolved policy.

FAQ

FAQ 1: Policy creates but does nothing?

Most common cause: CNI does not support NetworkPolicy (e.g. Flannel). Check plugin with `kubectl get pods -n kube-system`; switch to Calico or Cilium if unsupported. Also verify labels match podSelector exactly.

FAQ 2: App DNS fails; health checks cut off?

Default-deny intercepts all egress. Keep the allow-dns policy for kube-system port 53. kubelet probes are not subject to NetworkPolicy; app calls to external APIs need their own egress rules.

Summary

NetworkPolicy is default-deny plus allowlist—native, declarative microsegmentation for Kubernetes. Order of operations: deploy default-deny-all, then allow DNS and business paths one by one, then verify both allow and deny with real Pods. Policies match Pod labels dynamically; scale events need no extra rules. Cheapest east-west control in a cloud-native cluster.