NetworkPolicies
Implement namespace-level firewall rules to control which Pods can communicate with each other.
Default Network Behaviour
By default, Kubernetes uses a flat network: every Pod can reach every other Pod in any namespace, on any port. There are no firewalls between them. This is convenient for getting started but dangerous for production β a compromised Pod can freely reach your database.
NetworkPolicy: Kubernetes Firewalls
A NetworkPolicy is a namespace-scoped resource that defines firewall rules for Pod traffic. It works at the IP/port level, not the HTTP level.
Critical prerequisite: NetworkPolicies are enforced by the CNI plugin, not by Kubernetes itself. You must use a CNI that supports NetworkPolicies:
- β Calico, Cilium, Weave Net, Antrea
- β kindnet (the default kind CNI) β policies are accepted but NOT enforced
Policy Types
| Type | Controls |
|---|---|
Ingress | Traffic entering a Pod |
Egress | Traffic leaving a Pod |
A NetworkPolicy applies to Pods matched by podSelector. If no podSelector is specified ({}), the policy applies to ALL pods in the namespace.
The Default-Deny Pattern
The most secure posture is allowlist-based:
Step 1: Apply a default-deny policy (empty ingress/egress rules):
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
# no ingress or egress rules = deny allStep 2: Add explicit allow policies for each required traffic flow.
This is the same pattern as a security group in AWS or a firewall in traditional networking β deny everything, then allow specific flows.
Selector Types
| Selector | Matches |
|---|---|
podSelector | Pods with specific labels in the same namespace |
namespaceSelector | All pods in namespaces with specific labels |
ipBlock | Specific CIDR ranges (for external traffic) |
You can combine podSelector and namespaceSelector to mean "Pods with label X in namespace Y".
Key Gotcha: namespaceSelector and Labels
namespaceSelector matches on namespace labels, not namespace names. The target namespace must have the label you are selecting on:
kubectl label namespace monitoring env=monitoring
Then namespaceSelector: {matchLabels: {env: monitoring}} will work.
NetworkPolicy Kernel-Level Filtering Flow
[ Incoming Packet ] (Source: Attacker Pod IP)
|
v
+------------------+-------------------+
| Linux Host Network Namespace |
+------------------+-------------------+
|
v (Enters veth interface for Target Pod)
+------------------+-------------------+
| CNI Enforcement Hook (Kernel Space)|
| |
| - Option A: eBPF Socket Filter | ==> Match found? No => [ DROP Packet ]
| - Option B: iptables & ipset checks|
+------------------+-------------------+
| (Permitted by Allowlist)
v
+------------------+-------------------+
| Target Pod Network Namespace |
| - Container Processes (Port 80) |
+-------------------------------------+Under the Hood: NetworkPolicy Enforcement & CNI Engines
1. The Role of the CNI Daemon
Because NetworkPolicies are not enforced by the Kubernetes control plane directly, the CNI daemon (e.g., calico-node or cilium-agent) must watch the API server for policies and Pod changes. When a rule is added, the local CNI daemon translates it into low-level host OS kernel configuration.
2. iptables and ipset Chains (Calico standard mode)
In an iptables-based CNI, the agent configures custom chains (such as KUBE-NWPLCY-*). It aggregates the matched IPs of labeled pods into ipsetsβin-kernel hash tables that allow the iptables engine to match packets in O(1) time rather than linearly scanning hundreds of IP addresses.
3. eBPF Filtering (Cilium mode)
In eBPF-based networks, the CNI compiles NetworkPolicies directly into eBPF bytecode. It loads this program into the Linux kernel and binds it to the virtual ethernet interface (veth pair) or traffic control (tc) subsystems. Packets are evaluated and dropped at the socket layer, avoiding IP routing pipeline processing entirely for blocked connections, minimizing CPU utilization.
4. Connection Tracking (`conntrack`)
NetworkPolicies operate statefully. The policy engine hooks into the Linux kernel's connection tracking module (conntrack). Once a TCP handshake packet matches an allowed Egress or Ingress rule, the reverse response packets are automatically allowed back through the firewall, even if no explicit rule permits the return path.