What is a Kubernetes Service Account? RBAC Explained Simply (2026)
Service Accounts and RBAC confuse most beginners. Here's what they are, why they exist, and how to set them up correctly.
Every Kubernetes beginner eventually runs into this error:
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:default"
cannot list resource "pods" in API group "" in the namespace "default"
This is a Service Account + RBAC issue. Here's what's happening and how to fix it.
What is a Service Account?
Kubernetes has two types of accounts:
- User accounts — for humans (you using kubectl)
- Service accounts — for applications running inside the cluster
When a pod needs to talk to the Kubernetes API (to list pods, create deployments, read secrets), it needs an identity. That identity is a Service Account.
Every pod gets a Service Account automatically — if you don't specify one, it uses the default service account in its namespace.
Why Do Pods Need to Talk to the API?
Common cases:
- ArgoCD — needs to create/update/delete any resource in the cluster
- Prometheus — needs to list pods and services to discover scrape targets
- CI/CD runners — need to deploy applications
- Custom operators — manage custom resources
- Your app — might need to read ConfigMaps or list other pods
The RBAC Model
RBAC (Role-Based Access Control) controls who can do what.
Four key resources:
ServiceAccount → (bound by) → RoleBinding → Role
↓
(permissions to do)
list pods, create deployments...
- Role — defines permissions within a namespace
- ClusterRole — defines permissions cluster-wide
- RoleBinding — binds a Role to a ServiceAccount in a namespace
- ClusterRoleBinding — binds a ClusterRole cluster-wide
Step-by-Step Example
Let's give an application permission to list pods in its namespace.
Step 1: Create a Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp-sa
namespace: productionStep 2: Create a Role with the permissions needed
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]Step 3: Bind the Role to the Service Account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: myapp-pod-reader
namespace: production
subjects:
- kind: ServiceAccount
name: myapp-sa
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioStep 4: Use the Service Account in your Pod/Deployment
spec:
serviceAccountName: myapp-sa
containers:
- name: myapp
image: myapp:v1.0Now your app can list pods in the production namespace — and nothing else.
Common Verbs
verbs: ["get", "list", "watch"] # read only
verbs: ["create", "update", "patch"] # write
verbs: ["delete"] # delete
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # full CRUDClusterRole vs Role: When to Use Which
Use Role (namespaced) when:
- Your app only needs access to resources in its own namespace
- Following least privilege (always prefer this)
Use ClusterRole when:
- You need to access cluster-wide resources (nodes, namespaces, persistent volumes)
- You need to read resources across all namespaces (Prometheus scraping all pods)
# ClusterRole for Prometheus to discover targets cluster-wide
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch"]Debugging RBAC Issues
# Check if a service account can do something
kubectl auth can-i list pods \
--as=system:serviceaccount:production:myapp-sa \
-n production
# Check what roles are bound to a service account
kubectl get rolebindings -n production -o yaml | grep -A 5 myapp-sa
# Describe the service account
kubectl describe serviceaccount myapp-sa -n productionThe Default Service Account Problem
By default, every pod uses the default service account, which has no permissions. This is good for security — pods can't talk to the API without explicit grants.
Disable auto-mounting if your app doesn't need API access:
spec:
automountServiceAccountToken: falseThis improves security — if the pod is compromised, the attacker can't use the service account token to access the cluster API.
Resources
- Kubernetes Interview Questions — RBAC is a common interview topic
- Kubernetes Cheatsheet
- Course: CKA with Practice Tests
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
How to Set Up HashiCorp Vault for Secrets Management from Scratch (2026)
HashiCorp Vault is the industry standard for secrets management. This step-by-step guide shows you how to install Vault, configure it, and integrate it with Kubernetes.
What is a Service Mesh? Explained Simply (No Jargon)
Service mesh sounds complicated but the concept is simple. Here's what it actually does, why teams use it, and whether you need one — explained without the buzzwords.
Build a DevSecOps Pipeline with Trivy, SonarQube, and OPA from Scratch (2026)
Step-by-step project walkthrough: add security scanning, code quality gates, and policy enforcement to a GitHub Actions pipeline. Real configs, production-ready.