Service Accounts
π ServiceAccount Token Mounting Rules
-
Default behavior
-
automountServiceAccountTokenis true by default (even if not written). - So any Pod using that SA automatically mounts a token under
/var/run/secrets/kubernetes.io/serviceaccount/.
Case 1: automountServiceAccountToken: false in ServiceAccount YAML
- All Pods using this SA will NOT get a token mounted, unless the Pod overrides it.
Case 2: Pod spec also has automountServiceAccountToken
-
Pod spec overrides SA spec.
-
Pod =
trueβ token mounted, even if SA =false. - Pod =
falseβ no token, even if SA =true.
π Quick Effects
- SA false + Pod default (not set) β No token.
- SA false + Pod true β Token mounted.
- SA true (default) + Pod false β No token.
- SA true (default) + Pod default (not set) β Token mounted.
π In short: Pod spec wins.
controlplane:~$ k get sa secure-sa -o yaml
apiVersion: v1
automountServiceAccountToken: false # key field, added manually.
kind: ServiceAccount
metadata:
creationTimestamp: "2025-08-24T10:45:17Z"
name: secure-sa
namespace: default
resourceVersion: "8700"
uid: a9543735-8bff-4999-b509-492dcb306e57
controlplane:~$ k get po secure-pod -o yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
containers:
- image: nginx
name: secure-pod
serviceAccount: secure-sa
serviceAccountName: secure-sa # The key automountServiceAccountToken: wasn't mentioned in the pod manifest.
# Verify that the service account token is NOT mounted to the pod
controlplane:~$ kubectl exec secure-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat: /var/run/secrets/kubernetes.io/serviceaccount/token: No such file or directory
command terminated with exit code 1
controlplane:~$
---
controlplane ~ β vi 1.yaml
controlplane ~ β k apply -f 1.yaml
pod/sa-token-not-automounted created
pod/sa-token-automounted created
controlplane ~ β k exec sa-token-automounted -- ls /var/run/secrets/kubernetes.io/serviceaccount/token
/var/run/secrets/kubernetes.io/serviceaccount/token
controlplane ~ β k exec sa-token-not-automounted -- ls /var/run/secrets/kubernetes.io/serviceaccount/token
ls: cannot access '/var/run/secrets/kubernetes.io/serviceaccount/token': No such file or directory
command terminated with exit code 2
controlplane ~ β cat 1.yaml
apiVersion: v1
kind: Pod
metadata:
name: sa-token-not-automounted
spec:
serviceAccountName: secure-sa
automountServiceAccountToken: false
containers:
- image: nginx
name: without
---
apiVersion: v1
kind: Pod
metadata:
name: sa-token-automounted
spec:
serviceAccountName: secure-sa
automountServiceAccountToken: true
containers:
- image: nginx
name: with
controlplane ~ β
Team Neptune has its own ServiceAccount named neptune-sa-v2 in Namespace neptune. A coworker needs the token from the Secret that belongs to that ServiceAccount. Write the base64 decoded token to file /opt/course/5/token on ckad7326.
controlplane ~ β k get sa -n neptune
NAME SECRETS AGE
default 0 24m
neptune-sa-v2 0 20m
controlplane ~ β k get secrets -n neptune # No automatic Secret is created anymore for ServiceAccounts.
No resources found in neptune namespace.
controlplane ~ β k create token neptune-sa-v2 -n neptune
ey..........
controlplane ~ β k create token neptune-sa-v2 -n neptune > /opt/course/5/token # This gives you the raw JWT (already decoded) directly.
controlplane ~ β k get secrets -n neptune
No resources found in neptune namespace.
controlplane ~ β
Excellent observation π β youβre absolutely right to pause here. Letβs unpack whatβs really happening step by step π
π§ What You Know (and Itβs True)
Starting from Kubernetes v1.24, when you create a ServiceAccount (SA), β‘οΈ no Secret is automatically created for it anymore. Instead, pods using that SA get ephemeral tokens mounted as projected volumes.
So your confusion β βhow can there be a token Secret if no Secret is created?β β is completely valid.
π‘ What the Exam Question Means
In the CKAD/CKA exam, the environment might use an older cluster version (β€ v1.23) or the cluster is manually configured to still create token Secrets (for backward compatibility).
Thatβs why the question says:
βget the token from the Secret that belongs to that ServiceAccount.β
So β in that cluster, a Secret does exist for that SA.
π§© Steps to Solve It
- Find the Secret linked to the ServiceAccount:
kubectl get sa neptune-sa-v2 -n neptune -o yaml
Look under:
secrets:
- name: neptune-sa-v2-token-xxxxx
- Get the token value (base64):
kubectl get secret neptune-sa-v2-token-xxxxx -n neptune -o jsonpath='{.data.token}'
- Decode it and save to the file:
kubectl get secret neptune-sa-v2-token-xxxxx -n neptune -o jsonpath='{.data.token}' | base64 -d > /opt/course/5/token
- Verify (optional):
cat /opt/course/5/token
You should see a plain JWT (three dot-separated sections like xxxxx.yyyyy.zzzzz).
β Rule (refined in one line):
In clusters using legacy ServiceAccount Secrets, get the token from the SAβs Secret (
.data.token), decode it from base64, and save it as a plain JWT β but in newer clusters, tokens are ephemeral and must be created viakubectl create token <sa>.
--
Perfect β you just confirmed your intuition π―
controlplane ~ β k get secrets -n neptune
No resources found in neptune namespace.
That means your cluster is running a modern Kubernetes version (v1.24+), where ServiceAccounts no longer auto-create Secret tokens.
Letβs go through exactly what this means and what you should do in the exam context. π
π§ Why No Secret Exists
Since Kubernetes v1.24, ServiceAccount token Secrets are not created automatically. Instead, tokens are:
- ephemeral (short-lived),
- auto-mounted into pods using that SA,
- and can be manually created on demand with
kubectl create token.
β What To Do in This Scenario (Exam-Compatible)
Because the exam question asks for
βthe token from the Secret that belongs to that ServiceAccount,β
but no Secret exists, the correct modern approach is to manually create a token.
Run this command:
kubectl create token neptune-sa-v2 -n neptune > /opt/course/5/token
This will output a plain JWT (already decoded) and write it to the required path.
π§© Verify
You can check:
cat /opt/course/5/token
You should see something like:
eyJhbGciOiJSUzI1NiIsImtpZCI6IjY1Njg4NjM...<snip>...J9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiw...
β Rule (refined in one line):
In Kubernetes v1.24+, ServiceAccounts no longer have Secrets β use
kubectl create token <sa> -n <ns>to generate a plain JWT token instead of searching for a Secret.