Skip to content

RBAC Examples

Practical examples of Kubernetes Role-Based Access Control (RBAC) configurations.

Core Concepts

Resource Scope Description
Role Namespace Grants permissions within a single namespace
ClusterRole Cluster-wide Grants permissions across all namespaces or for cluster-scoped resources
RoleBinding Namespace Binds a Role or ClusterRole to subjects within a namespace
ClusterRoleBinding Cluster-wide Binds a ClusterRole to subjects across the entire cluster

Roles

Read-Only Role (Namespace)

Allows viewing all common resources in a namespace without modification.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: read-only
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "endpoints", "configmaps", "persistentvolumeclaims"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["batch"]
    resources: ["jobs", "cronjobs"]
    verbs: ["get", "list", "watch"]

Developer Role (Namespace)

Allows developers to manage application workloads but not cluster-level resources.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: my-app
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log", "pods/exec", "services", "endpoints", "configmaps"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets", "statefulsets"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]           # Read secrets but not create/modify
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["get", "list", "watch", "create", "delete"]

CI/CD Deployment Role (Namespace)

Allows a pipeline to deploy and update applications.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cicd-deployer
  namespace: production
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets"]
    verbs: ["get", "list", "watch", "update", "patch"]
  - apiGroups: [""]
    resources: ["services", "configmaps"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

ClusterRoles

Cluster Read-Only

Allows viewing all resources across all namespaces and cluster-scoped resources.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-read-only
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["get", "list", "watch"]
  - nonResourceURLs: ["*"]
    verbs: ["get"]

Namespace Admin

Full control over a namespace's resources (used as a ClusterRole scoped via RoleBinding).

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: namespace-admin
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
  # Excludes cluster-scoped resources — these are only accessible
  # when bound with a RoleBinding to a specific namespace

Metrics Reader

Allows reading metrics from pods and nodes (used by HPA, monitoring tools).

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: metrics-reader
rules:
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list"]

Custom Resource Definition Manager

Allows managing CRDs and their instances.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: crd-manager
rules:
  - apiGroups: ["apiextensions.k8s.io"]
    resources: ["customresourcedefinitions"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

RoleBindings

Bind a User to a Role

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-developer
  namespace: my-app
subjects:
  - kind: User
    name: alice@example.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Bind a Group to a Role

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: frontend-team-read
  namespace: frontend
subjects:
  - kind: Group
    name: frontend-engineers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: read-only
  apiGroup: rbac.authorization.k8s.io

Bind a ServiceAccount to a Role

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cicd-deployer-binding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: cicd-bot
    namespace: cicd
roleRef:
  kind: Role
  name: cicd-deployer
  apiGroup: rbac.authorization.k8s.io

Bind a ClusterRole to a Namespace (Scoped)

# Grants cluster-read-only permissions scoped only to the 'staging' namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ops-read-staging
  namespace: staging
subjects:
  - kind: Group
    name: ops-team
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole           # ClusterRole scoped to this namespace
  name: cluster-read-only
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBindings

Bind a User to Cluster-Wide Read

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: bob-cluster-viewer
subjects:
  - kind: User
    name: bob@example.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-read-only
  apiGroup: rbac.authorization.k8s.io

Bind a ServiceAccount to Cluster Admin (use sparingly)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: flux-cluster-admin
subjects:
  - kind: ServiceAccount
    name: flux
    namespace: flux-system
roleRef:
  kind: ClusterRole
  name: cluster-admin             # Built-in full admin role
  apiGroup: rbac.authorization.k8s.io

ServiceAccounts

Create a ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: default
automountServiceAccountToken: false   # Opt-in rather than auto-mount

Reference in a Pod/Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      serviceAccountName: my-app    # Use the named ServiceAccount
      automountServiceAccountToken: false
      containers:
        - name: app
          image: my-app:latest

Multi-Tenant Namespace Isolation

Full example of isolating two teams in separate namespaces.

# --- Namespaces ---
apiVersion: v1
kind: Namespace
metadata:
  name: team-alpha
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-beta

---
# --- ServiceAccounts ---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: alpha-deployer
  namespace: team-alpha
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: beta-deployer
  namespace: team-beta

---
# --- Roles (one per namespace) ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: team-deploy
  namespace: team-alpha
rules:
  - apiGroups: ["", "apps", "batch", "networking.k8s.io"]
    resources:
      - pods
      - services
      - deployments
      - statefulsets
      - ingresses
      - configmaps
      - jobs
    verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: team-deploy
  namespace: team-beta
rules:
  - apiGroups: ["", "apps", "batch", "networking.k8s.io"]
    resources:
      - pods
      - services
      - deployments
      - statefulsets
      - ingresses
      - configmaps
      - jobs
    verbs: ["*"]

---
# --- RoleBindings ---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alpha-deployer-binding
  namespace: team-alpha
subjects:
  - kind: ServiceAccount
    name: alpha-deployer
    namespace: team-alpha
  - kind: Group
    name: team-alpha-engineers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: team-deploy
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: beta-deployer-binding
  namespace: team-beta
subjects:
  - kind: ServiceAccount
    name: beta-deployer
    namespace: team-beta
  - kind: Group
    name: team-beta-engineers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: team-deploy
  apiGroup: rbac.authorization.k8s.io

Debugging RBAC

# Check if a user can perform an action
kubectl auth can-i get pods --namespace default --as alice@example.com
kubectl auth can-i delete deployments --namespace production --as bob@example.com

# Check all permissions for a user in a namespace
kubectl auth can-i --list --namespace default --as alice@example.com

# Check permissions for a ServiceAccount
kubectl auth can-i get pods --as=system:serviceaccount:default:my-app

# Describe a Role or ClusterRole
kubectl describe role developer -n my-app
kubectl describe clusterrole cluster-read-only

# List RoleBindings for a namespace
kubectl get rolebindings -n my-app
kubectl describe rolebinding alice-developer -n my-app

# List ClusterRoleBindings
kubectl get clusterrolebindings

Built-In ClusterRoles

ClusterRole Description
cluster-admin Full cluster control (use sparingly)
admin Namespace admin with read/write, but no node/quota control
edit Read/write to most namespace resources, no role management
view Read-only access to most namespace resources
system:node Used by kubelets
system:kube-scheduler Used by the scheduler
system:kube-controller-manager Used by controller manager

Common Verbs

Verb HTTP Method Description
get GET Retrieve a single resource
list GET List resources
watch GET (streaming) Watch for changes
create POST Create a resource
update PUT Replace a resource
patch PATCH Partially modify a resource
delete DELETE Delete a resource
deletecollection DELETE Delete a collection of resources
impersonate POST Act as another user
bind POST Bind roles (for creating RoleBindings)
escalate POST Modify roles to grant higher permissions

Use "*" as a wildcard to allow all verbs or all resources in a rule.