CKA Study notes - Service Accounts in Kubernetes Pods - 2024 edition
Continuing with my Certified Kubernetes Administrator exam preparations I'm now going to take a look at ServiceAccounts
.
This is an updated version of a similar post I created around three years ago. Things have changed since then so a new post was called for
Service Accounts provides an distinct identity
in a Kubernetes cluster. A Service Account can be used by Pods and other system components to access and communicate through the API scheduler. Service accounts is also a way for external services to authenticate to the cluster.
Service Accounts are namespaced meaning that they are created in and bound to a Kubernetes namespace
. Every namespace has a default service account.
Note #1: I'm using documentation for version 1.28 in my references below as this is the version used in the current (jan 2024) CKA exam. Please check the version applicable to your usecase and/or environment
Note #2: This is a post covering my study notes preparing for the CKA exam and reflects my understanding of the topic, and what I have focused on during my preparations.
Service account in Pods
One of the use cases for a service account is to give a Pod a specific access to specific resources, for instance a secret.
Let's first check the default service account in our default namespace
1kubectl get serviceaccounts
2kubectl describe serviceaccounts default
The default service account in the default namespace has nothing configured.
When a Pod gets scheduled it's getting a ServiceAccount
assigned. If you're not specifying anything the default Service account in the namespace is used. Let's take a look
1kubectl get pod -o=custom-columns='Name:.metadata.name','ServiceAccount:.spec.serviceAccount'
In our default namespace there's several Pods running, all of them are using the default service account.
Let's take a look at one of the other namespaces in the cluster
1kubectl get ns
2kubectl get serviceaccounts -n calico-system
3kubectl get pod -o=custom-columns='Name:.metadata.name','ServiceAccount:.spec.serviceAccount' -n calico-system
In the calico-system
namespace we can see that some of the Pods specific service accounts assigned whereas some are using the default service account.
For information about the installation of Calico in this cluster, please refer to this post
Service Accounts are used with the built-in Kubernetes role-based access control (RBAC) to grant (and thereby restrict) permissions in the Cluster. This is done by creating a Role
and bind a Service Account to this role. More on that in an upcoming post.
Create service account
Now let's try to create our own ServiceAccount and use this in a Pod
1kubectl create serviceaccount my-first-sa
2kubectl get serviceaccount
Now to assign this to a new Pod we'll create a Pod manifest and apply this in our cluster
1apiVersion: v1
2kind: Pod
3metadata:
4 name: sa-pod-demo
5spec:
6 containers:
7 - name: sa-pod
8 image: nginx
9 serviceAccount: my-first-sa
1kubectl apply -f sa-pod-demo-1.yaml
2kubectl get pod -o=custom-columns='Name:.metadata.name','ServiceAccount:.spec.serviceAccount'
3kubectl describe pod sa-pod-demo
As we can see our new Pod is now assigned with my-first-sa
as the Service Account. Note that at this point this service account doesn't do anything to or from.
Service account with secret
Now we'll see how to put the service account to use, but first we'll try to deploy a Pod based on a custom Nginx image from a private Docker Hub repository, note that we are using the Service Account we previously created.
1apiVersion: v1
2kind: Pod
3metadata:
4 name: nginx-test
5 labels:
6 app: nginx-test
7spec:
8 containers:
9 - name: web-test
10 image: rumart/web-test:0.0.1
11 serviceAccount: my-first-sa
1kubectl apply -f nginx-rumart.yaml
2kubectl get pod
As we can see the status of the Pod isn't Running
as the others, this time we have an ErrImagePull
status.
If we dig a little deeper we can see the reason why
1kubectl describe pod nginx-test
So the Kubernetes node fails to pull the container image from Docker Hub because they are missing access
To fix this let's create an imagePullSecret
and add this to our Service Account.
I already have a Docker credential on my client machine which will be used to create the imagePullSecret. For more information about this take a look at the official Kubernetes documentation
1ls ~/.docker
2kubectl create secret generic rudi-docker --from-file=.dockerconfigjson=~/.docker/config.json --type=kubernetes.io/dockerconfigjson
3kubectl get secret
Next step is to add this secret to the Service Account
Add imagePullSecret to ServiceAccount
Kubernetes documentation reference
1kubectl patch serviceaccount my-first-sa -p '{"imagePullSecrets": [{"name": "rudi-docker"}]}'
2kubectl get sa my-first-sa -o yaml
Redeploy Pod
Now, let's verify that this works by re-applying our Pod specification that uses the custom image. First we'll have to delete the existing, failing, pod
1kubectl delete -f nginx-rumart.yaml
2kubectl apply -f nginx-rumart.yaml
3kubectl get pod
Let's verify that our Pod is using our Service Account and that we are running the correct image
1kubectl describe pod nginx-test
Summary
There's a lot more to service accounts, pod security and role based access control (RBAC). Please refer to the Kubernetes documentation for more information
Thanks for reading, and please reach out if you have any questions or comments