Kubernetes Service Accounts
Users log in to a cluster with personal credentials. Programs running inside pods need an identity too: a monitoring tool that lists pods, a deployment script that updates images, or a controller that watches events. Service accounts provide that identity for workloads.
The Employee Badge Analogy
Staff members carry badges that open specific doors. A badge proves who the person is, and door rules decide what the person may enter. A service account works as a badge for a pod. RBAC rules act as the door rules, and they grant only the access that the badge holder needs.
Users Compared with Service Accounts
| Feature | User account | Service account |
|---|---|---|
| Meant for | Humans | Pods and automation |
| Stored in Kubernetes | No (managed outside) | Yes, as an object |
| Scope | Cluster-wide identity | Belongs to one namespace |
| Credential | Certificate, token, or login provider | Short-lived signed token |
The Default Service Account
Every namespace contains a service account named default. A pod without an explicit setting uses it. The default account carries almost no permissions, which keeps unconfigured pods safe.
kubectl get serviceaccount
kubectl get serviceaccount default -o yaml
Creating a Service Account
kubectl create serviceaccount pod-reader -n demo
The YAML version:
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-reader
namespace: demo
Giving It Permissions
A new service account holds no rights. Bind it to a Role with a RoleBinding.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-viewer
namespace: demo
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-viewer-binding
namespace: demo
subjects:
- kind: ServiceAccount
name: pod-reader
namespace: demo
roleRef:
kind: Role
name: pod-viewer
apiGroup: rbac.authorization.k8s.io
Diagram: Identity to Permission
Pod ──uses──▶ ServiceAccount: pod-reader
│
RoleBinding
│
▼
Role: pod-viewer
get, list, watch pods
│
▼
Kubernetes API Server
Attaching It to a Pod
apiVersion: v1
kind: Pod
metadata:
name: viewer
namespace: demo
spec:
serviceAccountName: pod-reader
containers:
- name: tool
image: bitnami/kubectl:latest
command: ["sleep", "3600"]
Kubernetes mounts a token into the container at /var/run/secrets/kubernetes.io/serviceaccount/. Client libraries find the token there and call the API automatically.
How Tokens Work Today
Older clusters stored long-lived tokens in Secrets. Modern clusters issue bound tokens through a projected volume. These tokens last a short time, tie to one pod, and refresh automatically by the kubelet. A leaked token expires fast, and deleting the pod invalidates it.
Kubernetes 1.24 and later no longer create Secret-based tokens for new service accounts. Request a temporary token manually when a script runs outside the cluster:
kubectl create token pod-reader -n demo --duration=1h
Turning Off Automatic Token Mounting
Most web applications never call the Kubernetes API. Remove the token from those pods to shrink the attack surface.
spec:
automountServiceAccountToken: false
The same field works on the ServiceAccount object to apply the rule to every pod that uses it.
Testing Permissions
kubectl auth can-i list pods \
--as=system:serviceaccount:demo:pod-reader -n demo
kubectl auth can-i delete pods \
--as=system:serviceaccount:demo:pod-reader -n demo
The first command answers yes and the second answers no with the Role above.
A Real Scenario
A team runs a small dashboard that lists the pods in its namespace and shows their status. The dashboard needs read access to pods and nothing else. The team creates a service account named dashboard, writes a Role that allows get, list, and watch on pods, and binds the two together. If an attacker breaks into the dashboard container, the stolen token can read pod information in one namespace. The token cannot delete workloads, read Secrets, or touch other namespaces.
Compare that outcome with a dashboard that runs under a cluster-admin identity. One stolen token hands over the entire cluster. Careful service account design limits the blast radius of every breach.
Security Habits
- Create one service account per application. Shared accounts blur responsibility and widen damage after a breach.
- Grant the smallest permission set that works.
- Avoid binding service accounts to
cluster-admin. - Disable token mounting for pods that never contact the API.
- Audit bindings regularly with
kubectl get rolebindings,clusterrolebindings -A.
Cloud Identity Integration
Managed clouds link service accounts to cloud identities. EKS uses IAM Roles for Service Accounts, GKE uses Workload Identity, and AKS uses Workload Identity with Microsoft Entra. A pod reaches cloud storage or databases without stored cloud keys.
Key Points
- Service accounts give pods an identity inside a namespace.
- RBAC bindings decide what that identity may do.
- Bound tokens expire quickly and refresh automatically.
- One account per application and minimal permissions limit risk.
