- Declarative only: no
kubectl create networkpolicy - Requires network policy controller (CNI plugin): assume installed on exam
- Default: all traffic allowed until a policy selects Pods
Spec structure
podSelector: which Pods policy applies topolicyTypes:[Ingress],[Egress], or bothingress/egressrules:from/to,ports
Allow specific traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels:
tier: backend
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
Interpretation: policy applies to tier=backend; only tier=frontend Pods may connect to those Pods on TCP 8080. Everything else to selected Pods is denied for that policy type.
Default deny-all
spec:
podSelector: {} # all Pods in namespace
policyTypes: [Ingress, Egress]
# no ingress/egress rules = deny all
Cross-namespace
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: other-ns
podSelector:
matchLabels:
app: client
ipBlock (external / CIDR-based traffic)
Use ipBlock to allow traffic to/from IP ranges (e.g. external load balancers, on-prem systems):
# Allow ingress from a specific external CIDR
ingress:
- from:
- ipBlock:
cidr: 192.168.1.0/24
except:
- 192.168.1.5/32 # exclude a specific IP
# Allow egress to an external API (e.g. 203.0.113.0/24)
egress:
- to:
- ipBlock:
cidr: 203.0.113.0/24
ports:
- protocol: TCP
port: 443
ipBlockmatches by IP address, not labelsexceptfield excludes sub-ranges from the allowed CIDR
Allow DNS (required when using default-deny egress)
If you apply a default-deny egress policy, all DNS lookups break. Always allow DNS:
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP # TCP 53 needed for large DNS responses
port: 53
Selector logic
- Multiple entries in
from→ OR - Multiple conditions in one selector entry → AND
# OR: frontend OR cache can connect
from:
- podSelector:
matchLabels:
tier: frontend
- podSelector:
matchLabels:
tier: cache
# AND: pods with tier=frontend inside namespaces labeled name=prod
from:
- namespaceSelector:
matchLabels:
name: prod
podSelector:
matchLabels:
tier: frontend
Debug blocked traffic
kubectl get netpol -n <ns>
kubectl get netpol <name> -n <ns> -o yaml
kubectl get po -n <ns> --show-labels
kubectl exec <source> -n <ns> -- wget -qO- --timeout=2 http://<svc>:<port>
Common shapes
# Deny all ingress to all Pods in a namespace
spec:
podSelector: {}
policyTypes: [Ingress]
ingress: []
# Allow egress to database and DNS only
policyTypes: [Egress]
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to: []
ports:
- protocol: UDP
port: 53
kubectl
kubectl apply -f netpol.yaml
kubectl get netpol
kubectl describe netpol allow-frontend
Exam tips
- Empty
podSelector: {}= all Pods in namespace - Policy must match Pod labels, not Service names
- Egress deny breaks DNS: allow UDP and TCP 53 to kube-dns in kube-system
ipBlockandpodSelectorcan be combined in the samefrom[]list (OR logic)- "Allow X to Y" usually means an ingress policy on Y
- NetworkPolicies do nothing unless the cluster CNI enforces them