Creating A Kubernetes Service Account To Run Pods

Michael Levan - Aug 3 '22 - - Dev Community

When you create any type of resource in Kubernetes, whether it’s a standard Pod, or a higher level controller that manages Pods like a Deployment or DaemonSet, the resource is deployed with a service account inside of Kubernetes.

Understanding what that service account does, and more importantly, the implications of using a service account to create Pods is crucial for any successful production deployment.

In this blog post, you’re going to learn about service accounts in Kubernetes.

What’s A Service Account?

A service account is how workloads in Kubernetes run. It contains RBAC permissions that give it the ability to deploy resources to a Kubernetes cluster. Service accounts are used to connect to the Kubernetes API server.

Service accounts can also give you the ability to connect to other services, for example, workloads running in GCP that a Kubernetes cluster may need access to. For example, a service account that can act as an IAM service account inside of GCP using Workload Identity.

Why Create A Service Account?

By default, when you create a Pod, the default Kubernetes service account is used.

Let’s say you have a Pod running, you can run the following command and see the spec.ServiceAccountName field.



kubectl get pods -o yaml


Enter fullscreen mode Exit fullscreen mode

Since there’s already a service account being used, you may be asking yourself why do I need to manually create a service account if it already exists? of which there’s one big reason - security.

The biggest reason is from a security perspective. If you’re using the same service account over and over again and that service account gets compromised, all of your applications are in big trouble. If a malicious entity obtains access to the default service account that’s deploying every workload inside of Kubernetes, that means it’ll ultimately have access to every Pod that’s running in the cluster. It’ll also allow any compromised Pod to run API calls against the cluster.

Another reason, although not as important as the security piece, is the cleanliness of the environment. Think about it like this - imagine every Sysadmin used the same email account for every single service that the infrastructure department uses or a developer generating and using the same API key for authentication across all applications. Not only is it a bad security practice, but it’s not a good practice in general.

Creating A Service Account

Now that you know why you want to use a different service account other than the Kubernetes default, let’s learn how to set it up.

For the purposes of this blog post, you’ll create a service account that’s tied to a specific namespace.

First, you’ll need to create a namespace. The example below shows a namespace called levantest that you can create.

Save the Kubernetes Manifest namespace code below as namespace.yaml



apiVersion: v1
kind: Namespace
metadata:
  name: levantest


Enter fullscreen mode Exit fullscreen mode

Create the namespace:



kubectl apply -f namespace.yaml


Enter fullscreen mode Exit fullscreen mode

Next, you need to create the service account and give it certain permissions. You’ll need to create:

  • The service account
  • A Role for the service account
  • A RoleBinding to bind the Role so you can use it on the service account

The below YAML creates a service account called app1serviceaccount, gives it permissions to create, get, watch, and list, and binds it to the levantest namespace.

Save the Kubernetes Manifest below and call it serviceaccount.yaml



apiVersion: v1
kind: ServiceAccount
metadata:
  name: app1serviceaccount
  namespace: levantest
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: levantest
  name: pod-creator
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-creator
  namespace: levantest
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-creator
subjects:
- kind: ServiceAccount
  name: app1serviceaccount
  namespace: levantest


Enter fullscreen mode Exit fullscreen mode

Run the following command to create the resource:



kubectl apply -f serviceaccount.yaml


Enter fullscreen mode Exit fullscreen mode

You should see an output similar to the screenshot below.

Image description

Next, let’s use the service account to create a Pod.

Using A Service Account

Now it’s time to create a Pod with the service account that you created.

The Kubernetes Manifest below creates a Pod resource that deploys a Pod running Nginx with no high-level controller (Deployment, DaemonSet, etc.) and utilizes the newly created service account.

Save the Kubernetes Manifest as pod.yaml



apiVersion: v1
kind: Pod
metadata:
  name: nginxpod
  namespace: levantest
spec:
  containers:
  - image: nginx:latest
    name: nginxpod
  serviceAccountName: app1serviceaccount


Enter fullscreen mode Exit fullscreen mode

Run the following command to deploy the Pod.



kubectl apply -f pod.yaml


Enter fullscreen mode Exit fullscreen mode

Once running, you can see the output of the Pod to confirm it’s using the appropriate service account.



kubectl get pods -n namespace_name -o yaml


Enter fullscreen mode Exit fullscreen mode

You should see an output similar to the screenshot below, which under spec will show the service account.

Image description

Congrats! You have successfully created and used a new service account for Pod deployments.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .