Introduction
Did you know? By default, every pod in Kubernetes can talk to any other pod—leading to unrestricted internal communication and potential security risks. This is a major concern in production environments where microservices demand strict access controls.
So, how do we lock down communication while ensuring seamless service interactions? NetworkPolicies provide the answer!
The Challenge: Unrestricted Communication = Security Risk
- Pods can freely communicate across namespaces
- Sensitive data exposure due to open networking
- No control over egress traffic to external services
- Lateral movement risk if an attacker compromises a pod
In short, without proper security, a single breach can compromise the entire cluster. The Solution: Layered NetworkPolicies for Progressive Security
Step 1: Deploy the Application Pods
Create a Namespace for Isolation
Organize your application by creating a dedicated namespace.
kubectl create namespace secure-app
Effect:
- All application resources will be deployed in this namespace
- NetworkPolicies will only affect this namespace, avoiding interference with other workloads
Deploy the Frontend Pod
The frontend should be publicly accessible and interact with the backend.
apiVersion: v1
kind: Pod
metadata:
name: frontend
namespace: secure-app
labels:
app: frontend
spec:
containers:
- name: frontend
image: nginx
Effect:
- Creates a frontend pod that can serve requests
- No restrictions yet—open network connectivity
Deploy the Backend Pod
The backend should only communicate with the frontend and the database.
apiVersion: v1
kind: Pod
metadata:
name: backend
namespace: secure-app
labels:
app: backend
spec:
containers:
- name: backend
image: python:3.9
Effect:
- Creates a backend pod to process logic
- Currently accessible by any pod in the cluster
Deploy the Database Pod
The database should only be accessible to the backend.
apiVersion: v1
kind: Pod
metadata:
name: database
namespace: secure-app
labels:
app: database
spec:
containers:
- name: database
image: postgres
Effect:
- Creates a database pod with unrestricted access
- A potential security risk—frontend or any pod could connect
Step 2: Implement NetworkPolicies for Security
By default, Kubernetes allows all pod-to-pod communication. To enforce security, we will apply four key NetworkPolicies step by step.
Enforce a Default Deny-All Policy
Restrict all ingress and egress traffic by default in the secure-app namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: secure-app
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Effect:
- No pod can send or receive traffic until explicitly allowed
- Zero-trust security model enforced at the namespace level
Allow Frontend to Backend Communication
The frontend should be allowed to send requests to the backend, but not directly to the database.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: secure-app
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
Effect:
- Frontend can talk to backend
- Backend cannot talk to frontend or database yet
Allow Backend to Access Database
The backend should be the only service that can communicate with the database.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: secure-app
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
Effect:
- Backend can talk to database
- Frontend is blocked from accessing the database
Restrict Backend’s Outbound Traffic
To prevent data exfiltration, restrict backend’s egress traffic to only a specific external API.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-backend-egress
namespace: secure-app
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 203.0.113.0/24 # Allowed external API
Effect:
- Backend can only connect to authorized external APIs
- Prevents accidental or malicious data exfiltration
Step 3: Verify NetworkPolicies
After applying the policies, test network access between services.
Check if frontend can access backend:
kubectl exec frontend -n secure-app -- curl backend:80
Expected: Success
Check if frontend can access database:
kubectl exec frontend -n secure-app -- curl database:5432
Expected: Connection refused
Check if backend can access database:
kubectl exec backend -n secure-app -- curl database:5432
Expected: Success
Conclusion
We implemented a four-layer security model to gradually enforce pod-to-pod communication rules:
- Default Deny-All Policy – Establish a zero-trust baseline by blocking all ingress and egress traffic. No pod can talk to another unless explicitly allowed.
- Allow Frontend-to-Backend Traffic – Define strict ingress rules so only frontend pods can reach backend services.
- Restrict Backend-to-Database Access – Grant database access only to backend pods, preventing unauthorized services from connecting.
- Control Outbound Traffic – Limit backend egress access only to trusted external APIs while blocking all other outbound requests.
The Impact: Stronger Kubernetes Security
- Strict pod-to-pod communication controls
- Zero-trust networking within the cluster
- Granular access control without breaking service dependencies
- Minimal attack surface, reducing lateral movement risks
This layered approach ensures network isolation, data security, and regulated API access, transforming an open network into a highly secure Kubernetes environment.
Are you using NetworkPolicies in your Kubernetes setup? Let’s discuss how we can enhance cluster security together! Drop your thoughts in the comments.
You implemented Kubernetes Pod Security Standards
