Skip to content
UNRESOVED

Kubernetes Security

Multi-Layered Hardening for Kubernetes: Why Each Layer Has to Be Tested on Its Own Terms

Defense in depth is usually described as a stack of layers. In practice it behaves more like six separate disciplines that happen to share a cluster, each with its own failure modes.

Hope Akpabio·17 September 2026·7 min read

Kubernetes · Security · Defense in Depth · Fundamentals

The assumption

"Defense in depth" is usually drawn as a stack: perimeter at the bottom, identity above it, network policy above that, workload configuration, supply chain, runtime detection, each layer sitting on top of the one before it like a wall built brick by brick. The image is reassuring because it implies redundancy. If one brick cracks, the others are still standing.

This was the working model behind most of the Kubernetes hardening research I did for my dissertation, and it took a fair amount of hands-on cluster testing to unlearn it. The layers in a real cluster are not stacked. They are closer to six separate disciplines that happen to share the same cluster and the same YAML files, each with its own threat model, its own failure modes, and almost no ability to compensate for a gap in any of the others.

The key idea

Defense in depth is not a stack where each layer backstops the one above it. It is six largely independent disciplines, and a cluster can be hardened at five of them while remaining completely exposed at the sixth.

The problem with the stack metaphor

A stack implies that if the top layer fails, the layer beneath it catches the fall. That is a reasonable description of how a network firewall and a host firewall interact: redundant controls, similar threat model, meaningful overlap. It is a poor description of how Kubernetes' security surfaces relate to each other.

Consider a cluster with excellent Pod Security Standards enforcement (nothing privileged, no host namespace access, mandatory non-root) and completely flat RBAC (every service account can read every secret in every namespace). The workload layer is hardened. The identity layer is not. A compromised pod cannot escalate to the node, because Pod Security Standards did its job, but it can read every credential in the cluster, because RBAC never did. The workload layer's strength provided zero compensation for the identity layer's weakness. They were never stacked. They were parallel.

This is the pattern that shows up across the K8s security experiments elsewhere on this site: a strong perimeter control says nothing about RBAC scope; a correct admission policy says nothing about audit visibility; a managed control plane says nothing about workload configuration. Multi-layered hardening only works as intended if each layer is actually tested against its own specific failure modes, not assumed to be covered because a neighboring layer looks strong.

The six layers, tested separately

1. Control plane and cluster configuration. This is the layer most hardening guides start with: API server flags, etcd encryption at rest, audit logging scope, kubelet authentication. The CIS Kubernetes Benchmark and the NSA/CISA hardening guidance both treat this as foundational, and it is, but it is also the layer most affected by whether you run a managed or self-managed control plane. On managed Kubernetes, most of this is handled for you. The mistake is assuming that means the layer is fully covered. Audit log scope and retention is frequently still the operator's decision even on a fully managed control plane, and it is exactly the kind of setting that determines whether an incident three months from now is reconstructable at all.

2. Identity and access. RBAC, service account scoping, and (where relevant) integration with an external identity provider. The single most common failure here is not a missing Role, it is a ClusterRoleBinding created early in a project's life for convenience and never revisited. A quick audit worth running on any cluster:

kubectl get clusterrolebindings -o json | \
  jq -r '.items[] | select(.roleRef.name=="cluster-admin") |
  .subjects[]?.name' | sort -u

Anything returned here that is not a small, deliberate list of human administrators is worth a second look. Service accounts with cluster-admin are a common finding, usually inherited from a Helm chart's default RBAC template rather than chosen on purpose.

3. Network segmentation. Kubernetes networking is flat by default. Every pod can reach every other pod across every namespace unless a NetworkPolicy says otherwise, and a NetworkPolicy with a subtly wrong selector can silently fail to enforce anything while still reporting as present and healthy, as tested directly in an earlier experiment. A service mesh with mutual TLS adds real value here, but it answers a different question (is this traffic authenticated and encrypted) than a NetworkPolicy does (should this traffic be permitted to exist at all), and hardening one is not a substitute for the other.

4. Workload and pod security. Pod Security Standards (or the admission controller enforcing them), seccomp profiles, read-only root filesystems, dropped Linux capabilities, mandatory non-root execution. This is the layer with the clearest, most mechanical checklist, which is precisely why it tends to get the most attention relative to its actual share of real-world incidents. A pod that cannot run as root and cannot mount the host filesystem is meaningfully safer, but it is not automatically safer at the identity or network layers, which is the parallel-not-stacked point again.

5. Supply chain. Image provenance, vulnerability scanning, signature verification, and admission-time enforcement of all three (Kyverno and OPA Gatekeeper are the common choices for the enforcement step). The dissertation research this article draws on spent real time here specifically because supply chain hardening is the layer most often implemented as a scanning report nobody reads rather than an enforced gate. A vulnerability scanner that produces a report is observability. A vulnerability scanner wired into an admission controller that blocks the deploy is enforcement. Only the second one is actually hardening.

6. Runtime detection. Falco, eBPF-based monitoring, or an equivalent, watching for anomalous process behavior, unexpected network connections, or file access patterns that indicate a workload has already been compromised despite the first five layers. This is the layer most often skipped entirely, usually because it is the least mechanical to implement and the hardest to validate without a real incident. It is also the layer that answers the question every other layer leaves open: what happens after something gets through anyway.

What changed my mind about testing this way

Treating these as one hardening project, executed once against a checklist, produces clusters that look complete and behave unevenly. Treating them as six separate disciplines, each requiring its own test plan, its own failure-mode analysis, and its own periodic re-verification, is slower and less satisfying to report on, but it is the only version that survives contact with an actual incident. A CIS Benchmark score does not tell you whether your NetworkPolicy selectors are correct. A green Pod Security Standards audit does not tell you whether your RBAC is scoped. Each layer has to be interrogated on its own terms, with its own specific test, because passing one tells you almost nothing about the others.

You might disagree

The strongest objection to this framing is practical: most teams do not have the resources to run six independent hardening disciplines with six independent test plans, and a checklist, imperfect as it is, at least ensures every layer gets some attention rather than the team's limited time concentrating entirely on whichever layer is most interesting or most visible. Six thorough layers is the ideal. Six superficial checkbox passes across every layer might, in practice, catch more real misconfigurations than one deeply tested layer and five untouched ones.

That is a fair prioritization argument, and for a small team, doing all six layers superficially is often the right call. But it is an argument about sequencing and resourcing, not about whether the layers actually reinforce each other. Even under a checklist-first approach, the checklist should be read as six separate pass/fail results, not one aggregate "hardened" status, precisely because a five-out-of-six average hides which one thing an attacker would actually find.

What I think now

I no longer describe a cluster as "hardened" as a single adjective. I describe it by layer: control plane configuration is strong, identity is weak, network segmentation is untested, workload security is strong, supply chain enforcement exists but isn't gating deploys, runtime detection is absent. That sentence is longer and less quotable than "the cluster is hardened," and it is also the only version that is actually true, because it is the only version that reflects that these six things were tested independently rather than assumed to travel together.

The takeaway

Multi-layered hardening is not a stack where strength in one layer compensates for weakness in another. It is six disciplines, control plane, identity, network, workload, supply chain, and runtime, that share infrastructure but not failure modes. A cluster's actual security posture is the weakest of the six, not the average, and the only way to know which one that is happens to be the same method this entire publication keeps returning to: test each layer on its own terms rather than trusting that a checklist completed once means the layer stays covered.

Join the conversation

Have a different perspective? Continue the discussion.

Discuss on LinkedIn