ServiceAccounts and RBAC
Kubernetes workloads and users need identities and permissions. ServiceAccounts identify workloads, and RBAC controls what they are allowed to do.
What this lesson covers
Kubernetes security starts with identity and permissions. ServiceAccounts identify workloads. RBAC defines what users or workloads are allowed to do.
- What ServiceAccounts are
- What Roles and ClusterRoles are
- What RoleBindings and ClusterRoleBindings are
- How to grant read-only access in a Namespace
- How to test permissions with kubectl auth can-i
- Why least privilege matters
The short version
ServiceAccount: Identity for a workload. Role: Permissions inside one Namespace. ClusterRole: Permissions that can apply cluster-wide or across Namespaces. RoleBinding: Grants a Role or ClusterRole to a subject in a Namespace. ClusterRoleBinding: Grants a ClusterRole across the cluster.
Before you start
kubectl config current-context kubectl get nodes kubectl create namespace rbac-lab
Step 1: View the default ServiceAccount
kubectl get serviceaccounts -n rbac-lab kubectl describe serviceaccount default -n rbac-lab
Step 2: Create a dedicated ServiceAccount
kubectl create serviceaccount pod-reader-sa -n rbac-lab kubectl get serviceaccounts -n rbac-lab
Step 3: Create a Role
Create a file named:
pod-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader-role namespace: rbac-lab rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]
kubectl apply -f pod-reader-role.yaml kubectl get roles -n rbac-lab kubectl describe role pod-reader-role -n rbac-lab
Step 4: Bind the Role to the ServiceAccount
Create a file named:
pod-reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-reader-binding namespace: rbac-lab subjects: - kind: ServiceAccount name: pod-reader-sa namespace: rbac-lab roleRef: kind: Role name: pod-reader-role apiGroup: rbac.authorization.k8s.io
kubectl apply -f pod-reader-binding.yaml kubectl get rolebindings -n rbac-lab kubectl describe rolebinding pod-reader-binding -n rbac-lab
Step 5: Test permissions
kubectl auth can-i list pods --as=system:serviceaccount:rbac-lab:pod-reader-sa -n rbac-lab kubectl auth can-i delete pods --as=system:serviceaccount:rbac-lab:pod-reader-sa -n rbac-lab kubectl auth can-i list secrets --as=system:serviceaccount:rbac-lab:pod-reader-sa -n rbac-lab
The ServiceAccount should be allowed to list Pods but not delete Pods or list Secrets.
Step 6: Create a Pod that uses the ServiceAccount
Create a file named:
serviceaccount-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: serviceaccount-pod
namespace: rbac-lab
spec:
serviceAccountName: pod-reader-sa
containers:
- name: app
image: busybox:latest
command: ["sh", "-c", "echo Running with a dedicated ServiceAccount; sleep 3600"]
kubectl apply -f serviceaccount-pod.yaml kubectl describe pod serviceaccount-pod -n rbac-lab
Look for the ServiceAccount name in the describe output.
Step 7: Understand Role vs ClusterRole
A Role is namespaced. A ClusterRole is cluster-scoped. But a ClusterRole can also be bound into a Namespace using a RoleBinding.
This is common for reusable permission sets, such as a ClusterRole that allows read-only access to common resources.
Step 8: Create a ClusterRole for reading Namespaces
Create a file named:
namespace-reader-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: namespace-reader-lab rules: - apiGroups: [""] resources: ["namespaces"] verbs: ["get", "list", "watch"]
kubectl apply -f namespace-reader-clusterrole.yaml kubectl get clusterrole namespace-reader-lab
Step 9: Avoid broad bindings
A ClusterRoleBinding would grant the ClusterRole across the cluster. That can be appropriate for cluster-level identities, but it is often too broad for application workloads.
In real environments, choose the narrowest scope that supports the workload.
Common RBAC troubleshooting commands
kubectl auth can-i <verb> <resource> -n <namespace> kubectl auth can-i <verb> <resource> --as=system:serviceaccount:<namespace>:<serviceaccount> -n <namespace> kubectl get serviceaccounts -n <namespace> kubectl get roles -n <namespace> kubectl get rolebindings -n <namespace> kubectl describe role <role-name> -n <namespace> kubectl describe rolebinding <binding-name> -n <namespace>
Common mistakes
- Using the default ServiceAccount for everything.
- Granting cluster-admin because a narrower permission was not understood.
- Binding permissions in the wrong Namespace.
- Forgetting that Secrets are sensitive Kubernetes resources.
- Confusing authentication with authorization.
Step 10: Clean up
kubectl delete namespace rbac-lab kubectl delete clusterrole namespace-reader-lab
Check your understanding
- What is a ServiceAccount used for?
- What does a Role define?
- What does a RoleBinding do?
- What is the difference between Role and ClusterRole?
- What command tests permissions?
- Why is cluster-admin risky?
- What subject string represents a ServiceAccount in kubectl auth can-i?
- Why should workloads usually have dedicated ServiceAccounts?
- What are three RBAC troubleshooting commands?
- What is least privilege?
Answer key
- It provides an identity for a workload.
- Permissions within a Namespace.
- It grants a Role or ClusterRole to a subject.
- Role is namespaced; ClusterRole is cluster-scoped.
- kubectl auth can-i.
- It grants broad administrative permissions that can amplify mistakes or compromise.
- system:serviceaccount:<namespace>:<serviceaccount>.
- So permissions can be scoped to the workload’s actual needs.
- Examples: auth can-i, get rolebindings, describe role, describe serviceaccount.
- Giving only the permissions required to perform the intended task.