Network Policies
Network Policies in Kubernetes provide pod-to-pod network isolation by controlling traffic flow at the network layer. They act as a firewall for your pods, allowing you to define which pods can communicate with each other based on labels, namespaces, and port numbers. Think of Network Policies as security guards that control who can talk to whom in your cluster.
What are Network Policies?
Network Policies are Kubernetes resources that define rules for allowing or denying network traffic between pods. They work by:
- Selecting pods - Using label selectors to identify which pods the policy applies to
- Defining ingress rules - Controlling incoming traffic to selected pods
- Defining egress rules - Controlling outgoing traffic from selected pods
Default Behavior
Without Network Policies:
- All pods can communicate with all other pods
- No network isolation
- Default: allow all traffic
With Network Policies:
- Policies are additive (if any policy allows traffic, it’s allowed)
- If a pod is selected by a Network Policy, it’s isolated by default
- Only explicitly allowed traffic is permitted
Network Policy Structure
A Network Policy has three main sections:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-policy
namespace: default
spec:
podSelector: # Which pods this policy applies to
matchLabels:
app: web
policyTypes: # Ingress, Egress, or both
- Ingress
- Egress
ingress: # Incoming traffic rules
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
egress: # Outgoing traffic rules
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
Basic Network Policy
Here’s a simple policy that allows only specific traffic:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-policy
namespace: default
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
This policy:
- Applies to pods with label
app: web - Allows ingress only from pods with label
app: api - Allows ingress only on port 80
- Denies all other ingress traffic
Ingress Rules
Ingress rules define allowed incoming traffic:
Allow from Specific Pods
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
Allow from Specific Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-namespace
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 80
Allow from IP Block
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ip-block
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- ipBlock:
cidr: 192.168.1.0/24
except:
- 192.168.1.100
ports:
- protocol: TCP
port: 80
Allow from Multiple Sources
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-multiple
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- podSelector:
matchLabels:
app: api
- namespaceSelector:
matchLabels:
name: frontend
- ipBlock:
cidr: 10.0.0.0/8
ports:
- protocol: TCP
port: 80
Egress Rules
Egress rules define allowed outgoing traffic:
Allow to Specific Pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
spec:
podSelector:
matchLabels:
app: web
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
Allow DNS
Pods typically need DNS access:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
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
Default Deny All
Create a policy that denies all traffic (then add allow rules):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # Selects all pods
policyTypes:
- Ingress
- Egress
# No ingress or egress rules = deny all
Then add specific allow policies as needed.
Default Allow All Ingress
Allow all ingress but control egress:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- {} # Allow all ingress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
Multi-Tier Application Example
Here’s a complete example for a three-tier application:
# Frontend - Allow ingress from internet, egress to API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-policy
spec:
podSelector:
matchLabels:
tier: frontend
ingress:
- from:
- namespaceSelector: {} # Allow from any namespace
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
tier: api
ports:
- protocol: TCP
port: 8080
---
# API - Allow ingress from frontend, egress to database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
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
---
# Database - Allow ingress only from API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-policy
spec:
podSelector:
matchLabels:
tier: database
ingress:
- from:
- podSelector:
matchLabels:
tier: api
ports:
- protocol: TCP
port: 5432
# No egress = allow all egress (if no egress policy type)
CNI Plugin Requirements
Network Policies require a CNI plugin that supports them:
- Calico - Full Network Policy support
- Cilium - Full Network Policy support
- Weave Net - Full Network Policy support
- Flannel - Limited support (depends on backend)
- Kubenet - No Network Policy support
Important: Network Policies won’t work if your CNI plugin doesn’t support them.
Best Practices
- Start with deny-all - Begin with restrictive policies, then allow as needed
- Allow DNS - Always allow DNS egress for pod functionality
- Test thoroughly - Network Policies can break applications if misconfigured
- Use labels consistently - Consistent labeling makes policies easier to write
- Document policies - Document why each policy exists
- Test in non-production first - Test policies before applying to production
- Monitor policy effects - Watch for connectivity issues after applying policies
- Use namespaces - Organize policies by namespace
- Review regularly - Review policies as applications evolve
- Allow health checks - Ensure health check traffic is allowed
Troubleshooting
Pods Cannot Communicate
- Check Network Policies:
kubectl get networkpolicies --all-namespaces - Verify pod labels:
kubectl get pods --show-labels - Check policy selectors: Ensure selectors match pod labels
- Test without policies: Temporarily remove policies to test
- Check CNI plugin: Verify CNI supports Network Policies
- Review policy rules: Ensure rules allow expected traffic
DNS Not Working
- Allow DNS egress: Add DNS egress rule to policies
- Check DNS service: Verify CoreDNS is running
- Test DNS directly:
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default - Review egress rules: Ensure DNS traffic is allowed
Policy Not Applied
- Check CNI plugin: Verify CNI supports Network Policies
- Verify policy syntax: Check YAML is valid
- Check pod selector: Ensure selector matches pods
- Review namespace: Ensure policy is in correct namespace
- Check CNI logs: Review CNI plugin logs for errors
See Also
- Network Policy Patterns - Common policy patterns and examples
- Services - Services that policies may need to allow
- CNI Plugins - CNI plugins that support Network Policies
- Pod Connectivity - Understanding pod networking