LearnKubernetes
Kubernetes6. Security·EXPERT·6 min read

Service Accounts

TL;DR

  • Every pod runs as a ServiceAccount (defaults to default if not specified)
  • Kubernetes 1.22+ uses short-lived, auto-rotating projected tokens instead of long-lived Secrets
  • ServiceAccount identity string in RBAC: system:serviceaccount:<namespace>:<name>
  • Cloud IAM integration (IRSA, Workload Identity) eliminates static credential Secrets
  • Set automountServiceAccountToken: false on pods that don’t need API access
  • Always create dedicated ServiceAccounts per workload; never rely on the default account

Core Concepts

ServiceAccounts as Pod Identity

A ServiceAccount is the workload equivalent of a human user. Every pod runs as a ServiceAccount (explicitly or implicitly using default), and that identity is used for RBAC authorization when the pod calls the Kubernetes API.

ServiceAccounts are namespaced: every namespace automatically gets a default ServiceAccount created. Pods in a namespace that don’t specify serviceAccountName use the default account.

Token Delivery: Projected Volumes vs. Legacy Secrets

Modern (Kubernetes 1.22+): Projected Volumes

Service account tokens are delivered as short-lived, auto-rotating, audience-bound JWTs via the projected volume mechanism:

volumes:
- name: token-vol
  projected:
    sources:
    - serviceAccountToken:
        path: token
        expirationSeconds: 3600      # Auto-rotates hourly
        audience: vault               # Scoped to specific consumer

Legacy: Static Secrets

Older kubernetes.io/service-account-token type Secrets still exist but are discouraged: they contain long-lived tokens that never expire and represent a large blast radius if leaked.

Projected tokens are inherently safer: automatic rotation shrinks the exploitation window, and audience-scoping prevents token replay across different services.

RBAC Identity Representation

A ServiceAccount’s identity in RBAC and audit logs is a standardized string:

system:serviceaccount:<namespace>:<serviceaccount-name>

Example: system:serviceaccount:payments:payments-api-sa

This exact format is used in RoleBinding subjects and with kubectl auth can-i --as=.

Cloud Workload Identity

Cloud-managed clusters (EKS, GKE, AKS) allow ServiceAccounts to federate with cloud IAM, eliminating static credential Secrets:

AWS IRSA (IAM Roles for Service Accounts) — Annotate the ServiceAccount with an IAM role ARN; EKS injects an OIDC-based token that AWS SDKs exchange for temporary credentials.

GCP Workload Identity — Bind a Kubernetes ServiceAccount to a Google Cloud service account via OIDC federation.

Azure Workload Identity Federation — Similar OIDC-based federation model.

This approach provides temporary, credential-less access without storing long-lived keys in Kubernetes Secrets.

Token Mounting and Security

By default, every pod mounts its ServiceAccount token at /var/run/secrets/kubernetes.io/serviceaccount/token. This token is valid for API server access.

Security best practice: Set automountServiceAccountToken: false on pods (and ServiceAccounts) that have no legitimate need to call the Kubernetes API. If a pod is later compromised, the attacker doesn’t automatically gain API access.

Comparison Table

Aspect ServiceAccount Token Type Use Case
Identity Scope Per-namespace Kubernetes API Workload identification
Token Lifetime Indefinite (account exists) Short-lived (1hr default) Temporary API access
Token Lifetime (Legacy) Indefinite (account exists) Long-lived (never expires) Deprecated in 1.22+
Mounting Explicit serviceAccountName Automatic projection Automatic pod token injection
Cloud Integration Via IRSA/Workload Identity OIDC federation Cloud credential exchange
Best for RBAC binding API requests Secure temporary access

Command Reference

Creating ServiceAccounts

# Imperative creation
kubectl create serviceaccount payments-api-sa -n payments

# View ServiceAccounts in a namespace
kubectl get serviceaccounts -n payments

# Describe a ServiceAccount (shows mounted token Secrets, etc.)
kubectl describe serviceaccount payments-api-sa -n payments

Specifying a ServiceAccount in a Pod

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: payments
spec:
  serviceAccountName: payments-api-sa      # Specify the SA
  automountServiceAccountToken: false      # Disable auto-mounting if not needed
  containers:
  - name: app
    image: myorg/app:1.0

RBAC Binding for ServiceAccounts

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: payments-api-reader
  namespace: payments
subjects:
- kind: ServiceAccount
  name: payments-api-sa          # Reference the SA
  namespace: payments             # Must match SA's namespace
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Cloud Workload Identity Configuration

apiVersion: v1
kind: ServiceAccount
metadata:
  name: payments-api-sa
  namespace: payments
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/payments-api-role

Token Inspection and Testing

# Check which ServiceAccount a pod uses
kubectl get pod my-app -o jsonpath='{.spec.serviceAccountName}'

# Generate a short-lived token for testing (Kubernetes 1.24+)
kubectl create token payments-api-sa -n payments --duration=1h

# Inspect the token inside a running pod
kubectl exec my-app -- cat /var/run/secrets/kubernetes.io/serviceaccount/token

# Check what a ServiceAccount can do (dry run)
kubectl auth can-i --list --as=system:serviceaccount:payments:payments-api-sa -n payments

# Check specific permission
kubectl auth can-i create pods --as=system:serviceaccount:payments:payments-api-sa -n payments

Common Pitfalls

Pitfall — Implicit default ServiceAccount Usage Pods run with the default ServiceAccount by accident when no ServiceAccount is explicitly specified, potentially with broad permissions.

  • Why: default exists in every namespace; omitting serviceAccountName silently uses it.
  • Fix: Always explicitly specify a dedicated ServiceAccount per workload. Minimize permissions on default or forbid its use entirely.

Pitfall — RoleBinding in Wrong Namespace A RoleBinding is created for a ServiceAccount, but in a different namespace than the SA/pod.

  • Why: RoleBindings are namespaced; a RoleBinding in namespace A doesn’t apply to a ServiceAccount in namespace B.
  • Fix: Ensure RoleBinding namespace matches the ServiceAccount and pod namespaces.

Pitfall — Enabling automountServiceAccountToken on Non-API Pods Pods that don’t call the Kubernetes API automatically mount a token, giving attackers unnecessary API access if the pod is compromised.

  • Why: Default behavior mounts tokens; no explicit configuration is needed to create the vulnerability.
  • Fix: Always set automountServiceAccountToken: false at pod or ServiceAccount level if API access is not required.

Pitfall — Long-lived Token Secrets in Production Using legacy kubernetes.io/service-account-token type Secrets instead of projected tokens.

  • Why: Long-lived tokens never expire and represent a large blast radius if leaked.
  • Fix: Use projected tokens (Kubernetes 1.22+) which auto-rotate and are audience-scoped.

Pitfall — Confusing ServiceAccount Namespace in RoleBinding Subject Referencing a ServiceAccount from a different namespace in a RoleBinding subject without specifying the namespace.

  • Why: ServiceAccount subjects must include a namespace field; omitting it causes the binding to reference the wrong account.
  • Fix: Always include namespace: <sa-namespace> in ServiceAccount RoleBinding subjects.

Interview Questions

Q: Explain how ServiceAccounts provide identity to pods for API server access.

Q: What is the difference between projected tokens and legacy Secret-based tokens? Why the change?

Q: How would you prevent a pod from accessing the Kubernetes API even if it’s compromised?

Q: Walk through setting up a ServiceAccount with minimal RBAC permissions for a specific application.

Q: What is cloud workload identity (IRSA, Workload Identity)? What problem does it solve?

Q: A pod cannot list ConfigMaps even though the RoleBinding looks correct. What are three things to check?

Q: Design a ServiceAccount/RBAC strategy for a multi-tenant cluster where each team has its own namespace.

Q: Explain the identity string format for ServiceAccounts in audit logs and RBAC.

🔒 Locked
Sign in and unlock the full syllabus to keep reading.
Sign in to continue
Knowledge check
5 scenario questions on this topic
Take the quiz →
Related in 6. Security
SSL/TLS Fundamentals
EXPERT
TLS in Kubernetes
EXPERT
Authentication & Authorization
EXPERT
RBAC
EXPERT