Skip to content
C Codeloom
Kubernetes

Kubernetes RBAC Cheatsheet: Roles, Bindings, and Service Accounts

A concise tour of Kubernetes RBAC: roles vs cluster roles, bindings, service accounts, and patterns that scale without becoming a permissions zoo.

·4 min read · By Codeloom
Intermediate 10 min read

What you'll learn

  • Roles vs ClusterRoles
  • Bindings vs ClusterBindings
  • Service accounts and tokens
  • Aggregated cluster roles
  • Auditing who can do what

Prerequisites

  • Familiar with terminals and YAML

What and Why

Kubernetes RBAC governs who can do what against the API server. It is built from four object types: Role, ClusterRole, RoleBinding, and ClusterRoleBinding. Master them and you can grant exactly the permissions a team or controller needs and no more.

Bad RBAC leads to two failure modes: too tight, and developers cannot ship; too loose, and a compromised pod can read every secret in the cluster. The cheatsheet here is the minimum vocabulary you need to avoid both.

Mental Model

Subject (User / Group / ServiceAccount)
      |
      v
 RoleBinding ----- references -----> Role          (namespace scoped)
 ClusterRoleBinding ----------------> ClusterRole  (cluster scoped)
                                           |
                                           v
                                   rules: verbs on resources
Subjects, bindings, and rules

Two key facts:

  1. A RoleBinding can reference a ClusterRole. This is how you grant a common set of permissions inside a single namespace without duplicating rules.
  2. Permissions are additive only. There is no deny rule. To revoke, you remove the binding.

Hands-on Example

Let a CI service account deploy into the web namespace but nothing else.

apiVersion: v1
kind: ServiceAccount
metadata: { name: ci-deployer, namespace: web }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: deployer, namespace: web }
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets"]
    verbs: ["get","list","watch","create","update","patch"]
  - apiGroups: [""]
    resources: ["pods","services","configmaps"]
    verbs: ["get","list","watch","create","update","patch","delete"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: { name: deployer-binding, namespace: web }
subjects:
  - kind: ServiceAccount
    name: ci-deployer
    namespace: web
roleRef:
  kind: Role
  name: deployer
  apiGroup: rbac.authorization.k8s.io

To get a token for CI:

kubectl -n web create token ci-deployer --duration=1h

Verify with the dry-run permission check:

kubectl auth can-i create deployments \
  --as=system:serviceaccount:web:ci-deployer -n web   # yes
kubectl auth can-i delete secrets \
  --as=system:serviceaccount:web:ci-deployer -n web   # no

For a cluster-wide read-only role for SREs, define an aggregated ClusterRole:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: sre-read
  labels: { rbac.example.com/aggregate-to-sre: "true" }
rules:
  - apiGroups: ["", "apps", "batch"]
    resources: ["*"]
    verbs: ["get","list","watch"]

Common Pitfalls

  • Using cluster-admin for everything. It is a backdoor. Audit any binding that references it and replace with narrower roles.
  • Wildcard verbs and resources. verbs: ["*"] on resources: ["*"] defeats the point of RBAC. Be specific.
  • Forgetting subresources. pods/exec and pods/portforward are separate. Granting pods does not let you exec into them - and granting exec is often unsafe.
  • Reusing a service account across workloads. When something gets compromised, blast radius is everything it could touch. One service account per workload.
  • Manually managed tokens. Long-lived secrets sitting in CI. Prefer projected tokens via kubectl create token or OIDC trust to your CI.

Production Tips

  • Treat RBAC as code. Keep it in Git, review changes, and apply via GitOps so a privilege bump leaves a trail.
  • Use namespace-per-team plus a small team-developer ClusterRole bound by RoleBinding into each team’s namespace. New teams get a copy-paste.
  • Run kubectl-who-can or rakkess periodically to audit who has dangerous verbs (escalate, bind, impersonate, secrets.get).
  • For workloads that need cloud permissions, bind the service account to an IAM role via IRSA (EKS) or Workload Identity (GKE) rather than embedding cloud keys.
  • Enable the audit log with a policy that records all RoleBinding and ClusterRoleBinding changes. You will want this when something goes wrong.

Wrap-up

RBAC is small in object count but large in consequence. Memorize the four objects, prefer namespace-scoped roles, lean on ClusterRole plus RoleBinding for reuse, and bind service accounts one-per-workload. Audit dangerous verbs regularly and treat any cluster-admin reference as a yellow flag. Done well, RBAC becomes a quiet safety net rather than the source of midnight pages.