Kubernetes Role-Based Access Control (RBAC) is the mechanism for controlling which users and service accounts can perform which actions on which resources within a Kubernetes cluster. Without RBAC configuration, all authenticated users (and service accounts in pods) have full admin access — a significant security risk in multi-team environments. RBAC uses four resource types: Role (defines permissions within a namespace), ClusterRole (defines permissions cluster-wide or used as a template), RoleBinding (grants a Role to a user/group/service account in a namespace), and ClusterRoleBinding (grants a ClusterRole cluster-wide). This guide covers configuring RBAC on RHEL 9 Kubernetes to implement least-privilege access for developers, CI/CD service accounts, and read-only operators.

Prerequisites

  • Kubernetes cluster running on RHEL 9 with RBAC enabled (enabled by default since Kubernetes 1.8)

Step 1 — View Current RBAC Configuration

# Check if RBAC is enabled
kubectl api-versions | grep rbac

# View existing ClusterRoles
kubectl get clusterroles | grep -v system:

# View existing RoleBindings in a namespace
kubectl get rolebindings -n myapp

Step 2 — Developer Role (Namespace-Scoped)

# /tmp/developer-rbac.yaml
# Role: allows developers to manage deployments and view pods
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: myapp
  name: developer
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "pods/log", "services", "configmaps"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]  # Allows kubectl exec into pods
---
# Bind the role to a user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
  namespace: myapp
subjects:
- kind: User
  name: jane.developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f /tmp/developer-rbac.yaml

Step 3 — CI/CD Service Account

# Create a service account for CI/CD pipeline
kubectl create serviceaccount cicd-deployer -n myapp

# Grant permission to update deployment images only
kubectl create role deployment-updater 
    --verb=get,patch,update 
    --resource=deployments 
    -n myapp

kubectl create rolebinding cicd-deployer-binding 
    --role=deployment-updater 
    --serviceaccount=myapp:cicd-deployer 
    -n myapp

# Get the service account token for CI/CD pipelines
kubectl create token cicd-deployer -n myapp --duration=8760h

Step 4 — Read-Only Cluster Viewer

# Use the built-in ClusterRole "view" for read-only access
kubectl create clusterrolebinding ops-viewer 
    --clusterrole=view 
    --user=ops-team-user

# Verify what a user can do
kubectl auth can-i list pods --namespace myapp --as jane.developer
kubectl auth can-i delete deployments --namespace myapp --as jane.developer

Conclusion

Kubernetes RBAC on RHEL 9 follows the principle of least privilege — grant only the permissions required for each role and no more. The most important patterns are: use namespace-scoped Roles (not ClusterRoles) for application teams so their permissions are limited to their namespace; create dedicated ServiceAccounts with minimal permissions for CI/CD pipelines rather than using admin tokens; and use the built-in view, edit, and admin ClusterRoles as the starting point for custom RoleBindings rather than creating all permissions from scratch.

Next steps: How to Deploy Applications to Kubernetes on RHEL 9, How to Install ArgoCD on RHEL 9, and How to Monitor Kubernetes with Prometheus on RHEL 9.