How to Set Up Kubernetes Network Policies
Network Policies let you control traffic flow between pods at the IP and port level. By default, all pods in a Kubernetes cluster can communicate freely. Network Policies act as a firewall, restricting which pods can talk to each other. This is essential for securing multi-service applications on your Breeze cluster.
Prerequisites
- A CNI plugin that supports Network Policies (Calico, Cilium, or Weave Net)
- A running Kubernetes cluster on your Breeze instance
- Multiple namespaces or pods to test policy enforcement
Default Deny All Ingress
The first step in any secure cluster is to deny all incoming traffic by default, then explicitly allow what you need:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
This blocks all incoming connections to every pod in the production namespace.
Allowing Traffic from Specific Pods
Now allow only the frontend pods to reach the API pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Restricting Egress Traffic
You can also control outbound connections. This policy only allows the API pods to talk to the database on port 5432 and DNS on port 53:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Namespace-Based Isolation
Restrict traffic to pods from a specific namespace using namespaceSelector:
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: staging
Testing Network Policies
Deploy a temporary debug pod and attempt connections:
# This should be blocked
kubectl run test-pod --rm -it --image=busybox --restart=Never -- wget -qO- --timeout=3 http://api-service:8080
# Verify from an allowed pod
kubectl exec frontend-pod-xyz -- wget -qO- http://api-service:8080
Best Practices
- Start with a default deny policy in every namespace
- Explicitly allow only required communication paths
- Always allow DNS egress (UDP/TCP 53) or pods cannot resolve service names
- Label namespaces for cross-namespace policies
- Document every policy so your team understands the intended traffic flow on your Breeze cluster