Introducing ServiceAccounts in Kubernetes

Reading Time: 4 minutes
What Is Kubernetes? - DZone DevOps

The concept of ServiceAccount is linked to other security related concepts in kubernetes such as Authentication, Authorization and Role based access controls etc.

So there are two types of accounts in Kubernetes. A user account and a service account.

A user account is for Humans and service account is for machines.

UserAccount: User account could be for an administrator accessing the cluster to perform administrative task, a developer accessing the cluster to deploy application etc.

ServiceAccount: A service account could be an account used by an application to interact with the kubernetes cluster. For example a monitoring application like Prometheus uses a service account to poll the kubernetes API for performance metrics . An automated tool like Jenkins uses service accounts to deploy application on the kubernetes cluster.

Let’s take an example. Suppose I have built a simple kubernetes dashboard application named, my kubernetes-dashboard. all that it does when deployed is retrieve the list of pods on a kubernetes cluster by sending a request to the kubernetes API and display it on a web page. In order for my application to query the kubernetes API it has to be authenticated. For that we use a service account.

Creating a ServiceAccount

Every namespace contains its own default Service Account but additional ones can be created if necessary.

But why should you bother with creating Service-Accounts instead of using the default one for all your pods?


The obvious reason is cluster security. Pods that don’t need to read any cluster metadata should run under a constrained account that doesn’t allow them to retrieve or modify any resources deployed in the cluster.

Pods that need to retrieve resource metadata should run under a ServiceAccount that only allows reading those objects’ metadata, whereas pods that need to modify those objects should run under their own ServiceAccount allowing modifications of API objects.

To create a service account run the command kubectl create service account followed by the account name, which is dashboard-sa in this case. To view the service accounts run the kubectl get serviceaccount command. This will list all the service accounts.

knoldus@knoldus-Vostro-3590:~$ kubectl create serviceaccount dashboard-sa
serviceaccount “dashboard-sa” created
knoldus@knoldus-Vostro-3590:~$ kubectl get serviceaccount

NAME           SECRETS   AGE
dashboard-sa   1         9s
default        1         2d20h
knoldus@knoldus-Vostro-3590:~$ kubectl describe serviceaccount dashboard-sa
Name:                dashboard-sa
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   dashboard-sa-token-hf4b9
Tokens:              dashboard-sa-token-hf4b9
Events:              <none>

When you create a service account it also creates a token automatically. In this case its named dashboard-sa-token-hf4b9.

To view the token, view the secret object by running the command kubectl describe secret.

knoldus@knoldus-Vostro-3590:~$ kubectl describe secret dashboard-sa-token-hf4b9
Name:         dashboard-sa-token-hf4b9
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: dashboard-sa
              kubernetes.io/service-account.uid: 651318a2-cc8c-4e03-86ec-5487ae07ea3a

Type:  kubernetes.io/service-account-token

Data
====
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IklKZW0zRWN0bWt5UW9GbEdQTXBZMTdyQ2tjNTlvOHRYSnBuQ2dyd2lwaDgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRhc2hib2FyZC1zYS10b2tlbi1oZjRiOSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkYXNoYm9hcmQtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2NTEzMThhMi1jYzhjLTRlMDMtODZlYy01NDg3YWUwN2VhM2EiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkYXNoYm9hcmQtc2EifQ.bawWm7td0agD2nBYK1zW-czrJtYumE4MqP9IAhoLJqju4a0jZMZNyUiqkERGQPBQuAed9qZWSpIIz_JtlF87X-9hSCdDSgJUHk1GM5LngeG4y85xQyuBmhg9rBNnjQYQJoaw4svHT5fweQmQoW3BV-s5A-yw6uSHMd-9aHGk9m_Bv4KO5ccrpAstuFgPYsQPXXB9arNgvIRYyGM50SiILOJsEavzOT9CJakbLOdnrt4-UHiXXk0SLjyQKFFuZ5WYXOPTRJO1vTM6xfQ2QzC-eXkw5A23bFsyxOWa_YuL4bdnbXpltzla6clxgAwAeDWCfOjXKMTvqvABPmZkILtCww
ca.crt:     1111 bytes

Assigning ServiceAccount to a Pod

After you create additional serviceaccount, you need to assign them to pods by setting the serviceaccount name in spec.serviceAccountName field in the pod definition.


NOTE: A pod’s service account must be attach when creating the pod. It can not be change later.

Pod using a non-default ServiceAccount: curl-custom-sa.yaml

apiVersion: v1
kind: Pod
metadata:
  name: custom-sa
spec:
  serviceAccountName: dashboard-sa   ## as created above
  containers:
  - name: main
    image: busybox:latest
    command: ["sleep", "999"]

Now create pod using kubectl command:

knoldus@knoldus-Vostro-3590:~$ kubectl create -f custom-sa.yml
pod/custom-sa created

We can check that the service account token is attach to the container by the following command.

knoldus@knoldus-Vostro-3590:~$ kubectl exec -it custom-sa -c main cat /var/run/secrets/kubernetes.io/serviceaccount/token 
 
eyJhbGciOiJSUzI1NiIsImtpZCI6IklKZ......

You can see the token is the one from the dashboard-sa ServiceAccount by comparing the token string from above.

But what if our application is an integral part of the cluster itself and lies into one of the PODs

In this scenario, when any pod is created in the Kubernetes cluster with any given namespace, these pods by default creates a service account with the name default. The default service account automatically creates the service token along with the required secret object.

So our application will be able to access the API server lying within the same namespace, by using this default service account mounted in the pod.

For instance, type the below-given command on your terminal:

knoldus@knoldus-Vostro-3590:~$ kubectl get serviceaccount
NAME         SECRETS  AGE
dashboard-sa  1       4d21h
default       1       4d21h

you will see the default secret as highlighted above, and if you go further to type the below set of commands to access the default secret attached with the default token

knoldus@knoldus-Vostro-3590:~$ kubectl get secret
NAME                       TYPE                                  DATA   AGE
dashboard-sa-token-74prf   kubernetes.io/service-account-token   3      4d21h
default-token-f4tpq        kubernetes.io/service-account-token   3      4d21h

To view the secret object detail against the default token, default-token-f4tpq. Type the following command:

knoldus@knoldus-Vostro-3590:~$ kubectl describe secret default-token-f4tpq
Name:         default-token-f4tpq
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: 1630cc0f-b611-4782-9213-bf0ada130271

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1111 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6Inp2UkRFMmlLQ0UtQkpDT1ZOTkNuVG1CcFRlaFdzU210RDN5a2thUmlvNEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tZjR0cHEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjE2MzBjYzBmLWI2MTEtNDc4Mi05MjEzLWJmMGFkYTEzMDI3MSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.Qq6rlJtFLy-G7LGc58fLe97EENvdUSWM_B6F1oGfKsYquEu1eppniUOJ6Hg19RBXgM-7EBewilcb_j0yACtm7MMzqvQr7PYCPm431rjbBILFqElqFU1NNYuewmfFTjp7VDghafnsZFos1Iv_0LAf2G38CLTfKfkc_HJ8ZuHCskf4_7uEBdbXJRcF0ktYu2KoMD2JKM9NypAZ8D9yg1XO3JFuAE3mR5ivzyIeLDYG74q9HMcaM014N3TAr2wJYdgrUSNFkrBeEBv_MiDXGAqqyxIjDB4km3F_WJ7bTEwukWIwkP6qjw5x2YlIYV8IVe92w9FcT6d9WAVStNMWS-omEw

So for our application hosted in the pod with the same namespace, this default secret object can be used to give access to the API servers lying in the same cluster namespace.

Conclusion

Service accounts are a powerful tool for cluster administration because you can use them to control and view access of resources in Kubernetes. You can use them to limit access to a particular namespace. You should limit pods to access only to what they need. The ability to know who accessed which resources and when they accessed them provides insight into cluster activity.

Did I get something wrong? have any suggestions to make it even better ?Let me know in the comments, I would love to hear your thoughts!

If you wanna learn more about Kubernetes head over to the following link you will find some amazing blogs.

https://blog.knoldus.com/?s=kubernetes

References:

https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/

Written by 

Jubair Ahmad is a Software Intern at Knoldus.Inc.He loves learning new technology and also have interest in playing cricket.