K8s - Do we need auto mount Service Account token?
I have often seen this topic misunderstood, with people thinking that the token must be mounted in the container to access the kube API server.
Yes, that's true. We definitely need a token if we want our container to access the kube API server. If you auto-mount it, it's like leaving your car key hanging on the car door because you always need the key to drive the car.
First, ask yourself why you need the token. If it's to access the Kube API server, do you need this token to be long-lived or short-lived? Also, determine the level of access the token should have.
So, the answer to the above question is subjective rather than objective.
Let's explore different scenarios where we need a token and when you should keep the automount token enabled.
- You need token for init-container
You would run an init-container to check the status of other Kubernetes services like deployments, pods, and jobs. To get the status of these services, you need to list them from the Kube API server.
In this case, the init-container is already a short-lived container that will be terminated once it completes its task. Therefore, automatically mounting a token to a pod is a poor decision because the token will remain in the pod until it is deleted, but you will never use it again in the init-container.
Mount the token in the init container by adding the following blocks to your deployment.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
serviceAccountName: <YOUR_SERVICE_ACCOUNT_NAME>
initContainers:
- name: init-kubectl
image: bitnami/kubectl:latest # This image includes kubectl
command: ['sh', '-c', 'kubectl get pods --field-selector=status.phase!=Running']
env:
- name: KUBERNETES_SERVICE_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: KUBERNETES_SERVICE_PORT
value: "443" # Default API server port
volumeMounts:
- name: service-account-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
containers:
- name: app-container
image: nginx
ports:
- containerPort: 80
volumes:
- name: service-account-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600 # Optional: expiration time in seconds
audience: kube-api-server # Optional: token audience
- configMap: # Mount the Kubernetes CA certificate
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
In this deployment, make sure the service account name exists in your namespace and has the necessary role bindings to the Kube API server.
For example, if it needs to list the status of a job, it should have a role binding for "List Job" from the Kube API.
Points to consider:
expirationSeconds
: should be atleast 10 minutes (600 seconds)configMap
: Since we are projecting volume to container, we may also need to explicitly mount the Kubernetes CA certificate (ca.crt
) alongside the token. This file is required to verify the identity of the Kubernetes API server when the service account token is used to authenticate API requests.
- Your container requires regular access to Kube API server
This should not be a usual concern; typically, your application does not need access to the Kube API server. However, if access is required, consider the following points.
You can consider mounting the token as a projected volume or enabling automatic token mounting to Pods. However, in this case, you need to ensure that the service account token has limited role bindings.
For example it requires to list status of other pods, then follow steps:
- Create a Role that allows listing Pods but nothing else.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default # Adjust if using a different namespace
name: pod-status-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "list"] # Only allow read permissions for Pods
- Create a RoleBinding that binds the Role to the specific ServiceAccount.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-status-reader-binding
namespace: <YOUR_NAMESPACE> # Add your own namespace
subjects:
- kind: ServiceAccount
name: <YOUR_SERVICE_ACCOUNT_NAME> # Name of your ServiceAccount
namespace: <Your_NAMESPACE> # Add your own namespace
roleRef:
kind: Role
name: pod-status-reader # The name of the Role created above
apiGroup: rbac.authorization.k8s.io
Now either mount it as projected volume or enable automountServiceAccountToken as true.
Validation:
You might also want to check if the token has been mounted to the container. To do this, log into the container's shell and list the directory /var/run/secrets/kubernetes.io/serviceaccount
. It should contain the token
and ca.crt
files.
This article clarifies the misconceptions about mounting tokens in containers to access the Kubernetes API server. It emphasizes the importance of understanding why you need the token, whether it should be long-lived or short-lived, and the level of access required. It discusses scenarios like using tokens in init-containers and regular access requirements, recommending best practices such as mounting tokens as projected volumes and ensuring limited role bindings for service account tokens.
Subscribe to my newsletter
Read articles from Ashutosh Rathore directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by