In this episode, we'll discuss Kubernetes RBAC (Role-Based Access Control) and RoleBinding for authorization. We'll learn about Roles, ClusterRoles, RoleBindings, ClusterRoleBindings, and best practices for implementing fine-grained access control.

Note
If you want to read the previous episode, you can click the Episode 32 thumbnail below
In the previous episode, we learned about ServiceAccount which provides identity for Pods. In episode 33, we'll discuss RBAC (Role-Based Access Control) and RoleBinding, which control what authenticated users and ServiceAccounts can do in the cluster.
Note: Here I'll be using a Kubernetes Cluster installed through K3s.
Authentication answers "who are you?" (ServiceAccount), while authorization answers "what can you do?" (RBAC). RBAC enables fine-grained access control, allowing you to grant specific permissions to users and applications based on the principle of least privilege.
RBAC (Role-Based Access Control) is Kubernetes' authorization mechanism that regulates access to cluster resources based on roles assigned to users or ServiceAccounts.
Think of RBAC like building security - your badge (ServiceAccount) identifies you, but RBAC determines which floors you can access, which doors you can open, and what actions you can perform in each room.
Key RBAC components:
RBAC IllustrationRole defines permissions within a specific namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]Characteristics:
ClusterRole defines permissions cluster-wide or for cluster-scoped resources.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]Characteristics:
RoleBinding grants Role permissions to subjects within a namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: ServiceAccount
name: my-app-sa
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioCharacteristics:
ClusterRoleBinding grants ClusterRole permissions cluster-wide.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-nodes
subjects:
- kind: ServiceAccount
name: monitoring-sa
namespace: monitoring
roleRef:
kind: ClusterRole
name: node-reader
apiGroup: rbac.authorization.k8s.ioCharacteristics:
Kubernetes resources belong to API groups:
rules:
# Core API group (empty string)
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
# apps API group
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
# rbac.authorization.k8s.io API group
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "rolebindings"]Kubernetes objects that can be accessed:
resources:
- "pods"
- "services"
- "deployments"
- "configmaps"
- "secrets"
- "persistentvolumeclaims"Restrict access to specific resource instances:
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["app-config", "app-secrets"]
verbs: ["get", "update"]Actions that can be performed:
verbs:
- "get" # Read single resource
- "list" # List resources
- "watch" # Watch for changes
- "create" # Create new resource
- "update" # Update existing resource
- "patch" # Partially update resource
- "delete" # Delete resource
- "deletecollection" # Delete multiple resourcesAccess to resource subresources:
rules:
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]# Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: production
subjects:
- kind: ServiceAccount
name: app-reader
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io# Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployment-admin
namespace: development
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: deployment-admin-binding
namespace: development
subjects:
- kind: ServiceAccount
name: deployer-sa
namespace: development
roleRef:
kind: Role
name: deployment-admin
apiGroup: rbac.authorization.k8s.io# ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-reader
rules:
- apiGroups: [""]
resources: ["pods", "services", "nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch"]
---
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-reader-binding
subjects:
- kind: ServiceAccount
name: monitoring-sa
namespace: monitoring
roleRef:
kind: ClusterRole
name: cluster-reader
apiGroup: rbac.authorization.k8s.io# Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-manager
namespace: production
rules:
# Manage Deployments
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Manage Services
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Read ConfigMaps and Secrets
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
# View Pods and logs
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-manager-binding
namespace: production
subjects:
- kind: ServiceAccount
name: app-manager-sa
namespace: production
roleRef:
kind: Role
name: app-manager
apiGroup: rbac.authorization.k8s.ioKubernetes provides default ClusterRoles:
Read-only access to most resources:
kubectl get clusterrole view -o yamlPermissions:
Read-write access to most resources:
kubectl get clusterrole edit -o yamlPermissions:
Full access within namespace:
kubectl get clusterrole admin -o yamlPermissions:
Full cluster access:
kubectl get clusterrole cluster-admin -o yamlPermissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-view
namespace: development
subjects:
- kind: ServiceAccount
name: developer-sa
namespace: development
roleRef:
kind: ClusterRole
name: view # Built-in ClusterRole
apiGroup: rbac.authorization.k8s.ioCombine multiple ClusterRoles:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-role
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # Rules automatically filled by aggregation
---
# Component role 1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-pods
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# Component role 2
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-nodes
labels:
rbac.example.com/aggregate-to-monitoring: "true"
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]# Check if you can perform action
kubectl auth can-i create deployments
# Check for specific user/ServiceAccount
kubectl auth can-i get pods --as=system:serviceaccount:default:my-app-sa
# Check in specific namespace
kubectl auth can-i delete services --namespace=production
# List all permissions
kubectl auth can-i --list
kubectl auth can-i --list --as=system:serviceaccount:default:my-app-sa# Run command as ServiceAccount
kubectl get pods --as=system:serviceaccount:default:my-app-sa
# Run command as user
kubectl get pods --as=john@example.com# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: cicd-deployer
namespace: default
---
# Role - Deploy applications
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer-role
namespace: production
rules:
# Manage Deployments
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "patch"]
# Manage Services
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "create", "update", "patch"]
# Manage ConfigMaps
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "update", "patch"]
# Read Pods (for status checking)
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-deployer-binding
namespace: production
subjects:
- kind: ServiceAccount
name: cicd-deployer
namespace: default
roleRef:
kind: Role
name: deployer-role
apiGroup: rbac.authorization.k8s.io# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: developer
namespace: development
---
# Role - Development environment access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer-role
namespace: development
rules:
# Full access to Deployments
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["*"]
# Full access to Services
- apiGroups: [""]
resources: ["services"]
verbs: ["*"]
# Full access to ConfigMaps
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["*"]
# Read-only Secrets
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
# Pod management
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec"]
verbs: ["get", "list", "watch", "create", "delete"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
namespace: development
subjects:
- kind: ServiceAccount
name: developer
namespace: development
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.io# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
# ClusterRole - Read metrics cluster-wide
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-role
rules:
# Read nodes
- apiGroups: [""]
resources: ["nodes", "nodes/metrics", "nodes/stats"]
verbs: ["get", "list", "watch"]
# Read pods
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Read services
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get", "list", "watch"]
# Read metrics
- apiGroups: ["metrics.k8s.io"]
resources: ["nodes", "pods"]
verbs: ["get", "list"]
---
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-binding
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
roleRef:
kind: ClusterRole
name: prometheus-role
apiGroup: rbac.authorization.k8s.io# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: namespace-admin
namespace: production
---
# RoleBinding - Use built-in admin role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: namespace-admin-binding
namespace: production
subjects:
- kind: ServiceAccount
name: namespace-admin
namespace: production
roleRef:
kind: ClusterRole
name: admin # Built-in ClusterRole
apiGroup: rbac.authorization.k8s.ioProblem: Giving cluster-admin to everyone.
# Bad: Too permissive
roleRef:
kind: ClusterRole
name: cluster-adminSolution: Grant minimum necessary permissions:
# Good: Specific permissions
roleRef:
kind: ClusterRole
name: viewProblem: Granting cluster-wide access when namespace access sufficient.
# Bad: Cluster-wide access
kind: ClusterRoleBindingSolution: Use RoleBinding for namespace-scoped access:
# Good: Namespace-scoped
kind: RoleBinding
metadata:
namespace: productionProblem: Using wildcards (*) for everything.
# Bad: Too broad
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]Solution: Be specific:
# Good: Specific permissions
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]Problem: Deploying RBAC without testing.
Solution: Always test:
kubectl auth can-i get pods --as=system:serviceaccount:default:my-app-saProblem: Wrong or missing API group.
# Bad: Missing API group for deployments
rules:
- apiGroups: [""] # Wrong! Deployments are in "apps"
resources: ["deployments"]Solution: Use correct API group:
# Good: Correct API group
rules:
- apiGroups: ["apps"]
resources: ["deployments"]Grant only necessary permissions:
# Minimal permissions
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"] # Only what's neededPrefer Role over ClusterRole:
# Good: Namespace-scoped
kind: Role
metadata:
namespace: productionUse view, edit, admin when appropriate:
roleRef:
kind: ClusterRole
name: view # Built-in rolemetadata:
name: app-manager
annotations:
description: "Manages applications in production namespace"
permissions: "deployments, services, configmaps"Review RBAC regularly:
# List all RoleBindings
kubectl get rolebindings --all-namespaces
# List all ClusterRoleBindings
kubectl get clusterrolebindings
# Check specific permissions
kubectl auth can-i --list --as=system:serviceaccount:default:my-app-sa# Reader role
kind: Role
name: pod-reader
# Writer role
kind: Role
name: pod-writer
# Admin role
kind: Role
name: pod-adminkubectl get roles
kubectl get roles --all-namespaces
kubectl get clusterroleskubectl get rolebindings
kubectl get rolebindings --all-namespaces
kubectl get clusterrolebindingskubectl describe role pod-reader
kubectl describe rolebinding read-pods
kubectl describe clusterrole view
kubectl describe clusterrolebinding cluster-adminkubectl get role pod-reader -o yaml
kubectl get rolebinding read-pods -o yaml# Delete Role
kubectl delete role pod-reader
# Delete RoleBinding
kubectl delete rolebinding read-pods
# Delete ClusterRole
kubectl delete clusterrole custom-role
# Delete ClusterRoleBinding
kubectl delete clusterrolebinding custom-bindingIn episode 33, we've explored RBAC and RoleBinding in Kubernetes in depth. We've learned how to implement fine-grained access control using Roles, ClusterRoles, RoleBindings, and ClusterRoleBindings.
Key takeaways:
RBAC is fundamental to Kubernetes security. By understanding and properly implementing RBAC, you can ensure secure, controlled access to cluster resources, protecting your applications and data from unauthorized access.
Are you getting a clearer understanding of RBAC and RoleBinding in Kubernetes? Keep your learning momentum going and look forward to the next episode!
Catatan
If you want to continue to the next episode, you can click the Episode 34 thumbnail below