From Packets to Identity: How Cilium Rewrites Kubernetes Security
Why networking performance was just the beginning

The Hidden Problem After Fixing Latency
After replacing kube-proxy with Cilium’s eBPF dataplane, the cluster felt smooth. No CPU spikes. No rollout-induced latency cliffs. No iptables during incidents.
But something else became obvious once the noise disappeared. Networking wasn’t the real problem anymore. Security and trust boundaries were.
Because even though traffic was fast, it was still governed by the same old idea:
“If your IP is allowed, you’re trusted.”
And in Kubernetes, that’s a recipe for disaster.
Why IP-Based Security Breaks in Kubernetes
Kubernetes is dynamic. Workloads move, pods die, IPs change. Most network policies still rely on IPs—static, unchanging, predictable. But Kubernetes isn’t static.
Here’s how Kubernetes breaks traditional IP-based security:
IPs are reused aggressively.
Sidecars inject themselves silently.
Services reshuffle endpoints every deployment.
Workloads spin up and down constantly.
During one rollout, we noticed something unsettling: a newly started pod briefly inherited an IP that previously belonged to a privileged workload.
For a few milliseconds, the network trusted the wrong thing.
Nothing broke. But it could have.
That’s when Cilium stopped being “just faster networking.”
Identity Over IP: Cilium’s Real Superpower
Cilium doesn’t ask:
“Where is this packet coming from?”
It asks:
“Who is sending this?”
Every pod is assigned a cryptographically derived identity based on:
Namespace
Labels
Service account
This identity is enforced inside the kernel, attached to the packet itself via eBPF metadata.
So instead of:
10.244.1.23 → 10.244.2.87
The kernel sees:
frontend:app=web → backend:app=api
No kube-proxy. No iptables. No sidecar. No race condition.
Just identity.
Policies That Move With Pods
With CiliumNetworkPolicy, rules stop chasing IPs. They describe intent.
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
Now watch what happens during a rollout:
Pods die → identities revoked instantly.
New pods start → identities applied before first packet.
No stale rules.
No update storms.
No “eventual consistency” gaps.
The policy doesn’t care where the pod runs. It follows the workload.
This is what Zero Trust actually looks like in Kubernetes.
Observability That Finally Tells the Truth
Before Cilium, debugging meant digging through logs, conntrack tables, and iptables counters.
Now, it’s different:
hubble observe --from-label app=frontend --to-label app=backend
You see:
Who talked to whom.
Which policy allowed or denied it.
Latency per request.
Drops with exact reasons.
Not logs after the fact. Truth at packet time.
This changes how incidents feel. They stop being mysteries.
A Production Incident That Didn’t Happen
One evening, an unexpected pod tried to access a sensitive internal API.
Before Cilium:
The IP was “allowed.”
The request would’ve gone through.
The alert would come later.
With Cilium:
The packet was dropped in-kernel.
The identity didn’t match policy.
Hubble showed it instantly.
No outage. No fire drill. No postmortem.
Just a quiet drop and a clean audit trail.
Compliance, Audit, and Zero Trust Reality
Here’s the uncomfortable truth: Most “Zero Trust Kubernetes” setups aren’t zero trust at all.
They rely on:
L7 proxies.
Sidecars.
Policy engines outside the dataplane.
Cilium enforces trust:
At L3–L7.
In the Linux kernel.
Before packets hit user space.
This matters for:
SOC 2.
ISO 27001.
PCI-DSS.
Internal security reviews.
Because enforcement is:
Deterministic.
Auditable.
Non-bypassable.
No sidecar crash can weaken it.
Conclusion
The first blog was about performance. This one is about correctness.
Cilium didn’t just make Kubernetes networking faster. It made it honest.
Traffic is identified, not assumed.
Policies express intent, not infrastructure.
Observability explains reality, not symptoms.
Once you experience identity-based networking, going back to IPs feels like debugging with candles.



