The ServiceAccountNotFound error means a Pod is trying to use a ServiceAccount that doesn’t exist in its namespace. This breaks the fundamental ability of a Pod to authenticate and authorize itself to the Kubernetes API.
Here are the common reasons this happens, and how to fix them:
1. Typo in the ServiceAccount Name
This is the most frequent culprit. A simple spelling mistake in the Pod’s manifest, or in the ServiceAccount’s name itself, will cause this error.
Diagnosis:
Check the serviceAccountName field in your Pod’s YAML. Compare it character-by-character with the output of kubectl get serviceaccounts -n <namespace>.
Fix:
Correct the serviceAccountName in your Pod’s YAML to match an existing ServiceAccount. For example, if your Pod has serviceAccountName: default-sa and the actual ServiceAccount is default-sa-prod, change it to default-sa-prod.
Why it works: Kubernetes uses exact string matching for ServiceAccount names. A mismatch, however small, means the API server cannot locate the intended identity.
2. ServiceAccount in the Wrong Namespace
You might have created the ServiceAccount in one namespace, but the Pod is trying to reference it from another.
Diagnosis:
Verify the metadata.namespace of the ServiceAccount using kubectl get serviceaccount <serviceaccount-name> -o yaml and compare it with the metadata.namespace of the Pod you are inspecting.
Fix:
Either move the ServiceAccount to the correct namespace or update the Pod’s serviceAccountName to include the namespace if you intend to use a cross-namespace ServiceAccount (though this is generally discouraged for security reasons and not directly supported by serviceAccountName field; you’d typically create the SA in the target namespace). The correct approach is to ensure the ServiceAccount exists in the same namespace as the Pod. For instance, if your Pod is in dev-namespace and your ServiceAccount is in shared-namespace, create a copy or a new SA in dev-namespace:
kubectl get serviceaccount my-sa -n shared-namespace -o yaml | \
sed "s/namespace: shared-namespace/namespace: dev-namespace/" | \
kubectl apply -f -
Why it works: ServiceAccounts are namespaced resources. A Pod can only directly reference ServiceAccounts within its own namespace.
3. Forgetting to Create the ServiceAccount
You’ve defined a serviceAccountName in your Pod spec, but you never actually created the ServiceAccount resource itself.
Diagnosis:
Run kubectl get serviceaccounts -n <namespace> and confirm that the ServiceAccount you’re referencing is not in the list.
Fix:
Create the ServiceAccount using kubectl create serviceaccount <serviceaccount-name> -n <namespace>. For example, if your Pod refers to my-app-sa in the production namespace:
kubectl create serviceaccount my-app-sa -n production
Why it works: The ServiceAccount resource must exist for Kubernetes to grant it to a Pod.
4. Using automountServiceAccountToken: false and Not Specifying serviceAccountName
If you’ve disabled the default ServiceAccount token mounting (automountServiceAccountToken: false in the ServiceAccount or Pod spec), but then you also don’t explicitly specify a serviceAccountName in your Pod, it tries to use the default ServiceAccount for the namespace. If that default SA is missing or misconfigured, you’ll get this error.
Diagnosis:
Check the Pod’s spec.automountServiceAccountToken (if set) and the ServiceAccount’s automountServiceAccountToken (if set). Also, check if spec.serviceAccountName is omitted. If automountServiceAccountToken is false for the SA or Pod, and serviceAccountName is not set, Kubernetes will try to use the default SA. Check kubectl get sa default -n <namespace>.
Fix:
Either:
a) Re-enable token mounting by removing automountServiceAccountToken: false from the Pod or ServiceAccount spec, or setting it to true.
b) Explicitly specify a valid serviceAccountName in the Pod spec that does have automountServiceAccountToken enabled (or is configured to allow it).
For example, if you want to use a specific SA named my-special-sa that should have a token:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: default
spec:
serviceAccountName: my-special-sa # Explicitly specify a valid SA
containers:
- name: my-container
image: nginx
Ensure my-special-sa exists and has automountServiceAccountToken enabled (which is the default).
Why it works: This forces the Pod to use a known, existing ServiceAccount that is configured to provide a token.
5. ServiceAccount Deleted After Pod Creation
It’s possible the ServiceAccount existed when the Pod was created, but was subsequently deleted. Pods might continue to run, but new Pods or Pods that restart might encounter this.
Diagnosis:
Check the creation timestamp of the Pod and compare it with the existence of the ServiceAccount. If the Pod is recent and the SA is missing, it’s a strong indicator. Use kubectl get pod <pod-name> -n <namespace> -o yaml to find the serviceAccountName and then kubectl get serviceaccount <serviceaccount-name> -n <namespace> to check its existence.
Fix: Recreate the deleted ServiceAccount. The Pod should automatically start using it again on its next reconciliation cycle or restart.
kubectl create serviceaccount <serviceaccount-name> -n <namespace>
Why it works: The Pod’s controller will attempt to resolve the serviceAccountName on its next loop, find the recreated SA, and update the Pod’s status accordingly.
6. Cluster-level Issues with RBAC or API Server
In rare cases, the issue might not be with the ServiceAccount definition itself, but with the Kubernetes control plane’s ability to access or validate it. This could be due to RBAC misconfigurations preventing the API server from reading ServiceAccounts, or transient API server issues.
Diagnosis:
Check the API server logs for errors related to ServiceAccount retrieval or authentication. Inspect the cluster-role-bindings and role-bindings to ensure the system:serviceaccount user (or other relevant service accounts) has permissions to get, list, and watch ServiceAccounts in the relevant namespaces.
kubectl auth can-i list serviceaccounts --namespace <namespace> --as=system:serviceaccount:<namespace>:<serviceaccount-name>
(Replace the last part with the specific SA the API server might be trying to impersonate or use).
Fix: Correct any RBAC policies that are too restrictive. If API server logs show transient errors, consider restarting the API server pods (though this is a significant operation and should be done with extreme caution).
Why it works: Ensuring the control plane components have the necessary permissions allows them to correctly identify and provision ServiceAccounts to Pods.
The next error you’ll likely see after fixing this is a SecretsNotFound error, or an inability for the Pod to access specific Kubernetes resources due to incorrect RBAC bindings associated with the ServiceAccount.