Container security in a managed Kubernetes service
Choosing a managed Kubernetes service transfers the control plane and almost nothing that gets clusters compromised. The provider runs and patches the API server, the scheduler and the key-value store behind them, which removes real operational risk. Access control inside the cluster, what a pod is allowed to do to its host, which cloud permissions a workload inherits, and whether the cluster is still on a supported version all remain yours. Those four are where incidents come from.
What does a managed control plane actually cover?
The components you never see. The provider operates the API server, the scheduler, the controller manager and the key-value store, patches them, and generally encrypts the datastore at rest with a provider-managed key. That is a genuine reduction in work, and it removes a category of failure that self-managed clusters spend real effort on.
Control plane availability across zones is not part of that deal everywhere, because on two of the three providers it turns on a choice you made. EKS runs the control plane across multiple Availability Zones. On GKE it depends on the cluster type: a regional cluster replicates the control plane across zones, while a zonal cluster runs a single replica in one zone and has no API server during a control plane upgrade. On AKS it depends on the tier: the Free tier is neither zone-redundant nor covered by a financially backed SLA, and zone-redundant API server availability requires Standard or Premium. Check which of those you have before you count control plane uptime as someone else's problem.
Everything expressed as cluster configuration remains with you, and the list is longer than teams expect: role bindings, service accounts, network policy, admission control, pod security settings, secret handling, the container images you run and where they came from, the identity your pods hold in the cloud account, and node-level configuration on any node pool you manage. The provider will not narrow a role binding or refuse a privileged pod on your behalf.
Node patching sits in between and deserves a specific answer rather than an assumption. Managed services offer automatic node image upgrades and release channels, and if you have enabled them the provider replaces nodes on a schedule you selected. If you have not, or if you have pinned a node image for compatibility, the operating system on your nodes is yours to patch, and pinning is common enough to be worth checking.
| Layer | Provider | You | Common failure |
|---|---|---|---|
| API server and scheduler | Runs and patches | Decide its network exposure | Endpoint reachable from anywhere |
| Cluster datastore encryption | Encrypted with a managed key | Choose your own key if required | Assuming this covers Kubernetes Secrets access |
| Node operating system | Supplies images, upgrades if enabled | Enable upgrades, or patch yourself | Node image pinned for compatibility, then forgotten |
| Role bindings and service accounts | Nothing | All of it | A service account bound to cluster administrator |
| Network policy | Provides a capable network plugin | Write the policies | No policy at all, so every pod reaches every pod |
| Admission control | Supports the mechanism | Choose and enforce the policies | Enabled in audit mode and never enforced |
| Workload cloud identity | Provides the federation mechanism | Bind roles per service account | Pods inherit the node's broader role |
| Cluster version | Offers upgrades and a support window | Actually upgrade | Falls out of support, then upgrades in a rush |
Which cluster misconfigurations get exploited?
A short and consistent list. An API server endpoint reachable from the public internet combined with permissive role bindings, which turns any leaked token into cluster access. Dashboards or add-ons exposed without authentication. Service accounts bound to cluster-wide administrative roles because a chart's default asked for it and nobody narrowed it afterwards. Pods running privileged, or mounting the host filesystem, or sharing the host network namespace, each of which reduces the container boundary to a formality.
Then the quieter ones. Service account tokens mounted into every pod by default, so an application that never calls the Kubernetes API still carries a credential for it. Secrets exposed as environment variables, readable by anyone who can open a shell in the pod or read a crash dump. And the absence of any network policy, which is the default on most clusters and means a compromised pod can reach every service in the cluster including the ones with no business relationship to it.
The pattern behind the list is that Kubernetes defaults favour working over restricting, which is the correct choice for a general-purpose platform and means the secure configuration is always something you added. Assume nothing is restricted unless you can point at the manifest that restricts it.
How does cluster identity turn into cloud identity?
Through one of two mechanisms, and the difference between them determines what a container compromise costs you. The naive arrangement lets pods use the node's own cloud identity, which is shared by every pod on that node and generally holds whatever permissions the node pool needed for any workload scheduled to it. A single compromised container then holds the union of those permissions.
The correct arrangement is workload identity federation, where a Kubernetes service account is associated with a cloud role and the pod exchanges a projected, short-lived, audience-scoped token for cloud credentials. Every major managed service provides this. The result is per-service-account permissions, short-lived credentials, no key material, and an audit trail that names the workload rather than the node.
There is a consequence people miss, and it changes how you think about namespace administration. If a cloud role trusts a service account in a namespace, then anyone who can create a pod in that namespace can obtain that role, because they can schedule a pod using that service account. The ability to deploy in a namespace is therefore equivalent to holding the cloud permissions bound to it, which means role bindings that permit pod creation are cloud permission grants and should be reviewed as such.
What does admission control buy, and how does it break things?
It is the only control that prevents a bad workload from existing, rather than reporting it afterwards. Pod Security Admission, which replaced the removed pod security policy mechanism, applies a baseline or restricted profile per namespace and rejects pods that ask for privileges the profile forbids. Policy engines go further and let you require resource limits, forbid host mounts, insist on non-root users, mandate approved registries or verify image signatures before anything runs.
The failure mode is operational rather than security-related. An admission webhook that must be consulted before every creation becomes part of your availability story, and a policy engine that is unavailable while configured to fail closed will block every deployment in the cluster, including the deployment that would fix it. Understand the failure policy on every webhook you install, keep the engine highly available, and know how to bypass it under an incident.
The rollout that works is gradual and per namespace. Run in audit or warn mode first and collect what would have been rejected, since the answer is usually several existing production workloads. Fix or exempt those explicitly, enforce on new namespaces, then enforce on existing ones one at a time. Teams that enable enforcement cluster-wide on a Friday learn the same lesson every time.
What has to keep happening after deployment?
Upgrades, which is the container security control most consistently skipped and the one that quietly matters most. Kubernetes produces roughly three minor releases a year, community patch support for any given minor version lasts a little over a year, and managed providers offer extended support at a higher price for a period beyond that. Falling out of support means no security patches, then a rushed multi-version upgrade under pressure, which is where outages happen.
Then node image freshness, which does for the operating system layer what image rebuilds do for your application images: most vulnerability findings on a node clear when the node is replaced with a current image, so an automated replacement cadence removes more risk than reading the findings would. The same logic applies to your own images, and a freshness target is a better objective than a finding count because you control it.
Alongside those, three recurring reviews. Role bindings, because charts and helpful colleagues add broad ones and nothing removes them. Admission policy exemptions, which should expire so that each is re-decided cheaply rather than becoming permanent by default. And whoever owns triage for scanner output, because a container security platform that nobody reads is the most common state for these tools six months after purchase, and that is a staffing decision rather than a product one.
What can you test this week?
Four commands and one question. Check whether your API server endpoint answers from outside your network, since every managed service offers a private endpoint and a public one should be a deliberate decision. List every binding to a cluster-wide administrative role and ask what breaks if each is narrowed. Then, from inside an ordinary application pod, enumerate what its own service account is permitted to do, which the Kubernetes client can report directly.
Next, from that same pod, try to reach the node metadata endpoint and retrieve cloud credentials. If it succeeds, your pods hold the node's permissions regardless of what workload identity is configured elsewhere, and blocking that path is the single highest-value change available in a managed cluster.
The question is about versions: which version is each cluster on, when does support end, and who is accountable for the upgrade. If nobody can answer, the upgrade will happen late, and the version you run when an urgent patch lands decides how hard that week is.
Common questions
- What does a managed Kubernetes service secure for you?
- The control plane: the API server, scheduler, controller manager and the cluster datastore, including their patching, with the datastore encrypted at rest under a provider-managed key. Availability across zones is not automatic on every provider. EKS control planes span multiple Availability Zones, GKE replicates the control plane only on a regional cluster, and AKS offers zone-redundant API server availability and a financially backed SLA only on the Standard or Premium tier. Everything expressed as cluster configuration stays with you, including role bindings, network policy, admission control, pod privileges, secret handling, image provenance and the cloud permissions your pods hold. Node patching depends on whether you enabled automatic node upgrades.
- Why is workload identity better than using the node's role?
- Because the node's cloud identity is shared by every pod scheduled to it and usually holds the union of permissions any of those workloads needed, so one compromised container inherits all of them. Workload identity federation binds a Kubernetes service account to a specific cloud role, exchanging a short-lived projected token for credentials. That gives per-workload permissions, no key material, and an audit trail naming the workload rather than the node.
- Does creating a pod in a namespace grant cloud permissions?
- Effectively yes, if a cloud role trusts a service account in that namespace. Anyone who can create a pod can schedule it with that service account and obtain the role. This means role bindings that allow pod creation are cloud permission grants and should be reviewed with the same care as cloud policy. It is also why namespaces holding sensitive workload identities need tighter deployment permissions.
- What is Pod Security Admission and do we need a policy engine too?
- Pod Security Admission is built into Kubernetes and applies a baseline or restricted profile per namespace, rejecting pods that request forbidden privileges. It replaced the removed pod security policy mechanism. A separate policy engine is worth adding when you need rules it does not cover, such as requiring resource limits, restricting registries, mandating labels or verifying image signatures before admission.
- Can admission control cause an outage?
- Yes. An admission webhook is consulted before resources are created, so if the policy engine is unavailable and configured to fail closed, every deployment in the cluster is blocked, including the one that would fix it. Check the failure policy of every webhook you install, run the engine with redundancy, and document how to bypass it during an incident. Roll enforcement out namespace by namespace after a period in audit mode.
- Why do Kubernetes upgrades matter as a security control?
- Because a version outside its support window receives no security patches. Kubernetes ships roughly three minor releases a year, community patch support for a minor version lasts a little over a year, and managed providers sell extended support beyond that at a higher price. Clusters that drift out of support end up upgrading several versions at once under pressure, which is when upgrade-related outages occur.