Network Policy Patterns
Network Policy patterns are reusable configurations that solve common network isolation scenarios. Understanding these patterns helps you implement effective network security in your Kubernetes clusters. This guide covers the most common patterns you’ll encounter.
Common Patterns
1. Namespace Isolation
Isolate all pods in a namespace from other namespaces:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # All pods in namespace
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: production # Allow only within namespace
egress:
- to:
- namespaceSelector:
matchLabels:
name: production
This ensures pods in the production namespace can only communicate with other pods in the same namespace.
2. Application Tier Isolation
Isolate application tiers (frontend, backend, database):
# Frontend - Allow ingress from anywhere, egress to API only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-isolation
spec:
podSelector:
matchLabels:
tier: frontend
ingress:
- {} # Allow all ingress
egress:
- to:
- podSelector:
matchLabels:
tier: api
ports:
- protocol: TCP
port: 8080
- to:
- namespaceSelector:
matchLabels:
name: kube-system
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# API - Allow ingress from frontend, egress to database only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-isolation
spec:
podSelector:
matchLabels:
tier: api
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# Database - Allow ingress from API only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-isolation
spec:
podSelector:
matchLabels:
tier: database
ingress:
- from:
- podSelector:
matchLabels:
tier: api
ports:
- protocol: TCP
port: 5432
# No egress = allow all egress
3. Microservices Isolation
Isolate individual microservices:
# User Service - Allow ingress from API Gateway only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: user-service-policy
spec:
podSelector:
matchLabels:
app: user-service
ingress:
- from:
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
4. Database Access Control
Restrict database access to specific applications:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-access
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- podSelector:
matchLabels:
app: api-service
- podSelector:
matchLabels:
app: admin-service
ports:
- protocol: TCP
port: 5432
# No egress rules = allow all egress
Only api-service and admin-service can access the database.
5. Multi-Namespace Communication
Allow communication between specific namespaces:
# In frontend namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend
namespace: frontend
spec:
podSelector:
matchLabels:
app: web
egress:
- to:
- namespaceSelector:
matchLabels:
name: backend
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 8080
---
# In backend namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: backend
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
6. External Access Only
Allow pods to receive traffic only from outside the cluster:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: external-only
spec:
podSelector:
matchLabels:
app: public-api
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8 # Block internal cluster IPs
- 172.16.0.0/12 # Block internal cluster IPs
- 192.168.0.0/16 # Block internal cluster IPs
ports:
- protocol: TCP
port: 80
# No egress = allow all egress
7. Deny All, Allow Specific
Start with deny-all, then allow specific traffic:
# Step 1: Deny all
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# No rules = deny all
# Step 2: Allow specific ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
# Step 3: Allow DNS egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
8. Service Mesh Integration
Allow service mesh traffic while maintaining isolation:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: service-mesh-policy
spec:
podSelector:
matchLabels:
app: my-app
ingress:
- from:
- podSelector:
matchLabels:
app: other-app
- namespaceSelector:
matchLabels:
name: istio-system # Allow service mesh control plane
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: istio-system
ports:
- protocol: TCP
port: 15017 # Istio agent port
Best Practices for Patterns
- Start restrictive - Begin with deny-all, then allow as needed
- Use consistent labels - Consistent labeling makes policies easier
- Document patterns - Document why each pattern is used
- Test incrementally - Apply policies gradually and test
- Allow DNS - Always include DNS egress rules
- Review regularly - Review policies as applications evolve
- Use namespaces - Organize policies by namespace
- Monitor effects - Watch for connectivity issues
- Version control - Keep policies in version control
- Automate testing - Test policies as part of CI/CD
Common Mistakes
Forgetting DNS
# ❌ Bad - No DNS access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: bad-policy
spec:
podSelector:
matchLabels:
app: web
egress:
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
# ✅ Good - Includes DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: good-policy
spec:
podSelector:
matchLabels:
app: web
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
Overly Permissive Policies
# ❌ Bad - Too permissive
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: too-permissive
spec:
podSelector:
matchLabels:
app: web
ingress:
- {} # Allows all ingress
# ✅ Good - Specific rules
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: specific
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
Missing Health Checks
Ensure health check traffic is allowed:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: with-health-checks
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 8080 # Health check port
See Also
- Network Policies Overview - Introduction to Network Policies
- Services - Services that policies may need to allow
- CNI Plugins - CNI plugins that support Network Policies