TL;DR
- NetworkPolicy is a core Kubernetes resource (since v1.7, GA in v1.19) for declaring ingress and egress rules between pods, namespaces, and external CIDRs.
- The API is implementation-agnostic — the rules are enforced by the cluster's CNI plugin. Calico, Cilium, Antrea, and Weave Net are the dominant implementations; the default kindnet/flannel CNI does NOT enforce NetworkPolicy.
- Default Kubernetes networking is wide open: every pod can reach every other pod. NetworkPolicy is the primary primitive for zero-trust pod networking inside the cluster.
- Cilium adds L7 (HTTP, gRPC, Kafka) and identity-based policies via its CiliumNetworkPolicy CRD; Calico extends with GlobalNetworkPolicy and HostEndpoint. Both are common in sovereign deployments where pod-to-pod isolation is auditable.
Default Pod Networking and Why It Needs Policy#
Kubernetes' default networking model assumes every pod can reach every other pod by IP. This is a useful default for getting started but unacceptable in production: a compromised pod in one tenant's namespace can probe and attack every other workload in the cluster. NetworkPolicy plugs that hole.
Once any NetworkPolicy selects a pod, that pod's traffic becomes default-deny for the policy direction (ingress or egress). The cluster admin then declares what is allowed. The model is whitelist-only — there is no "deny" verb, only "this is allowed."
Anatomy of a Policy#
# Allow only the gateway to reach vLLM pods; deny everything else
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: vllm-ingress
namespace: inference
spec:
podSelector:
matchLabels: { app: vllm }
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels: { name: ingress }
podSelector:
matchLabels: { app: envoy-gateway }
ports:
- protocol: TCP
port: 8000What the API Covers#
- podSelector — which pods does this policy apply to (in the same namespace).
- policyTypes — Ingress, Egress, or both.
- ingress.from / egress.to — pod selectors, namespace selectors, IPBlock CIDRs.
- ports — protocol (TCP/UDP/SCTP) and port number or named port.
- endPort — port range, added in v1.25.
Implementations#
NetworkPolicy is enforced by the CNI plugin — the kernel is not involved in the API itself, the CNI is. The major implementations:
| CNI | Vendor | NetworkPolicy | Extras |
|---|---|---|---|
| Calico | Tigera | Full | GlobalNetworkPolicy, host policies, eBPF mode |
| Cilium | Isovalent | Full | L7 policies, identity-based, eBPF native |
| Antrea | VMware/Broadcom | Full | ClusterNetworkPolicy, Open vSwitch |
| Weave Net | Weaveworks | Full | Encryption in CNI |
| AWS VPC CNI | AWS | Yes (since 2023) | Native VPC routing |
| kindnet / flannel | Various | No | Use only with separate policy enforcer |
Cilium L7 and Identity#
Standard NetworkPolicy operates at L3/L4 — IPs and ports. Cilium adds CiliumNetworkPolicy and CiliumClusterwideNetworkPolicy, which can match on HTTP path, gRPC service, Kafka topic, and DNS hostname, and which use Cilium's identity model instead of pod IPs. This matters because pod IPs are ephemeral — basing policy on stable workload identity (a label set) is sturdier.
For sovereign deployments needing pod-to-pod mTLS, Cilium's transparent encryption (WireGuard or IPsec) layers cleanly with NetworkPolicy: the policy decides allowed flows, the encryption protects them on the wire.
Default to Cilium for new clusters unless you have a specific reason otherwise. The eBPF data plane, L7 policy support, and Hubble observability are a meaningful upgrade over iptables-based CNIs.
Patterns for Sovereign Multi-Tenant Clusters#
- Default-deny baseline — apply a `deny-all` NetworkPolicy in every tenant namespace, then add specific allow rules.
- Namespace isolation — block cross-namespace pod-to-pod traffic except through known service entry points.
- Egress controls — restrict tenant egress to a known set of CIDRs (gateway, S3, model registry) so a compromised pod cannot exfiltrate.
- L7 allow-lists — for tenants calling shared LLM endpoints, allow only specific HTTP paths and methods.
- Audit — Cilium Hubble or Calico Whisker provides flow logs feeding the SIEM.
Common Mistakes#
Three failure modes recur: forgetting that policy applies only after a policy selects the pod (so an empty policy is not a deny), forgetting that DNS resolution to kube-dns must be allowed in egress policies (or pods cannot resolve services), and assuming the default CNI enforces policies (kindnet and flannel do not). Run policy assertion tests in CI — Cilium ships `cilium connectivity test`, Calico ships `calicoctl audit` — and verify in a staging cluster before applying to production.
References
- Kubernetes NetworkPolicy · Kubernetes Docs
- Cilium Network Policy · Cilium Project
- Calico Network Policy · Tigera