【Kubernetes】ServiceAccountについて理解する

2022.06.11
2024.03.24
Kubernetes

本ページはAmazonアフィリエイトのリンクを含みます。

はじめに

Service Accountについて、動かしながら基本的な部分を理解していきたいと思います。

ServiceAccountとは

サービスアカウント(Service Account)は、Kubernetes内で管理されているアカウントで、Podと紐づけることでPodからKubernetesAPIを操作できるようになります。

【Kubernetes】ユーザー管理について理解する

【Kubernetes】ユーザー管理について理解する

はじめに Kubernetesのユーザーについてざっくりまとめて、実際にユーザーを作成(?)して

Service Accountは、Podに紐づいたAPIの認証情報であるtokenを利用して、PodからKubernetesAPIを利用します。

ver1.24から、今まで自動で作成されていたtoken用のSecretが作成されなくなり、Pod内にtokenが紐付くようになったようです。

kubernetes/CHANGELOG/CHANGELOG-1.24.md at master · kubernetes/kubernetes

kubernetes/CHANGELOG/CHANGELOG-1.24.md at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

Secrets

Secrets

A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Such information might otherwise be put in a Pod specification or in a container image. Using a Secret means that you don't need to include confidential data in your application code.

unknown link

defaultのServiceAccount

まずは、各Namespaceにデフォルトで作成されるdefaultというServiceAccountについて、確認していきます。

1❯ kubectl get sa
2NAME      SECRETS   AGE
3default   0         4h39m
4
5
6❯ kubectl describe sa default
7Name:                default
8Namespace:           default
9Labels:              <none>
10Annotations:         <none>
11Image pull secrets:  <none>
12Mountable secrets:   <none>
13Tokens:              <none>
14Events:              <none>

自分で作成していないdefaultというServiceAccountが確認できます。また、SECRETSの列が0になっており、tokenも紐づいていなくなっていることがわかります。

defaultのServiceAccountとPod

このdefaultというアカウントがどのように使われているか確認します。

まず、簡単なPodを作成します。

1apiVersion: v1
2kind: Pod
3metadata:
4  name: nginx
5spec:
6  containers:
7  - image: nginx
8    name: nginx
1kubectl apply -f nginx.yml

作成されたPodをyaml形式で確認してみます。

1❯ kubectl get pod
2NAME    READY   STATUS    RESTARTS   AGE
3nginx   1/1     Running   0          19s
4
5
6❯ kubectl get pod nginx -o yaml
7apiVersion: v1
8kind: Pod
9
10...
11
12spec:
13  containers:
14  - image: nginx
15    imagePullPolicy: Always
16    name: nginx
17
18    ...
19
20    volumeMounts:
21    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
22      name: kube-api-access-d9mtw
23      readOnly: true
24
25  ...
26
27  serviceAccount: default
28  serviceAccountName: default
29
30  ...
31
32  volumes:
33  - name: kube-api-access-d9mtw
34    projected:
35      defaultMode: 420
36      sources:
37      - serviceAccountToken:
38          expirationSeconds: 3607
39          path: token
40
41...

defaultのServiceAccountが自動で利用されており、token用のボリュームがマウントされていることが確認できます。

マウントされているtokenのファイルを見てみます。

1❯ kubectl exec -it nginx -- ls /var/run/secrets/kubernetes.io/serviceaccount
2ca.crt  namespace  token
3
4
5❯ kubectl exec -it nginx -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
6eyJhbGciOiJSUzI1NiIsImtpZCI6InF2TDhTTHNtenhubFpZcnpwbU5UV2hOSjlYWHpyY0loNzdDREJIZGdwa0kifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg2NDU5ODk1LCJpYXQiOjE2NTQ5MjM4OTUsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjkwZmYxNjM0LTBkZWEtNDViOC04OWU2LWY5YzBlYjI2NDE0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6Ijk2MDE0NzE0LWViOTctNDEyYy1hYjZlLWYzY2FjZjEwNDQ3ZSJ9LCJ3YXJuYWZ0ZXIiOjE2NTQ5Mjc1MDJ9LCJuYmYiOjE2NTQ5MjM4OTUsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.tRGnrq3F0zVDZGk_lquPVsApIGtRkxxJWs_dvD3kUcktqdwtkT3nUKt5nr7RwJEA__O7yL3PmbdMqD0HevulnOyTQouoA3Ieu7Q8w539KmBJfXozB-1vzmi0XJVExv7SAx3JfOA-QQRn9I_CQSQXuZkXRnypWZ_i15uNMsC2CskEyW3UuwbVl0O79rI7p6OWT1pusmuPjBZCLF9c6ZgsC3bqbFihaXkU8_fmkGyuF4JQy6EqxCwYOmestCgYAVM9uYtA_yavwcNnqgDOctUKQeftcIvKxThNx2cQDaDe1a6RrnWvE6jytCFH9lLsohsS2zbQPl-uFYW73tnLjw4rlQ

token用のファイルがあり、その中にJWTが記述されています。

試しにデコードすると、tokenの内容が確認できます。

1❯ jwt decode "eyJhbGciOiJSUzI1NiIsImtpZCI6InF2TDhTTHNtenhubFpZcnpwbU5UV2hOSjlYWHpyY0loNzdDREJIZGdwa0kifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg2NDU5ODk1LCJpYXQiOjE2NTQ5MjM4OTUsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjkwZmYxNjM0LTBkZWEtNDViOC04OWU2LWY5YzBlYjI2NDE0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6Ijk2MDE0NzE0LWViOTctNDEyYy1hYjZlLWYzY2FjZjEwNDQ3ZSJ9LCJ3YXJuYWZ0ZXIiOjE2NTQ5Mjc1MDJ9LCJuYmYiOjE2NTQ5MjM4OTUsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.tRGnrq3F0zVDZGk_lquPVsApIGtRkxxJWs_dvD3kUcktqdwtkT3nUKt5nr7RwJEA__O7yL3PmbdMqD0HevulnOyTQouoA3Ieu7Q8w539KmBJfXozB-1vzmi0XJVExv7SAx3JfOA-QQRn9I_CQSQXuZkXRnypWZ_i15uNMsC2CskEyW3UuwbVl0O79rI7p6OWT1pusmuPjBZCLF9c6ZgsC3bqbFihaXkU8_fmkGyuF4JQy6EqxCwYOmestCgYAVM9uYtA_yavwcNnqgDOctUKQeftcIvKxThNx2cQDaDe1a6RrnWvE6jytCFH9lLsohsS2zbQPl-uFYW73tnLjw4rlQ"
2
3Token header
4------------
5{
6  "alg": "RS256",
7  "kid": "qvL8SLsmzxnlZYrzpmNTWhNJ9XXzrcIh77CDBHdgpkI"
8}
9
10Token claims
11------------
12{
13  "aud": [
14    "https://kubernetes.default.svc.cluster.local"
15  ],
16  "exp": 1686459895,
17  "iat": 1654923895,
18  "iss": "https://kubernetes.default.svc.cluster.local",
19  "kubernetes.io": {
20    "namespace": "default",
21    "pod": {
22      "name": "nginx",
23      "uid": "90ff1634-0dea-45b8-89e6-f9c0eb26414c"
24    },
25    "serviceaccount": {
26      "name": "default",
27      "uid": "96014714-eb97-412c-ab6e-f3cacf10447e"
28    },
29    "warnafter": 1654927502
30  },
31  "nbf": 1654923895,
32  "sub": "system:serviceaccount:default:default"
33}

ServiceAccountを作成する

次は、自分でServiceAccountを作成してみます。

1apiVersion: v1
2kind: ServiceAccount
3metadata:
4  name: test-sa
1kubectl apply -f test-sa.yml

test-saというServiceAccountが作成できました。Secretもtokenも紐付いていません。

1❯ kubectl get sa
2NAME      SECRETS   AGE
3default   0         5h18m
4test-sa   0         6m37s
5
6
7❯ kubectl describe sa test-sa
8Name:                test-sa
9Namespace:           default
10Labels:              <none>
11Annotations:         <none>
12Image pull secrets:  <none>
13Mountable secrets:   <none>
14Tokens:              <none>
15Events:              <none>

作成したServiceAccountをPodに紐付ける

作成したtest-saにRoleをつけて、Podに紐付けて、動きを見ていきます。

作成するRoleはPodの読み取り権限です。RoleBindingを使って、test-saにRoleを付与します。

1apiVersion: rbac.authorization.k8s.io/v1
2kind: Role
3metadata:
4  name: role-pod-read
5  namespace: default
6rules:
7  - apiGroups: [""]
8    resources: ["pods"]
9    verbs: ["get", "watch", "list"]
10---
11apiVersion: rbac.authorization.k8s.io/v1
12kind: RoleBinding
13metadata:
14  name: service-account-rolebinding
15  namespace: default
16subjects:
17  - kind: ServiceAccount
18    name: test-sa
19roleRef:
20  kind: Role
21  name: role-pod-read
22  apiGroup: rbac.authorization.k8s.io
1kubectl apply -f role.yml

次に、test-saを紐づけるPodを作成します。kubectl get podを実行するコンテナになります。

1apiVersion: v1
2kind: Pod
3metadata:
4  name: kubectl-pod
5spec:
6  containers:
7  - image: bitnami/kubectl
8    name: kubectl
9    command:
10    - sh
11    - -c
12    - |
13      while true
14      do
15        kubectl get pod
16        sleep 30
17      done
18  serviceAccountName: test-sa
1kubectl apply -f kubectl-pod.yml

ログを確認すると、kubectl get podが実行できていることが確認できます。

1❯ kubectl logs kubectl-pod
2NAME          READY   STATUS              RESTARTS   AGE
3kubectl-pod   0/1     ContainerCreating   0          4s
4nginx         1/1     Running             0          51m
5NAME          READY   STATUS    RESTARTS   AGE
6kubectl-pod   1/1     Running   0          34s
7nginx         1/1     Running   0          51m
8NAME          READY   STATUS    RESTARTS   AGE
9kubectl-pod   1/1     Running   0          64s
10nginx         1/1     Running   0          52m

試しに、kubectl get deployに変更してみると、下記のようなエラーになります。

1❯ kubectl logs kubectl-pod
2Error from server (Forbidden): deployments.apps is forbidden: User "system:serviceaccount:default:test-sa" cannot list resource "deployments" in API group "apps" in the namespace "default

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee