Kubernetes Network Policies
Introduction
Kubernetes by default allows all pod-to-pod communication — a flat network model that is convenient but insecure. Network policies provide pod-level firewalling, enabling micro-segmentation and zero-trust networking within the cluster.
Understanding Network Policies
A NetworkPolicy is a Kubernetes resource that specifies how groups of pods communicate with each other and with external endpoints. Policies are selector-based, namespace-scoped, and implemented by a Container Network Interface (CNI) plugin.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: TCP
port: 443
Default Deny Policies
Start with default deny policies and explicitly allow required traffic. This enforces least-privilege networking.
---
# Default deny all ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
---
# Default deny all egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
Cilium: eBPF-Based Networking
Cilium leverages eBPF to provide network policies with identity-based security, HTTP-aware rules, and cluster mesh capabilities.
# CiliumNetworkPolicy with HTTP-aware filtering
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-http-policy
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/public/.*"
- method: "POST"
path: "/api/v1/orders"
headers:
- "X-API-Version: 2"
# DNS-aware egress policy with Cilium
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: dns-egress
spec:
endpointSelector:
matchLabels:
app: api-server
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
rules:
dns:
- matchPattern: "*"
Calico: Policy-First Networking
Calico provides a rich policy model with both Kubernetes-native and extended policy resources.
# Calico network policy with advanced features
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: payment-service
namespace: production
spec:
selector: app == 'payment-service'
ingress:
- action: Allow
protocol: TCP
source:
selector: app == 'order-service'
namespaceSelector: project == 'production'
destination:
ports:
- 8443
- action: Allow
source:
serviceAccounts:
- name: payment-processor
egress:
- action: Allow
protocol: TLS
destination:
domains:
- "*.payment-gateway.com"
ports:
- 443
# Calico policy enforcement and troubleshooting
calicoctl get networkpolicy -n production
calicoctl get workloadendpoint -n production
calicoctl get profiles
# Test connectivity
calicoctl policy test --pod production/payment-pod-xyz \
--to-pod production/database-pod-abc --port 5432
Zero-Trust for Pods
Zero-trust networking assumes no pod is inherently trusted. Every connection must be authenticated and authorized.
# Zero-trust: identity-aware policy with SPIFFE
apiVersion: spiffe.io/v1beta1
kind: SPIREIdentity
metadata:
name: api-server
spec:
selector:
matchLabels:
app: api-server
dnsNames:
- api-server.production.svc.cluster.local
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zero-trust-api
spec:
podSelector:
matchLabels:
app: api-server
ingress:
- from:
- podSelector:
matchLabels:
spiffe-id: "spiffe://cluster.local/ns/production/sa/api-gateway"
ports:
- protocol: TCP
port: 8443
Policy Testing and Validation
# Test network policies before deployment
netcheck \
--kubeconfig ~/.kube/config \
--namespace production \
--test-policy policy.yaml \
--output detailed
# Monitor policy decisions
cilium monitor -v --type drop | grep policy
# Policy audit mode (log without enforcing)
kubectl annotate ns production "projectcalico.org/policy-audit-mode=enabled"
Conclusion
Kubernetes network policies are essential for cluster security. Start with default-deny, use namespace isolation, leverage CNI-specific features like HTTP-aware filtering with Cilium or service-account policies with Calico, and adopt zero-trust principles where every connection is explicitly authorized. Always test policies in audit mode before enforcement.