Network Policies Basics
A NetworkPolicy is a namespaced firewall for pods, selecting them by label and allowing specific ingress and egress. This page walks the core patterns from allow-all to targeted rules.
Search across all documentation pages
A NetworkPolicy is a namespaced firewall for pods, selecting them by label and allowing specific ingress and egress. This page walks the core patterns from allow-all to targeted rules.
kubectl configured for the cluster.Quick setup for a scratch namespace:
kubectl create namespace demo
kubectl label namespace demo team=demo
kubectl -n demo run web --image=nginx --labels="app=web" --port=80
kubectl -n demo run client --image=nicolaka/netshoot --command -- sleep infinityBefore writing policy, confirm your CNI actually enforces it - a policy on a non-enforcing CNI is silently ignored.
kubectl -n demo exec client -- curl -sS --max-time 3 http://webclient pod around as your probe throughout.A NetworkPolicy always has a podSelector that picks which pods it governs in its namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-policy
namespace: demo
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- IngresspodSelector selects target pods by label within the same namespace.podSelector: {} would select every pod in the namespace.policyTypes declares which directions this policy governs.Ingress with no ingress rules means deny all ingress to web.Selecting every pod with no rules is the canonical namespace ingress lockdown.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: demo
spec:
podSelector: {}
policyTypes:
- IngresspodSelector: {} matches all pods in demo.ingress: block means no traffic is allowed in.Now poke a hole: let only pods labeled app=client reach web.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-client-to-web
namespace: demo
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: client
ports:
- protocol: TCP
port: 80app=client in the same namespace.ports list restricts the allowed destination port to 80/TCP.web.Cross-namespace rules use namespaceSelector, matching on namespace labels.
ingress:
- from:
- namespaceSelector:
matchLabels:
team: platform
ports:
- protocol: TCP
port: 80namespaceSelector matches namespaces by their labels, not their names.kubectl label ns platform team=platform) to target them.podSelector in the same from entry to narrow further.The structure of from decides whether selectors combine with AND or OR - a classic gotcha.
ingress:
- from:
- namespaceSelector:
matchLabels:
team: platform
podSelector:
matchLabels:
app: apifrom element are ANDed: pods labeled app=api in team=platform namespaces.- items would OR them instead.Locking egress is symmetric, but be careful: it will break DNS unless you allow it.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: demo
spec:
podSelector: {}
policyTypes:
- Egresskube-system DNS.client probe after applying to see what breaks.The mandatory companion to any egress lockdown - permit DNS so name resolution survives.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: demo
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53kubernetes.io/metadata.name label reliably selects kube-system.A single policy can govern both directions when you list both policyTypes.
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: client
egress:
- to:
- podSelector:
matchLabels:
app: db
ports:
- protocol: TCP
port: 5432web accepts ingress only from client and may only egress to db on 5432.Once policies exist, verify what applies to a pod and confirm behavior.
kubectl -n demo get networkpolicy
kubectl -n demo describe networkpolicy allow-client-to-web
kubectl -n demo exec client -- curl -sS --max-time 3 http://webdescribe shows the resolved selectors and rules for each policy.curl probe to confirm allowed paths pass and others hang.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026