Cart

    Sorry, we could not find any results for your search querry.

    Using a ServiceAccount for each application in Kubernetes

    Every application in Kubernetes runs under an identity. If you do not configure one, a workload uses the namespace's `default` ServiceAccount. This complicates security, auditing, and troubleshooting.

    Therefore, use a separate ServiceAccount for each application. This lets you assign permissions precisely, disable API access for workloads that do not need it, and identify more quickly which workload performed an action.

    • Create a dedicated ServiceAccount for each application or component.
       
    • Disable `automountServiceAccountToken` if an application does not need to use the Kubernetes API.
       
    • Assign permissions only after determining which API calls the application actually needs.
     

     

    Create two ServiceAccounts: one with and one without API access

     

    Step 1

    Create a .yaml file, for example:

    nano serviceaccounts-demo.yaml

    Add the following content to the file:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: kb-sa-test
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: app-api
      namespace: kb-sa-test
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: app-noapi
      namespace: kb-sa-test
    automountServiceAccountToken: false
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: configmap-reader
      namespace: kb-sa-test
    rules:
      - apiGroups: [""]
        resources: ["configmaps"]
        verbs: ["get", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: app-api-configmap-reader
      namespace: kb-sa-test
    subjects:
      - kind: ServiceAccount
        name: app-api
        namespace: kb-sa-test
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: configmap-reader
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: sample-config
      namespace: kb-sa-test
    data:
      example: ok
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: noapi-pod
      namespace: kb-sa-test
    spec:
      serviceAccountName: app-noapi
      automountServiceAccountToken: false
      restartPolicy: Never
      containers:
        - name: busybox
          image: busybox:1.36
          command: ["/bin/sh", "-c", "sleep 3600"]

    Save the changes and close the file (ctrl + x > y > enter).


     

    Step 2

    Create the resources:

    kubectl apply -f serviceaccounts-demo.yaml
    kubectl -n kb-sa-test wait --for=condition=Ready pod/noapi-pod --timeout=180s

    You now have one ServiceAccount with limited API permissions and one ServiceAccount without a token mount for workloads that do not need to use the API.


     

    Check the differences between the two ServiceAccounts

     

    Step 1

    Check whether `app-api` is allowed to read ConfigMaps in its own namespace:

    kubectl auth can-i list configmaps \
      --as=system:serviceaccount:kb-sa-test:app-api \
      -n kb-sa-test

    The expected result is `yes`.


     

    Step 2

    Check that `app-noapi` is not allowed to perform the same action:

    kubectl auth can-i list configmaps \
      --as=system:serviceaccount:kb-sa-test:app-noapi \
      -n kb-sa-test

    The expected result is `no`.


     

    Step 3

    Then check that the pod without API access does not have a ServiceAccount token mounted:

    kubectl -n kb-sa-test exec noapi-pod -- ls /var/run/secrets/kubernetes.io/serviceaccount

    You should receive an error stating that the path does not exist. This is intentional: the pod cannot accidentally use the Kubernetes API.


     

    Use the correct ServiceAccount in your Deployment

     

    Always explicitly reference the correct ServiceAccount in a Deployment or StatefulSet:

    spec:
      serviceAccountName: app-api
      automountServiceAccountToken: true

    For an application that does not need API access, use:

    spec:
      serviceAccountName: app-noapi
      automountServiceAccountToken: false

    This keeps the behaviour of your workload predictable, even if someone later changes the namespace's `default` ServiceAccount.


     

    Separate ServiceAccounts for each application make permissions, token mounts, and auditing much clearer. Always combine this with RBAC so that a ServiceAccount cannot do more than a workload actually requires.

    Need help?

    Receive personal support from our supporters

    Contact us