Kubernetes NetworkPolicy
Default deny patterns
Default deny all ingress and egress
Blocks all traffic in and out of all pods in a namespace.
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressDefault deny ingress only
Blocks all incoming traffic; egress remains unchanged.
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- IngressDefault deny egress only
Blocks all outgoing traffic; ingress remains unchanged.
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- EgressExplicit allow patterns
Allow all egress
Overrides egress isolation and allows all outbound traffic.
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}Allow all ingress
Overrides ingress isolation and allows all inbound traffic.
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- {}Selectors
podSelector
Selects pods within the same namespace.
yaml
podSelector:
matchLabels:
role: frontendnamespaceSelector
Selects entire namespaces.
yaml
namespaceSelector:
matchLabels:
project: myprojectCombined namespaceSelector + podSelector (AND logic)
Selects pods matching both conditions.
yaml
from:
- namespaceSelector:
matchLabels:
user: alice
podSelector:
matchLabels:
role: clientipBlock
Used for external CIDR ranges (not Pod IPs).
yaml
ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24matchLabels vs matchExpressions
matchLabels (simple equality, implicit AND)
yaml
matchLabels:
app: web
tier: frontendmatchExpressions (advanced logic)
yaml
matchExpressions:
- key: env
operator: In
values: ["prod", "staging"]
- key: version
operator: NotIn
values: ["v1"]Supported operators:
- In
- NotIn
- Exists
- DoesNotExist
AND vs OR behavior (critical)
AND behavior
Within a single rule:
fromANDportsnamespaceSelectorANDpodSelector- All conditions must match
OR behavior
- Multiple entries in arrays are OR’ed
OR in from
yaml
from:
- podSelector:
matchLabels:
role: frontend
- namespaceSelector:
matchLabels:
project: myprojectOR across rules
yaml
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
- from:
- ipBlock:
cidr: 10.0.0.0/24Meaning of {}
| Location | Meaning |
|---|---|
podSelector: {} | Select all pods |
ingress: - {} | Allow all ingress |
egress: - {} | Allow all egress |
| empty ingress list | Allow nothing |
| empty egress list | Allow nothing |
Evaluation rules
- Policies are additive
- Traffic is allowed if any policy allows it
- If at least one policy selects a pod, default becomes deny
- No policies → allow all traffic
Mandatory note
NetworkPolicy has no effect unless the CNI plugin supports it (e.g., Calico, Cilium).
Additional examples (practical and expressive)
Example 1 — Allow frontend → backend on HTTP and HTTPS only
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-ingress-web
namespace: backend
spec:
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443Example 2 — Allow egress only to database Service by label
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-egress-db
namespace: app
spec:
podSelector:
matchLabels:
app: api
policyTypes: [Egress]
egress:
- to:
- podSelector:
matchLabels:
role: db
ports:
- protocol: TCP
port: 5432Example 3 — Allow DNS egress only (UDP/TCP 53)
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dns-only-egress
namespace: workload
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Example 4 — Allow ingress from specific CIDR to NodePort-facing pods
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-office-cidr
namespace: edge
spec:
podSelector:
matchLabels:
expose: nodeport
policyTypes: [Ingress]
ingress:
- from:
- ipBlock:
cidr: 203.0.113.0/24
ports:
- protocol: TCP
port: 30080Example 5 — Use matchExpressions to select multiple app versions
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: canary-ingress
namespace: api
spec:
podSelector:
matchExpressions:
- key: version
operator: In
values: ["v2", "v3"]
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
team: platform
ports:
- protocol: TCP
port: 8080Example 6 — Strict isolation with explicit allow list (classic zero-trust)
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zero-trust
namespace: payments
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
ingress:
- from:
- podSelector:
matchLabels:
role: gateway
ports:
- protocol: TCP
port: 8443
egress:
- to:
- ipBlock:
cidr: 10.20.0.0/16
ports:
- protocol: TCP
port: 443