Kubernetes NetworkPolicy Reference: Default Deny, Egress, CIDR Rules & Three-Tier Patterns
Kubernetes NetworkPolicy is the built-in way to control pod-to-pod traffic. By default, all pods can talk to all other pods. A NetworkPolicy changes that — once you apply one to a pod, it becomes deny-all except what you explicitly allow. Requires a CNI plugin that supports NetworkPolicy (Calico, Cilium, Weave — not Flannel by default).
kubectl get pods -n kube-system | grep -E "calico|cilium|weave"1. Default Deny & Basic Allow
Default deny-all pattern and allowing specific ingress/egress
# Default deny-all ingress for a namespace (apply this first):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # applies to ALL pods in namespace
policyTypes:
- Ingress # only ingress rules (egress still allowed)
# Default deny-all (both ingress and egress):
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# Allow ingress to the API pods from the frontend pods only:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api # policy applies to pods with app=api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # allow from pods with app=frontend
ports:
- protocol: TCP
port: 8080
# Multiple policies are additive (OR logic):
# Pod with two NetworkPolicies = union of all allowed traffic
2. Cross-Namespace Traffic
Allow traffic from pods in other namespaces using namespaceSelector
# Allow ingress from a specific namespace (e.g. monitoring namespace):
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring # namespace label
ports:
- port: 9090 # Prometheus scrape port
# Allow from specific pods in specific namespace (AND logic — same from[] entry):
ingress:
- from:
- namespaceSelector:
matchLabels:
env: production
podSelector: # AND: namespace AND pod label
matchLabels:
role: prometheus
# IMPORTANT: namespaceSelector + podSelector in the SAME from[] item = AND
# namespaceSelector + podSelector in SEPARATE from[] items = OR
ingress:
- from:
- namespaceSelector: # item 1: any pod in monitoring namespace
matchLabels:
kubernetes.io/metadata.name: monitoring
- podSelector: # item 2: OR any pod with role=admin (ANY namespace)
matchLabels:
role: admin
# Label namespaces for NetworkPolicy selectors:
# kubectl label namespace monitoring kubernetes.io/metadata.name=monitoring
# (kubernetes.io/metadata.name is auto-set in K8s 1.21+ for new namespaces)
3. Egress Rules
Control outbound traffic — allow DNS, external APIs, and database access
# Allow egress only to the database and DNS (deny all other outbound):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
# Allow DNS (ALWAYS include this or pod DNS breaks):
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Allow access to database pods:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- port: 5432
# Allow access to external HTTPS API:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8 # block internal ranges
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- port: 443
# CRITICAL: If you add an Egress policyType without egress rules,
# ALL egress is denied — including DNS. Always explicitly allow UDP/TCP port 53.
4. CIDR-Based Rules & Node Access
Allow/deny traffic to external IP ranges, node IPs, and cloud load balancers
# Allow ingress from a specific CIDR (e.g. VPN range, office IP):
ingress:
- from:
- ipBlock:
cidr: 10.100.0.0/24 # allow from VPN subnet
ports:
- port: 443
# Block access from a broad range except a subset:
ingress:
- from:
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.50.0.0/16 # deny this specific subnet within the /8
# Allow access to cloud metadata API (sometimes needed):
egress:
- to:
- ipBlock:
cidr: 169.254.169.254/32 # AWS/GCP/Azure instance metadata IP
ports:
- port: 80
# Allow egress to Kubernetes API server (for service accounts):
egress:
- ports:
- port: 443
to:
- ipBlock:
cidr: <API-SERVER-IP>/32
# Verify NetworkPolicy is being enforced:
kubectl exec -it api-pod -- nc -zv postgres-service 5432 # should succeed
kubectl exec -it api-pod -- nc -zv other-service 8080 # should fail if blocked
5. Real-World Patterns
Three-tier (frontend/API/DB), monitoring access, and namespace isolation patterns
# Three-tier isolation (frontend -> api -> db):
# Tier 1: Frontend — allow ingress from ingress controller only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: frontend-ingress, namespace: production}
spec:
podSelector: {matchLabels: {tier: frontend}}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
# Tier 2: API — allow ingress from frontend only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: api-ingress, namespace: production}
spec:
podSelector: {matchLabels: {tier: api}}
policyTypes: [Ingress]
ingress:
- from:
- podSelector: {matchLabels: {tier: frontend}}
ports: [{port: 8080}]
# Tier 3: Database — allow ingress from API only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: db-ingress, namespace: production}
spec:
podSelector: {matchLabels: {tier: database}}
policyTypes: [Ingress]
ingress:
- from:
- podSelector: {matchLabels: {tier: api}}
ports: [{port: 5432}]
# Allow Prometheus to scrape all pods in namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: allow-prometheus-scrape, namespace: production}
spec:
podSelector: {} # all pods
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports: [{port: 9090}, {port: 8080}, {port: 3000}]
# Debug: list all NetworkPolicies and what they select:
kubectl get networkpolicy -A
kubectl describe networkpolicy -n production
Track Kubernetes releases at ReleaseRun. Related: Kubernetes RBAC Reference | Cilium Reference | Kubernetes Networking Reference
🔍 Free tool: K8s YAML Security Linter — after writing NetworkPolicies, check all related workload manifests for security misconfigurations.
Founded
2023 in London, UK
Contact
hello@releaserun.com