Kubernetes service accounts, and creating kubeconfig for one

Official kubernetes docs say

A service account is a type of non-human account that, in Kubernetes, provides a distinct identity in a Kubernetes cluster.

Service accounts can be used for providing access both to components inside the cluster and other services from outside the cluster. For example, I use a service account to give access to GitHub actions to deploy new version of the WebGazer on a new release.

"But I already have a kubeconfig that I use with kubectl, managing the cluster"

Please don't copy/paste your cluster-admin role kubeconfig 🙃 If you do, that allows other party to do whatever they want to do to every resource, on every namespace, cluster-wide. Even if the tool or service you create the service account is very trustworthy, and not malicious; there might be a bug in their systems somehow accidentally editing or deleting unexpected resources.

That's why you should create a service account specific for that tool or service, and with limited permissions that is enough for what you expect the tool or service to do (see Principle of least privilege). You know, better safe than sorry.

A service account, a role and a role binding

For the GitHub actions deploying WebGazer on the cluster case, my configuration is similar to this:

ServiceAccount and its token secret

apiVersion: v1
kind: ServiceAccount
metadata:
  name: webgazer-github
  namespace: default

serviceaccount-webgazer-github.yaml

apiVersion: v1
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: webgazer-github
  name: webgazer-github-token
  namespace: default
type: kubernetes.io/service-account-token

secret-webgazer-github.yaml

Before version 1.24, Kubernetes created secret for the service account automatically. But after 1.24, we manually need to create a secret.

From kubernetes docs

Role and binding

The rules in the Role resource is the important. That is where you allow the service account to do certain stuff on the cluster.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: webgazer-github
  namespace: default
rules:
- verbs: ["*"]
  apiGroups: ["", apps, batch, networking.k8s.io, rbac.authorization.k8s.io]
  resources: ["*"]

role-webgazer-github.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: webgazer-github
  namespace: webgazer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: webgazer-github
subjects:
- kind: ServiceAccount
  name: webgazer-github
  namespace: default

RoleBinding

Creating kubeconfig for service account

There are some shell scripts you can find on the internet. But the most convenient method I found is Kazuki Suda's view-serviceaccount-kubeconfig kubectl plugin.

You will need krew to install that plugin, which is the most popular kubectl package I know. I used homebew to install krew:

$ brew install krew

To see other methods you can use to install krew, head over to krew's installation docs.

Once you have krew installed, you can install view-serviceaccount-kubeconfig plugin, too:

$ kubectl krew install view-serviceaccount-kubeconfig

And then you can use the plugin to create the kubeconfig:

$ kubectl view-serviceaccount-kubeconfig \
  --namespace default \
  webgazer-github

And it will output the kubeconfig's content. You can use that kubeconfig wherever you need to access the cluster with the service account you created.