Security: RBAC, Service Accounts & Pod Security Standards
Kubernetes security operates at complementary layers: RBAC governs API access. Service Accounts are the identity a Pod uses when calling the API Server. Security Context controls OS/kernel-level conta
Kubernetes security operates at complementary layers: RBAC governs API access. Service Accounts are the identity a Pod uses when calling the API Server. Security Context controls OS/kernel-level container behavior. Pod Security Standards constrain allowed Security Context settings per namespace.
-
RBAC: Role/ClusterRole define permission sets. RoleBinding/ClusterRoleBinding attach them to subjects. RBAC is purely additive -- no explicit deny.
-
RBAC is the union of every Role/ClusterRole bound to a subject. Anything not explicitly granted is denied by omission.
-
Every Pod runs under a ServiceAccount. A token for that SA is automatically mounted, used to authenticate API calls.
-
Security Context controls: runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation, capabilities drop/add.
-
Pod Security Standards enforced via namespace labels: Privileged (no restrictions), Baseline, Restricted (comprehensive hardening).
-
Create a ServiceAccount for each application that needs to call the Kubernetes API (don't rely on the namespace's default ServiceAccount for anything with real permissions).
-
Define a Role (namespace-scoped) or ClusterRole (cluster-scoped) listing exactly the verbs/resources needed (e.g. get/list/watch on pods).
-
Bind it with a RoleBinding (or ClusterRoleBinding for cluster-wide) connecting the Role to the ServiceAccount (or user/group).
-
Reference the ServiceAccount in the Pod spec's serviceAccountName -- its token is auto-mounted and used for any in-cluster API calls the Pod makes.
-
Set a SecurityContext on the Pod/container (runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation: false, dropped capabilities) to constrain what the container can do at the OS level.
-
Label the namespace with a Pod Security Standard level (privileged/baseline/restricted) so the built-in admission controller enforces or warns on non-compliant Pod specs cluster-wide.
-
A CI/CD controller (like ArgoCD) running under a tightly-scoped ServiceAccount with a ClusterRole limited to exactly the resource types it needs to reconcile, not cluster-admin.
-
A monitoring agent's ServiceAccount granted read-only (get/list/watch) ClusterRole access to Pods/Nodes across the cluster, with no write permissions at all.
-
Enforcing the restricted Pod Security Standard on all application namespaces while leaving a separate, explicitly-labeled namespace at privileged for infrastructure components (CNI, storage drivers) that genuinely need elevated access.
-
Disabling automountServiceAccountToken on Pods that never call the Kubernetes API at all, removing an unnecessary credential from the container entirely.
-
An incident-response review using
kubectl auth can-i --list --as=system:serviceaccount:ns:nameto audit exactly what a compromised ServiceAccount could have accessed.
-
Grant the narrowest Role/ClusterRole that actually satisfies the need -- RBAC is purely additive, so start from nothing and add specific verbs/resources rather than trimming down from a broad grant.
-
Give every application its own dedicated ServiceAccount instead of sharing one across unrelated workloads -- makes audit and blast-radius containment possible.
-
Set automountServiceAccountToken: false on Pods that never call the Kubernetes API, removing a credential that provides no value but is still a potential attack surface.
-
Default to the restricted Pod Security Standard for application namespaces and require an explicit, reviewed exception for anything needing baseline or privileged.
-
Regularly audit ClusterRoleBindings specifically -- cluster-wide grants are the highest-blast-radius mistake and are easy to create accidentally when copy-pasting example YAML.
-
Prefer short-lived, audience-bound tokens (TokenRequest API / projected volume tokens) over the legacy long-lived auto-mounted ServiceAccount token where supported.
-
Binding a ClusterRole with wildcard verbs/resources ('*') to a ServiceAccount 'to get things working,' then never tightening it -- this is functionally cluster-admin and a major blast-radius risk.
-
Letting Pods run under the namespace's default ServiceAccount by omission -- giving it any permissions grants those to any Pod that doesn't specify its own.
-
Assuming RBAC has an explicit deny -- it doesn't; the only way to restrict access already granted by one binding is to remove that binding, not add a 'deny' rule.
-
Setting a namespace's Pod Security Standard to enforce: restricted without first checking existing workloads against it -- legitimately-running Pods can suddenly be rejected on their next rollout.
-
Leaving allowPrivilegeEscalation and privileged unset (defaulting to permissive) rather than explicitly setting them false -- an unset SecurityContext field is not the same as a hardened one.
-
Forgetting that RoleBinding can reference a ClusterRole to grant its permissions scoped to just one namespace -- teams sometimes duplicate ClusterRoles into per-namespace Roles unnecessarily.
-
RBAC authorization checks happen on every API Server request -- with a very large number of Roles/Bindings, authorization lookup can add measurable latency at scale; keep binding counts reasonable and avoid deeply nested group hierarchies where avoidable.
-
Disabling automountServiceAccountToken on Pods that don't need it is a small but real reduction in per-Pod startup work (one fewer Secret volume mount) at cluster scale.
-
Pod Security Standard admission checks run on every Pod creation/update -- using the lighter-weight 'warn' or 'audit' modes during rollout avoids blocking deploys while you find non-compliant workloads.
-
SecurityContext settings like readOnlyRootFilesystem shift some write I/O to explicitly-mounted volumes (e.g. emptyDir) -- plan for that redirected I/O path rather than assuming zero performance impact from hardening.
-
Periodically run an RBAC audit (
kubectl auth can-i --listper ServiceAccount, or a tool like rbac-lookup) as a standing production practice, not a one-time setup step. -
Roll out Pod Security Standards in warn/audit mode first, review violations over a real traffic period, then switch to enforce once workloads are confirmed compliant.
-
Treat any ClusterRoleBinding creation as requiring the same review rigor as a production code change -- it's cluster-wide and easy to under-scope.
-
Rotate and monitor ServiceAccount token usage; an unexpectedly-used token (wrong source IP, unusual API calls) is a strong compromise signal worth alerting on.
-
Create a ServiceAccount, a Role granting only get/list on pods, a RoleBinding connecting them, and confirm with
kubectl auth can-i list pods --as=system:serviceaccount:default:<name>that it can list but not delete. -
Set automountServiceAccountToken: false on a test Pod and confirm no token is mounted at /var/run/secrets/kubernetes.io/serviceaccount.
-
Apply the restricted Pod Security Standard label to a test namespace and try deploying a Pod running as root -- observe the admission rejection.
-
Bind a ClusterRole with cluster-admin-equivalent permissions to a test ServiceAccount, then use
kubectl auth can-i --list --as=system:serviceaccount:ns:nameto see the full resulting access.
-
RBAC (Role/ClusterRole + RoleBinding/ClusterRoleBinding) controls API access -- purely additive, no explicit deny.
-
ServiceAccounts are Pod identities for API calls, distinct from human user identities.
-
Security Context controls OS/kernel-level behavior -- completely independent of RBAC.
-
Pod Security Standards (Privileged/Baseline/Restricted) are namespace-level admission-enforced policy.
Want a visual for this concept?
Generate a diagram tailored to “Security: RBAC, Service Accounts & Pod Security Standards” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →