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.


  1. 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.

  1. 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.

0
Subscribe to my newsletter

Read articles from Ashutosh Rathore directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ashutosh Rathore
Ashutosh Rathore