Automatically mounting ServiceAccount tokens as Secrets exposes four security risks: tokens with no audience binding, overprivileged system-component accounts, tokens that never expire, and one Secret per service account that limits cluster scalability. ServiceAccount Token Volume Projection eliminates all four risks by mounting tokens directly as projected volumes—no Secrets required—with configurable audience binding, automatic rotation, and a configurable expiration time.
Why use token volume projection
The traditional method stores each ServiceAccount in a Secret and mounts it into pods as a file. This creates the following problems:
-
No audience binding: JSON Web Tokens (JWTs) are not bound to
audienceidentities, so a service account holder can impersonate another user and launch masquerade attacks. -
Broad attack surface: System components often carry more permissions than they need. If an attacker obtains those service accounts, they can launch privilege escalation attacks against the Kubernetes control plane.
-
No expiration: JWTs remain valid as long as the service account exists. Revoking a compromised token requires rotating the signing key—a complex manual process that client-go does not automate.
-
Secret proliferation: One Secret per service account reduces elasticity and capacity in large-scale workload deployments.
ServiceAccount token volume projection addresses all four issues. Pods mount tokens as projected volumes, avoiding any dependency on Secrets, with support for audience binding, expiration, and automatic rotation.
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
-
ServiceAccount Token Volume Projection enabled on the cluster. The feature is enabled by default in clusters running Kubernetes 1.22 or later. To upgrade your cluster, see Manually upgrade ACK clusters
When the feature is enabled, the API server and controller-manager automatically set the required feature gate and add the following startup parameters to the API server:
| Parameter | Description | Default value | Console configuration |
|---|---|---|---|
service-account-issuer |
The issuer of the ServiceAccount token, corresponding to the iss field in the token payload. |
https://kubernetes.default.svc |
Supported |
api-audiences |
Identifiers used to validate request tokens for the API server. Configure multiple audiences separated by commas (,). |
https://kubernetes.default.svc |
Supported |
service-account-signing-key-file |
The file path of the private key used to sign the token. | /etc/kubernetes/pki/sa.key |
Not supported. Default value: /etc/kubernetes/pki/sa.key |
Step 1: Create a ServiceAccount
Each namespace includes a default ServiceAccount. Run the following command to view existing service accounts:
kubectl get serviceaccounts
To assign a dedicated identity to your pod's processes, create a new 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 ServiceAccount token volume projection
Project a ServiceAccount token into a pod as a volume so the container can authenticate with the cluster's API server. The following example configures a token with an audience of vault and an expiration time of 2 hours (7200 seconds).
-
Create a file named
nginx.yamlwith the following content: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 -
Deploy the pod:
kubectl apply -f nginx.yaml -
Verify that the token is mounted with the correct expiration time.
-
Confirm that the pod is running:
kubectl get pod nginxExpected output:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 3m15s -
Download the token from the pod:
kubectl exec -t nginx -- cat /var/run/secrets/tokens/vault-token > vault-token -
Decode the token and check its expiration 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
-
Token rotation and file permissions
Token rotation
Ensure that the pod can retrieve the latest rotated token in real time by periodically reloading the target token, preferably every 5 minutes. Official Kubernetes supports automatic token retrieval in client-go version 10.0.0 or later.
File permissions
The file permissions for the ServiceAccount token in the container change when you use token volume projection:
| Configuration | Permission |
|---|---|
| Traditional ServiceAccount token (mounted from Secret) | 644 |
| Bound ServiceAccount token volume projection | 600 |
Bound token with fsGroup enabled |
640 |
What's next
-
Configure ServiceAccount RAM permissions for pod access control through RRSA to achieve pod-level API access isolation and fine-grained access control to cloud resources.
-
Use Alibaba Cloud KMS for disk encryption to encrypt Kubernetes secret keys in ACK Pro clusters.
-
Configure service accounts for pods in the Kubernetes documentation.