TEAM IM Insights

Kubernetes Developer Tools - Service Account

Written by Mat Thomas | Jul 9, 2024 4:00:00 PM

Configure a service account which can access the Kubernetes API to pull back data to be exposed to developers.

Kubernetes Service Account

In my previous insight, I detailed out the high level approach for our k8s dev tools application.  This relies on a Kubernetes service account which is used to make API calls to the Kubernetes API server.  This can be granted specific permissions depending on what data it needs access to.  Service Accounts are assigned to pods to allow that pod to automatically make requests without human interaction.  This is how we expose specific data to developers without the developers needing access to the underlying API.

Creating a Kubernetes Service Account

The simplest way to create a service account is defining it in a yaml file and using kubectl apply to configure it in your k8s cluster.  In my examples, I'll be creating a service account named dev-tools in the default namespace.  The yaml for this is:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dev-tools
  namespace: default

This simply creates the service account, to add permissions, a Role object also needs to be created.  For now, we won't assign any permissions.  The yaml for this is:

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

Then to tie permissions to the service account, one final yaml needs to be created:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-tools
  namespace: default
subjects:
- kind: ServiceAccount
  name: dev-tools
  namespace: default
roleRef:
  kind: Role
  name: dev-tools-reader

These should each be run using the following kubectl command:

kubectl apply -f <filename>.yaml

Then to assign the service account to a pod, this can be added in a deployment/stateful set under spec.template.spec.serviceAccountName or in a pod under spec.serviceAccountName and redeploying the deployment/stateful set/pod.

Validating the service account is set up as expected

Once the service account has been configured and associated with a pod, we can validate it can make a basic call to the k8s API.  To do this, first connect to the pod (ideally a linux pod although similar commands could likely be run in a Windows pod) using kubectl:

kubectl exec --stdin --tty <pod name> -- /bin/bash

Then run the following commands from the pod's command line:

SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
TOKEN=$(cat ${SERVICEACCOUNT}/token)
CACERT=${SERVICEACCOUNT}/ca.crt
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET https://kubernetes.default.svc/api/v1/namespaces/default/pods

This should return something like:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.49.2:8443"
    }
  ]

Further reading

We'll be further exploring permissions and API endpoints in the next couple articles:

Pods: https://www.teamim.com/insights/kubernetes-developer-tools-displaying-application-version

Logs: https://www.teamim.com/insights/kubernetes-developer-tools-retrieving-application-logs