How Do You Isolate Namespaces with Network Policies?
Namespace isolation uses Network Policies with namespaceSelector to restrict traffic between namespaces. Apply a default-deny policy to each namespace, then use namespace labels to create explicit allow rules — for example, allowing only the frontend namespace to reach the backend namespace.
Detailed Answer
Namespace isolation is achieved by combining default-deny Network Policies with explicit allow rules that use namespaceSelector. This creates a zero-trust model where cross-namespace traffic is blocked unless explicitly permitted.
Step 1: Label Your Namespaces
Network Policies use labels to identify namespaces. Since Kubernetes 1.22, every namespace automatically gets the kubernetes.io/metadata.name label:
kubectl get namespace production --show-labels
# NAME STATUS AGE LABELS
# production Active 30d kubernetes.io/metadata.name=production
# Add custom labels for fine-grained control
kubectl label namespace frontend team=frontend environment=production
kubectl label namespace backend team=backend environment=production
kubectl label namespace monitoring purpose=monitoring
Step 2: Apply Default-Deny to Each Namespace
# Apply this to every namespace that needs isolation
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: backend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Step 3: Create Cross-Namespace Allow Rules
Allow the frontend namespace to reach backend services:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend
ports:
- protocol: TCP
port: 8080
Allow monitoring to scrape metrics from all namespaces:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring-scrape
namespace: backend
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: monitoring
ports:
- protocol: TCP
port: 9090
Complete Namespace Isolation Example
A three-tier application with strict isolation:
# --- Backend Namespace Policies ---
# Deny all
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: backend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Allow DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: backend
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
---
# Allow intra-namespace communication
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: backend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector: {}
egress:
- to:
- podSelector: {}
---
# Allow ingress from frontend namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend
ports:
- protocol: TCP
port: 8080
---
# Allow ingress from ingress controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-controller
namespace: backend
spec:
podSelector:
matchLabels:
exposed: "true"
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
Common Patterns
Allow within the same namespace only
ingress:
- from:
- podSelector: {} # All Pods in THIS namespace
Allow from specific namespaces
ingress:
- from:
- namespaceSelector:
matchLabels:
team: frontend
Allow from specific Pods in specific namespaces (AND logic)
ingress:
- from:
- namespaceSelector:
matchLabels:
team: frontend
podSelector:
matchLabels:
app: web
Allow from all namespaces (cluster-wide)
ingress:
- from:
- namespaceSelector: {} # ALL namespaces
Verification
# Test from the frontend namespace to backend
kubectl exec -n frontend deploy/web -- curl -m 5 http://api.backend:8080
# Should succeed
# Test from an unauthorized namespace
kubectl exec -n unauthorized deploy/attacker -- curl -m 5 http://api.backend:8080
# Should timeout (denied by policy)
System Namespace Considerations
Always allow traffic from system namespaces that provide essential services:
| Namespace | Service | Direction | |---|---|---| | kube-system | DNS (CoreDNS) | Egress from all Pods | | ingress-nginx | Ingress controller | Ingress to exposed Pods | | monitoring | Prometheus | Ingress to metrics ports | | cert-manager | Certificate management | Egress for ACME challenges |
Why Interviewers Ask This
Interviewers ask this to assess whether you can implement multi-tenant network isolation in a shared cluster — a common production security requirement.
Common Follow-Up Questions
Key Takeaways
- Label namespaces and use namespaceSelector in Network Policies for cross-namespace access control.
- Default-deny per namespace combined with explicit cross-namespace allow rules creates strong isolation.
- Remember to allow traffic from system namespaces (kube-system for DNS, ingress-nginx for external traffic).