Kubernetes Service Accounts

As a developer or a cluster admin, you interact with the Kubernetes apiserver via kubectl. A ServiceAccount is a Kubernetes object that allows an application running inside a Pod to access the Kubernetes apiserver. This is useful for applications that need to interact directly with the Kubernetes API, such as monitoring tools.  A ServiceAccount allows an application to talk to the apiserver securely with the appropriate permissions.

A ServiceAccount is defined as follows.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-service-account

The ServiceAccount itself is of little use unless you associate it with a set of roles. To do this you’ll need to create a Role.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader-role
rules:
  - apiGroups: [ "" ] # "" indicates the core API group
    resources: [ "pods" ]
    verbs: [ "get", "watch", "list" ]

This Role describes the APIs that the Role owner will have access to as well as resources and access to those resources. In this instance the Role can get, watch and list pods.

To associate a Role with a ServiceAccount, you need to create a RoleBinding. A RoleBinding linking the pod-reader-role to the sample-service-account is defined below.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-role-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: sample-service-account
    namespace: default
roleRef:
  kind: Role
  name: pod-reader-role # this must match the name of the Role you want to bind to
  apiGroup: rbac.authorization.k8s.io

Finally, we can create a Pod that references the ServiceAccount by setting the serviceAccountName in the Pod spec as follows.

apiVersion: v1
kind: Pod
metadata:
  name: service-account-pod
spec:
  serviceAccountName: sample-service-account
  containers:
    - name: service-account-pod
      image: busybox
      command: [ 'sh', '-c', 'echo container started & sleep 3600' ]

Next, create the various objects on the cluster as follows.

When the Pod starts you can exec into the container and get the ServiceAccount token from /var/run/secrets/kubernetes.io/serviceaccount/token. You can then use the token to make an authenticated call to the Kubernetes API.

Given the ServiceAccountRole and RoleBinding created earlier, we have the required privileges to retrieve a list of Pods from the API.

If we cat index.html we’ll see a list of Pod details.

The sample code for these notes is available here.