Chapter 5. Kubernetes Network Policies
— Default-Deny (with Tests)
Prereqs
- Your app is deployed in namespace ship, Service name app (adjust if different).
- Your Minikube profile has a CNI that enforces NetworkPolicies (e.g., Cilium or Calico).
If you haven’t enabled one yet, run a CNI addon that supports NetworkPolicy. (Minikube supports popular CNIs; pick one available on your setup.)
1) Capture service info
export NS=ship
export SVC=app
# Replace with your service port if not 8080:
export PORT=8080
kubectl -n $NS get svc $SVC -o wide
2) Apply a namespace default-deny
Create infra/k8s/netpol-default-deny.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: ship
spec:
podSelector: {} # all Pods in namespace
policyTypes: ["Ingress","Egress"] # deny everything by default
mkdir -p artifacts/netpol-manifests
kubectl apply -f infra/k8s/netpol-default-deny.yaml | tee artifacts/netpol-manifests/apply.txt
3) Launch a test client and try to curl (should be blocked)
# A temporary debug pod without any special labels
kubectl -n $NS run netshoot --restart=Never --image=nicolaka/netshoot -it --rm -- \
/bin/sh -lc "apk add --no-cache curl >/dev/null 2>&1 || true; \
echo 'curling cluster service…'; \
curl -sS --max-time 5 http://$SVC.$NS.svc.cluster.local:$PORT/healthz || echo 'BLOCKED'"
Save output:
kubectl -n $NS run netshoot --restart=Never --image=nicolaka/netshoot --command -- sleep 5 2>/dev/null || true
kubectl -n $NS delete pod netshoot 2>/dev/null || true
Append your curl attempt (stdout/stderr) to ./artifacts/netpol-test.txt:
echo -e "\n--- BLOCK attempt $(date) ---" >> artifacts/netpol-test.txt
# (paste the curl output from the interactive run here)
Expected: timeout or connection refused → blocked.
4) Allow traffic only from labeled clients to the app Pods
Label your app Pods (if not already):
kubectl -n $NS label deploy/$SVC app=$SVC --overwrite
Create infra/k8s/netpol-allow-app-from-labeled.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-from-labeled
namespace: ship
spec:
podSelector:
matchLabels:
app: app # target: your app Pods (adjust label if needed)
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
access: allowed
ports:
- protocol: TCP
port: 8080 # adjust to your app containerPort/Service port
Apply it:
kubectl apply -f infra/k8s/netpol-allow-app-from-labeled.yaml \
| tee -a artifacts/netpol-manifests/apply.txt
5) Test again (first blocked, then allowed)
Create an unlabeled client (still blocked):
kubectl -n $NS run np-client --restart=Never --image=nicolaka/netshoot -- \
/bin/sh -lc "apk add --no-cache curl >/dev/null 2>&1 || true; \
curl -sS --max-time 5 http://$SVC.$NS.svc.cluster.local:$PORT/healthz || echo BLOCKED" \
| tee -a artifacts/netpol-test.txt
kubectl -n $NS delete pod np-client --now
Create an allowed client and label it:
kubectl -n $NS run np-allowed --restart=Never --image=nicolaka/netshoot -- /bin/sh -lc "sleep 3600" >/dev/null 2>&1 &
sleep 2
kubectl -n $NS label pod np-allowed access=allowed --overwrite
kubectl -n $NS exec np-allowed -- /bin/sh -lc \
"apk add --no-cache curl >/dev/null 2>&1 || true; \
curl -sS --max-time 5 http://$SVC.$NS.svc.cluster.local:$PORT/healthz" \
| tee -a artifacts/netpol-test.txt
kubectl -n $NS delete pod np-allowed --now
Expected: first attempt BLOCKED, second attempt 200 OK.
Makefile helpers (optional)
netpol-apply:
kubectl apply -f infra/k8s/netpol-default-deny.yaml
kubectl apply -f infra/k8s/netpol-allow-app-from-labeled.yaml
netpol-test:
@NS=ship SVC=app PORT=8080 bash -lc '\
kubectl -n $$NS run np-client --restart=Never --image=nicolaka/netshoot -- /bin/sh -lc "apk add --no-cache curl >/dev/null 2>&1 || true; curl -sS --max-time 5 http://$$SVC.$$NS.svc.cluster.local:$$PORT/healthz || echo BLOCKED" | tee -a artifacts/netpol-test.txt; \
kubectl -n $$NS delete pod np-client --now; \
kubectl -n $$NS run np-allowed --restart=Never --image=nicolaka/netshoot -- /bin/sh -lc "sleep 3600" >/dev/null 2>&1 & sleep 2; \
kubectl -n $$NS label pod np-allowed access=allowed --overwrite; \
kubectl -n $$NS exec np-allowed -- /bin/sh -lc "apk add --no-cache curl >/dev/null 2>&1 || true; curl -sS --max-time 5 http://$$SVC.$$NS.svc.cluster.local:$$PORT/healthz" | tee -a artifacts/netpol-test.txt; \
kubectl -n $$NS delete pod np-allowed --now; \
echo "Wrote artifacts/netpol-test.txt"'
Checklist
- Your Minikube profile has a CNI that enforces NetworkPolicy
-
default-denyapplied for Ingress+Egress - Labeled allow-rule works (blocked → allowed)
-
artifacts/netpol-test.txtsaved with both outcomes