Stage 5 · Platform
Security, Identity & Admission
ServiceAccount Identity
Bound tokens, audience claims, projected tokens, and workload identity federation.
ServiceAccount Overview
ServiceAccounts provide identity for pods. Each namespace has a default ServiceAccount. Pods use ServiceAccount tokens to authenticate with the API server and external services. In v1.24+, tokens are bound to the pod by default.
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-service
namespace: production
annotations:
# Azure Workload Identity
azure.workload.identity/client-id: "00000000-0000-0000-0000-000000000000"
automountServiceAccountToken: false # Don't auto-mount if not needed
secrets:
- name: api-service-token-abc12automountServiceAccountToken: false prevents the token from being mounted unless explicitly configured. This is the secure default for pods that don't need Kubernetes API access.
Bound Service Account Tokens
Bound tokens are scoped to a specific pod, audience, and expiration. They are projected into the pod at /var/run/secrets/kubernetes.io/serviceaccount/token. kubelet auto-rotates them before expiry. This is more secure than legacy long-lived tokens.
apiVersion: v1
kind: Pod
metadata:
name: api-pod
spec:
serviceAccountName: api-service
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
volumes:
- name: token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600 # 1 hour
audience: https://kubernetes.default.svcThe token is valid for 1 hour and scoped to the audience https://kubernetes.default.svc. kubelet automatically rotates the token before expiry. The application reads the token from the projected volume.
Audience Claims
Audience claims scope tokens to specific services. A token with audience A cannot be used to authenticate with service B. This prevents token replay attacks where a stolen token is used against unintended services.
apiVersion: v1
kind: Pod
metadata:
name: external-caller
spec:
serviceAccountName: external-api-reader
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: api-token
mountPath: /var/run/secrets/api
readOnly: true
volumes:
- name: api-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: https://external-api.example.comThe token is scoped to https://external-api.example.com. It cannot be used to authenticate with the Kubernetes API server. The external API validates the audience claim before accepting the token.
Workload Identity Federation
Workload Identity federates Kubernetes ServiceAccounts with external identity providers (Azure AD, AWS IAM, GCP IAM). Pods use their projected token to authenticate with cloud services without storing credentials.
apiVersion: v1
kind: ServiceAccount
metadata:
name: storage-reader
namespace: production
annotations:
azure.workload.identity/client-id: "11111111-1111-1111-1111-111111111111"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: blob-reader
namespace: production
spec:
template:
metadata:
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: storage-reader
containers:
- name: app
image: my-app:1.0The ServiceAccount is federated with Azure AD using the client-id annotation. The pod label azure.workload.identity/use: true enables the webhook. The pod gets an Azure AD token using the federated identity.
Token Projection
Token projection configures how the ServiceAccount token is projected into the pod. Control the path, expiration, and audience. This is useful when external services expect tokens at specific paths.
apiVersion: v1
kind: Pod
metadata:
name: multi-audience
spec:
serviceAccountName: multi-service
containers:
- name: app
volumeMounts:
- name: k8s-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
- name: api-token
mountPath: /var/run/secrets/api
readOnly: true
volumes:
- name: k8s-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: https://kubernetes.default.svc
- name: api-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: https://my-api.example.comMultiple projected volumes provide tokens for different audiences. The Kubernetes API token is at /var/run/secrets/kubernetes.io/serviceaccount/token. The API token is at /var/run/secrets/api/token. Each is scoped to its audience.
Best Practices
- Use automountServiceAccountToken: false for pods that don't need API access
- Create dedicated ServiceAccounts per workload — don't share the default SA
- Use Workload Identity for cloud service access — never embed credentials
- Set short expirationSeconds (1h) for projected tokens
- Restrict token audiences to the specific service being called
- Audit ServiceAccount permissions with kubectl auth can-i --list
Verify token mounting with kubectl exec -it pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d. -f2 | base64 -d. This decodes the JWT payload showing the audience, expiration, and service account identity.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.