By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Pod-to-Pod Traffic Control for Engineers Who Ship
Network Policies are Kubernetes’ firewall rules for pods. They define which pods can talk to which other pods (or external services) and on which ports. Without them, your cluster is a free-for-all: any pod can reach any other pod, including sensitive ones (databases, internal APIs, admin dashboards).
You’re a DevOps engineer at a fintech startup. Your payment service (pod payments-v1) talks to: - A PostgreSQL database (pod pg-primary) - A Redis cache (pod redis-cache) - An internal fraud API (pod fraud-detection)
payments-v1
pg-primary
redis-cache
fraud-detection
Problem: A junior dev deploys a debug pod (debug-shell) with kubectl exec access. Without Network Policies, this pod can: - Query the database directly (bypassing the payment service).- Flood Redis with garbage requests.- Call the fraud API in a loop, triggering false positives.
debug-shell
kubectl exec
Solution: Use Network Policies to enforce: - Only payments-v1 can talk to pg-primary and redis-cache.- Only payments-v1 and fraud-detection can talk to each other.- No other pods can reach these services.
NetworkPolicy
podSelector
app: payments
tier: backend
policyTypes
Ingress
Egress
policyTypes: ["Ingress", "Egress"]
ingress
from
egress
api.stripe.com
namespaceSelector
namespaceSelector: { matchLabels: { env: prod } }
ipBlock
10.0.0.0/24
kubectl get pods -n kube-system | grep -E 'calico|cilium'
kubectl
bash kubectl create namespace network-policy-demo kubectl config set-context --current --namespace=network-policy-demo
We’ll simulate the fintech scenario: - payments-v1: The payment service.- pg-primary: PostgreSQL database.- redis-cache: Redis cache.- fraud-detection: Internal fraud API.- debug-shell: A rogue pod (simulating a compromised pod).
Deploy the pods and services:
# Payments service kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: payments-v1 labels: app: payments tier: backend spec: containers: - name: nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: payments spec: selector: app: payments ports: - protocol: TCP port: 80 targetPort: 80 EOF # PostgreSQL kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pg-primary labels: app: postgres tier: db spec: containers: - name: postgres image: postgres:13 env: - name: POSTGRES_PASSWORD value: "password" ports: - containerPort: 5432 --- apiVersion: v1 kind: Service metadata: name: postgres spec: selector: app: postgres ports: - protocol: TCP port: 5432 targetPort: 5432 EOF # Redis kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: redis-cache labels: app: redis tier: cache spec: containers: - name: redis image: redis ports: - containerPort: 6379 --- apiVersion: v1 kind: Service metadata: name: redis spec: selector: app: redis ports: - protocol: TCP port: 6379 targetPort: 6379 EOF # Fraud detection kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: fraud-detection labels: app: fraud tier: backend spec: containers: - name: nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: fraud spec: selector: app: fraud ports: - protocol: TCP port: 80 targetPort: 80 EOF # Debug shell (rogue pod) kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: debug-shell labels: app: debug tier: dev spec: containers: - name: alpine image: alpine command: ["sh", "-c", "sleep infinity"] EOF
Before applying policies, confirm all pods can talk to each other:
# From debug-shell, try to reach payments, postgres, and redis kubectl exec debug-shell -- sh -c "nc -zv payments 80 && nc -zv postgres 5432 && nc -zv redis 6379"
Expected Output:
payments (10.96.123.45:80) open postgres (10.96.123.46:5432) open redis (10.96.123.47:6379) open
All traffic is allowed by default.
Block all traffic in the namespace:
kubectl apply -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector: {} policyTypes: - Ingress - Egress EOF
What this does: - podSelector: {}: Applies to all pods in the namespace.- policyTypes: ["Ingress", "Egress"]: Blocks both incoming and outgoing traffic.
podSelector: {}
Verify:
kubectl exec debug-shell -- sh -c "nc -zv payments 80"
nc: payments (10.96.123.45:80): Operation timed out
Traffic is now blocked.
kubectl apply -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-payments-to-db spec: podSelector: matchLabels: app: payments policyTypes: - Egress egress: - to: - podSelector: matchLabels: app: postgres ports: - protocol: TCP port: 5432 - to: - podSelector: matchLabels: app: redis ports: - protocol: TCP port: 6379 EOF
What this does: - Allows payments-v1 to talk to pg-primary (port 5432) and redis-cache (port 6379).- No other pods can talk to these services.
# From payments-v1, test connectivity to postgres and redis kubectl exec payments-v1 -- sh -c "nc -zv postgres 5432 && nc -zv redis 6379"
postgres (10.96.123.46:5432) open redis (10.96.123.47:6379) open
# From debug-shell, try to reach postgres (should fail) kubectl exec debug-shell -- sh -c "nc -zv postgres 5432"
nc: postgres (10.96.123.46:5432): Operation timed out
kubectl apply -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-payments-fraud spec: podSelector: matchLabels: app: payments policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: fraud ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: fraud ports: - protocol: TCP port: 80 EOF
What this does: - Allows fraud-detection to call payments-v1 (ingress).- Allows payments-v1 to call fraud-detection (egress).
# From fraud-detection, test connectivity to payments kubectl exec fraud-detection -- sh -c "nc -zv payments 80"
payments (10.96.123.45:80) open
# From debug-shell, try to reach payments (should fail) kubectl exec debug-shell -- sh -c "nc -zv payments 80"
kubectl apply -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-payments-to-stripe spec: podSelector: matchLabels: app: payments policyTypes: - Egress egress: - to: - ipBlock: cidr: 103.14.0.0/24 # Stripe's IP range (example) ports: - protocol: TCP port: 443 EOF
What this does: - Allows payments-v1 to call api.stripe.com (port 443).- Replace 103.14.0.0/24 with the actual CIDR of your external service.
103.14.0.0/24
kubectl exec payments-v1 -- sh -c "nc -zv api.stripe.com 443"
api.stripe.com (103.14.0.1:443) open
default-deny
prod
monitoring
allow-payments-to-postgres
policy-1
# Allows payments to query fraud API for risk checks
felix
kubectl describe networkpolicy
bash kubectl describe networkpolicy allow-payments-to-postgres
k8s-netpol
Trap: "All traffic is blocked" (wrong).
Policy types:
policyTypes: ["Egress"]
Trap: Forgetting to include Egress in policyTypes.
Selector specificity:
Trap: Using broad selectors like tier: backend.
CNI plugin support:
Trap: Assuming all CNI plugins support Network Policies.
Scenario-based:
frontend
backend
Challenge: You have a monitoring namespace with a prometheus pod (labels: app: prometheus). Write a NetworkPolicy that: 1. Allows prometheus
prometheus
app: prometheus
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.