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

FeatureUser accountService account
Meant forHumansPods and automation
Stored in KubernetesNo (managed outside)Yes, as an object
ScopeCluster-wide identityBelongs to one namespace
CredentialCertificate, token, or login providerShort-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.