Calico Network Policies allow you to define granular network access rules for your Kubernetes pods, effectively acting as a firewall for your cluster.
Let’s see Calico Network Policies in action. Imagine we have a simple application with a frontend pod (frontend) and a backend pod (backend). By default, they can talk to each other.
apiVersion: v1
kind: Pod
metadata:
name: frontend
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
apiVersion: v1
kind: Pod
metadata:
name: backend
labels:
app: backend
spec:
containers:
- name: python
image: python:3.9-slim
command: ["python", "-m", "http.server", "8000"]
Without any policies, we can curl from frontend to backend:
# Inside the frontend pod
$ curl http://backend:8000
Now, let’s introduce a NetworkPolicy that denies all ingress traffic to the backend pod.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
If we try to curl from frontend to backend again, it will fail.
# Inside the frontend pod
$ curl http://backend:8000
curl: (7) Failed to connect to backend port 8000: Connection refused
This NetworkPolicy selects pods with the label app: backend and applies the policyTypes: [Ingress] rule. Since there are no ingress rules defined, all ingress traffic is implicitly denied.
To allow frontend to talk to backend, we need to add an ingress rule to our NetworkPolicy.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8000
With this policy, traffic from pods labeled app: frontend to pods labeled app: backend on TCP port 8000 is allowed. All other ingress traffic to backend remains denied.
This is the core concept: select pods, define policy types (Ingress/Egress), and then specify rules based on pod selectors, namespaces, or IP blocks, and target ports.
The system Calico uses to enforce these policies is quite interesting. When you apply a NetworkPolicy, Calico translates these Kubernetes NetworkPolicy objects into its own internal datamodel. For Calico, this means programmatically configuring its BGP daemon (BIRD) or IP-in-IP/VXLAN encapsulation, and more importantly, programming iptables rules on each node. Each pod gets an IP address, and iptables rules are applied to the host’s network stack to intercept and filter traffic destined for or originating from those pods based on the defined policies. This happens at the node level, meaning traffic doesn’t need to go through a central proxy; it’s filtered as it leaves or enters the node’s network interface associated with the pod.
A common point of confusion is the difference between podSelector and namespaceSelector. podSelector matches pods within the same namespace, while namespaceSelector matches entire namespaces. If you want to allow traffic from a specific pod in another namespace, you’d use namespaceSelector on the target namespace and podSelector for the source pod within that namespace.
You might think that if a pod has no labels, it cannot be selected. However, an empty podSelector: {} will match all pods in the namespace. This is a powerful way to create a default-deny policy for all pods in a namespace if you want to explicitly allow only specific traffic.
The policyTypes field is crucial. If you omit it, it defaults to Ingress and Egress. If you specify policyTypes: [Ingress], then egress traffic from the selected pods is not affected by this policy. If you want to control both incoming and outgoing traffic for a set of pods, you must include both Ingress and Egress in policyTypes.
The most surprising true thing about Calico Network Policies is that they are not strictly confined to Kubernetes. Calico is a networking solution that can be used independently of Kubernetes, and its network policy engine can enforce policies on bare-metal servers or VMs as well. The Kubernetes NetworkPolicy API is essentially a declarative interface that Calico understands and translates into its underlying, more general-purpose policy enforcement mechanisms. This means you can have a consistent policy framework across your Kubernetes cluster and your traditional infrastructure.
The next concept to explore is Calico’s support for Global Network Policies, which operate across all namespaces, unlike standard Network Policies.