- Default K8s: all pods can talk to all pods
- Once a NetworkPolicy selects a Pod: only explicitly allowed traffic passes
- Declarative only: no
kubectl create networkpolicy - Requires CNI plugin: assume installed on exam
Deny-all ingress + allow specific
# Pattern 1: Deny ALL ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
spec:
podSelector:
matchLabels:
app: db
policyTypes:
- Ingress
# NO ingress rules = deny all ingress
---
# Pattern 2: Allow only from specific pods + namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-webapp
spec:
podSelector:
matchLabels:
app: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: webapp
namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 5432
Default-deny ALL (ingress + egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # empty = ALL pods
policyTypes:
- Ingress
- Egress
Egress control
spec:
podSelector:
matchLabels:
app: webapp
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
- to:
- podSelector:
matchLabels:
app: db
AND vs OR: the key distinction
# SAME item = AND (webapp pod IN prod namespace)
ingress:
- from:
- podSelector:
matchLabels:
app: webapp
namespaceSelector:
matchLabels:
env: prod
# Separate items = OR (webapp pod) OR (any pod in prod namespace)
ingress:
- from:
- podSelector:
matchLabels:
app: webapp
- namespaceSelector:
matchLabels:
env: prod
ipBlock
ingress:
- from:
- ipBlock:
cidr: 192.168.1.0/24
except:
- 192.168.1.5/32
egress:
- to:
- ipBlock:
cidr: 203.0.113.0/24
ports:
- protocol: TCP
port: 443
Allow DNS (required with default-deny egress)
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
kubectl
kubectl apply -f netpol.yaml
kubectl get netpol
kubectl describe netpol allow-frontend
Exam gotchas
- Empty
podSelector: {}= all Pods in namespace - Policy matches Pod labels, not Service names
- Egress deny breaks DNS: allow UDP and TCP 53 to kube-dns
- NetworkPolicy requires CNI with policy support (Calico, Cilium, Weave); Flannel alone does NOT enforce
Practice scenario: Three-tier + NetworkPolicies
Tasks
- NS
production→ 3 Deployments:tier=frontend|backend|database - Services: frontend LoadBalancer :80; backend ClusterIP :3000→80; database :5432
- NetPol: backend ingress only from frontend on 3000
- NetPol: database ingress only from backend on 5432
Solution
kubectl create ns production
kubectl create deploy frontend --image=nginx --labels=tier=frontend -n production
kubectl create deploy backend --image=nginx --labels=tier=backend -n production
kubectl create deploy database --image=postgres --labels=tier=database -n production
kubectl expose deploy frontend --port=80 --type=LoadBalancer --name=frontend-svc -n production
kubectl expose deploy backend --port=3000 --target-port=80 --name=backend-svc -n production
kubectl expose deploy database --port=5432 --name=database-svc -n production
# apply NetworkPolicy YAML: podSelector tier=backend/database + from podSelector + ports
kubectl get deploy,svc,netpol -n production
Concepts: NetPol podSelector = Pod labels; port-level ingress.