Kubernetes Security

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
Field note: Kubernetes permissions should be intentional. Do not give broad cluster-admin permissions to workloads just because it makes something work.

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
Bottom line: ServiceAccounts identify workloads. RBAC controls what those identities can do. Use least privilege and test permissions with kubectl auth can-i.

Check your understanding

  1. What is a ServiceAccount used for?
  2. What does a Role define?
  3. What does a RoleBinding do?
  4. What is the difference between Role and ClusterRole?
  5. What command tests permissions?
  6. Why is cluster-admin risky?
  7. What subject string represents a ServiceAccount in kubectl auth can-i?
  8. Why should workloads usually have dedicated ServiceAccounts?
  9. What are three RBAC troubleshooting commands?
  10. What is least privilege?
Answer key
  1. It provides an identity for a workload.
  2. Permissions within a Namespace.
  3. It grants a Role or ClusterRole to a subject.
  4. Role is namespaced; ClusterRole is cluster-scoped.
  5. kubectl auth can-i.
  6. It grants broad administrative permissions that can amplify mistakes or compromise.
  7. system:serviceaccount:<namespace>:<serviceaccount>.
  8. So permissions can be scoped to the workload’s actual needs.
  9. Examples: auth can-i, get rolebindings, describe role, describe serviceaccount.
  10. Giving only the permissions required to perform the intended task.
← Previous: Scheduling Controls Series index Next: NetworkPolicies →