All Products
Search
Document Center

Container Service for Kubernetes:Use ServiceAccount token volume projection

Last Updated:Jul 16, 2026

ServiceAccount tokens authenticate communication between pods and the Kubernetes API server. The traditional approach stores tokens in Secrets and mounts them as files—leaving pods exposed to impersonation attacks, privilege escalation, and stale tokens that never expire. Service Account Token Volume Projection eliminates these risks by mounting short-lived, audience-bound tokens directly as projected volumes, without relying on Secrets.

Background

Traditional ServiceAccount tokens have four structural security weaknesses:

  • Unbound audience: JSON Web Tokens (JWTs) carry no audience restriction, so a compromised token can be replayed against any service in the cluster, enabling impersonation attacks.

  • Overprivileged Secrets: Tokens are stored in Secrets and delivered as files to nodes. System-component tokens often carry permissions beyond what individual workloads need, expanding the attack surface.

  • No expiry: JWTs remain valid for the entire lifetime of the ServiceAccount. Rotating them requires manually replacing the signing key—a process client-go does not automate.

  • Secret sprawl: One Secret per ServiceAccount degrades cluster elasticity at scale.

ServiceAccount token volume projection addresses all four problems. Tokens are scoped to a specific audience, expire after a configurable period, and are automatically rotated by the kubelet—no Secrets required.

How it works

When a pod with a projected ServiceAccount token volume starts, the kubelet requests a short-lived, signed token from the API server and writes it to the configured mount path inside the container. The kubelet monitors the token and proactively requests a replacement before it expires. The application is responsible for reloading the token file when it rotates; polling every five minutes is sufficient for most workloads.

Prerequisites

Before you begin, ensure that you have:

  • An ACK managed cluster, ACK dedicated cluster, or ACK Serverless cluster running Kubernetes 1.20 or later. See Create an ACK managed cluster, Create an ACK dedicated cluster (discontinued), and Create an ACK Serverless cluster.

  • Service Account Token Volume Projection enabled on the cluster. The feature is on by default in clusters running Kubernetes 1.22 or later. To upgrade, see Manually upgrade ACK clusters.

    When enabled, the API server and controller-manager automatically configure the following startup parameters:

    ParameterDescriptionDefault valueConsole configurable
    service-account-issuerThe token issuer, mapped to the iss field in the JWT payloadhttps://kubernetes.default.svcYes
    api-audiencesAPI identifiers used to validate incoming tokens. Separate multiple values with commas (,).https://kubernetes.default.svcYes
    service-account-signing-key-filePath to the private key used to sign tokens/etc/kubernetes/pki/sa.keyNo (fixed at default)

Step 1: Create a ServiceAccount

Each namespace includes a default ServiceAccount. Run kubectl get serviceaccounts to list existing accounts in the current namespace.

To assign a distinct identity to a pod, create a dedicated ServiceAccount:

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
EOF

Verify the ServiceAccount was created:

kubectl get serviceaccounts/build-robot -o yaml

Step 2: Deploy a pod with token volume projection

The following example mounts a projected ServiceAccount token into an nginx pod. The token is scoped to the vault audience and expires after two hours (7200 seconds).

  1. Create a file named nginx.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
        name: nginx
        volumeMounts:
        - mountPath: /var/run/secrets/tokens
          name: vault-token
      serviceAccountName: build-robot
      volumes:
      - name: vault-token
        projected:
          sources:
          - serviceAccountToken:
              path: vault-token
              expirationSeconds: 7200
              audience: vault
  2. Apply the manifest:

    kubectl apply -f nginx.yaml

Verify token expiry

  1. Confirm the pod is running:

    kubectl get pod nginx

    Expected output:

    NAME    READY   STATUS    RESTARTS   AGE
    nginx   1/1     Running   0          3m15s
  2. Extract the token from the container:

    kubectl exec -t nginx -- cat /var/run/secrets/tokens/vault-token > vault-token
  3. Decode the token and print its expiry time:

    cat vault-token | awk -F '.' '{print $2}' | base64 -d 2>/dev/null | jq '.exp' | xargs -I {} date -d @{}

    Sample output:

    Mon  Aug 26 15:45:59 CST 2024

Usage notes

Token rotation: The kubelet automatically rotates the token before it expires. Configure your application to reload the token file on a schedule—polling every five minutes is sufficient regardless of the actual TTL.

SDK compatibility: Automatic token reloading in Go requires client-go version 10.0.0 or later.

File permissions: The ServiceAccount token file permission changes from 644 to 600 when using bound token volume projection. If fsGroup is set in the pod's security context, the permission is 640.

What's next