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.