Service accounts

Service accounts

Identity for workloads. Every namespace has a default ServiceAccount and every Pod runs as one.

graph LR SA[ServiceAccount app] --> P[Pod serviceAccountName: app] K[kubelet] -->|projected token<br/>1 h, bound to Pod| P P -->|Authorization: Bearer ...| API[API server] RB[RoleBinding] --> SA

The kubelet mounts a short-lived, audience-bound JWT into /var/run/secrets/kubernetes.io/serviceaccount/ (plus CA and namespace) and refreshes it. The token dies with the Pod. The API sees the Pod as system:serviceaccount:<ns>:<name>.

apiVersion: v1
kind: ServiceAccount
metadata: { name: app-reader, namespace: dev }
automountServiceAccountToken: false      # default for Pods using this SA
---
spec:
  serviceAccountName: app-reader
  automountServiceAccountToken: true     # only where the app needs the API
kubectl create sa app-reader -n dev
kubectl create rolebinding app-reader --clusterrole=view --serviceaccount=dev:app-reader -n dev
kubectl create token app-reader -n dev --duration=10m     # for a pipeline or a test
kubectl auth can-i list pods -n dev --as system:serviceaccount:dev:app-reader

Good practice

  • One ServiceAccount per application, never grant rights to default.
  • automountServiceAccountToken: false unless the app talks to the API - most do not.
  • No long-lived token Secrets (kubernetes.io/service-account-token); use kubectl create token or projected tokens.
  • In the cloud, workload identity (Azure Workload Identity, EKS Pod Identity) maps a ServiceAccount to a cloud identity - no cloud keys in Secrets.

References