What Is a Kubernetes ServiceAccount and How Does It Relate to RBAC?

intermediate|rbacdevopssrecloud architectCKACKS
TL;DR

A ServiceAccount is an identity for processes running inside Pods. Kubernetes automatically mounts a token for the Pod's ServiceAccount, and RBAC bindings grant that ServiceAccount specific API permissions. Every namespace has a default ServiceAccount.

Detailed Answer

A ServiceAccount provides an identity for processes running in a Pod. While Users and Groups represent people or external systems, ServiceAccounts represent workloads — your applications, controllers, CI/CD agents, and operators.

How ServiceAccounts Work

When a Pod starts, Kubernetes mounts a token at /var/run/secrets/kubernetes.io/serviceaccount/token. The kubelet obtains this token from the TokenRequest API. When the Pod makes API calls, it presents this token, and the API server authenticates it as the corresponding ServiceAccount.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production
  labels:
    app: my-application

Assigning a ServiceAccount to a Pod

Specify the ServiceAccount in the Pod spec:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: production
spec:
  serviceAccountName: app-service-account
  containers:
    - name: app
      image: my-app:1.0
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"

If you omit serviceAccountName, the Pod uses the default ServiceAccount in its namespace.

ServiceAccount Token Evolution

Understanding the token mechanism is important for both interviews and security:

Before Kubernetes 1.24:

  • A Secret was automatically created for each ServiceAccount
  • The token was long-lived (never expired) and not audience-bound
  • This was a security risk — leaked tokens were valid indefinitely

Kubernetes 1.24 and later:

  • No auto-created Secret-based tokens
  • Tokens are issued by the TokenRequest API
  • Tokens are short-lived (default 1 hour), audience-bound, and automatically rotated
  • Projected as a volume into the Pod by the kubelet
# The projected token volume (automatically configured)
spec:
  containers:
    - name: app
      image: my-app:1.0
      volumeMounts:
        - name: kube-api-access
          mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          readOnly: true
  volumes:
    - name: kube-api-access
      projected:
        sources:
          - serviceAccountToken:
              expirationSeconds: 3607
              path: token
          - configMap:
              name: kube-root-ca.crt
              items:
                - key: ca.crt
                  path: ca.crt
          - downwardAPI:
              items:
                - path: namespace
                  fieldRef:
                    fieldPath: metadata.namespace

Connecting ServiceAccounts to RBAC

A ServiceAccount by itself has no permissions. You grant permissions by creating an RBAC binding:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: configmap-reader
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: production
  name: app-configmap-access
subjects:
  - kind: ServiceAccount
    name: app-service-account
    namespace: production
roleRef:
  kind: Role
  name: configmap-reader
  apiGroup: rbac.authorization.k8s.io

Now any Pod running as app-service-account can read ConfigMaps in the production namespace.

Disabling Token Mounting

Some Pods never need to talk to the Kubernetes API (most application Pods). You can disable the automatic token mount to reduce the attack surface:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: no-api-access
  namespace: production
automountServiceAccountToken: false

Or at the Pod level:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  serviceAccountName: no-api-access
  automountServiceAccountToken: false
  containers:
    - name: app
      image: my-app:1.0

Creating and Managing ServiceAccounts

# Create a ServiceAccount
kubectl create serviceaccount deploy-bot -n ci-cd

# List ServiceAccounts in a namespace
kubectl get serviceaccounts -n production

# Check which ServiceAccount a Pod uses
kubectl get pod my-app -n production -o jsonpath='{.spec.serviceAccountName}'

# Verify permissions of a ServiceAccount
kubectl auth can-i list pods \
  --as=system:serviceaccount:production:app-service-account \
  -n production

ImagePullSecrets with ServiceAccounts

ServiceAccounts can also carry image pull credentials, so every Pod using that ServiceAccount automatically pulls from a private registry:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production
imagePullSecrets:
  - name: registry-credentials

Best Practices

  1. Create dedicated ServiceAccounts for each workload instead of using default.
  2. Disable token mounting for Pods that do not need API access.
  3. Apply least-privilege RBAC — only grant the verbs and resources the workload actually needs.
  4. Audit ServiceAccount bindings regularly to detect privilege creep.
  5. Use projected tokens (default in 1.24+) and avoid manually creating long-lived Secret-based tokens.

Why Interviewers Ask This

Interviewers ask this to assess whether you understand in-cluster identity and authorization. Misconfigured ServiceAccounts are a common attack vector in Kubernetes security incidents.

Common Follow-Up Questions

What changed with ServiceAccount tokens in Kubernetes 1.24+?
Kubernetes 1.24 stopped auto-creating long-lived Secret-based tokens. Instead, the TokenRequest API issues short-lived, audience-bound tokens that are projected into Pods automatically.
How do you assign a ServiceAccount to a Pod?
Set spec.serviceAccountName in the Pod spec. If omitted, the Pod uses the default ServiceAccount in its namespace.
Can a ServiceAccount be used across namespaces?
A ServiceAccount exists in one namespace, but a ClusterRoleBinding can grant it cluster-wide permissions. The ServiceAccount itself cannot be moved to another namespace.

Key Takeaways

  • ServiceAccounts are the identity mechanism for workloads running inside the cluster.
  • Every namespace gets a default ServiceAccount, which should be locked down in production.
  • Modern Kubernetes uses projected, short-lived tokens instead of long-lived Secrets.
  • RBAC bindings link ServiceAccounts to specific permissions.

Related Questions