KubernetesのServiceAccountを触って学ぶ

udomomo.hatenablog.com

以前RBACについての記事を書いたが、Rolebindingで権限を付与できる対象は複数ある。以前の記事では人に対して与えられるUser Accountについて書いたが、Pod内で動くコンテナのプロセスに対して与えられるService Accountというものもある。
RBACでは、このService Accountごとの権限設定もできる。例えば同じNamespaceの中で異なる役割のPodがあるとき、ServiceAccountを使って権限を付与すれば、より細かな権限管理が可能になり、セキュリティ上のリスクを減らすことができる。

Service Accountを設定する

普段はほとんど意識しないが、Service Account自体は常に使われている。デフォルトでは、全てのアプリケーションはそれぞれのNamespaceに固有である default という名前のServiceAccountで起動される。

特にServiceAccount関連の設定をせずにPodを起動してみる。

# nginx.yaml
apiVersion: v1                                                                                                                                       
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx-container
       image: nginx:1.17-alpine
       ports:
       - containerPort: 80
$ kubectl apply -f nginx.yaml
pod/nginx created

$ kubectl get pod -o yaml
apiVersion: v1
items:
...
spec:
  containers:
  ...
    volumeMounts:
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: default-token-h7nhq
          readOnly: true
  ...
  serviceAccount: default
  serviceAccountName: default
  ...
  volumes:
    - name: default-token-h7nhq
      secret:
        defaultMode: 420
        secretName: default-token-h7nhq

default という名前のServiceAccountが使われていることがわかる。そして、ServiceAccount用のSecretが作られ、Volumeとしてマウントされている。このSecretの中に、各ServiceAccountに付与されたAPIアクセス権限(トークン)が保存される。
これを変えるには、マニフェスト内で別のServiceAccountを指定すれば良い。

# nginx-serviceaccount.yaml
apiVersion: v1                                                                                                                                       
kind: ServiceAccount
metadata:
  name: nginx-serviceaccount
  namespace: default
# nginx.yaml
apiVersion: v1                                                                                                                                       
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx-container
       image: nginx:1.17-alpine
       ports:
       - containerPort: 80
  serviceAccountName: nginx-serviceaccount
$ kubectl get pod -o yaml
apiVersion: v1
items:
...
spec:
  containers:
    ...
    volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: nginx-serviceaccount-token-2qlq4
        readOnly: true
  ...
  serviceAccount: nginx-serviceaccount
  serviceAccountName: nginx-serviceaccount
  ...
  volumes:
    - name: nginx-serviceaccount-token-2qlq4
      secret:
        defaultMode: 420
        secretName: nginx-serviceaccount-token-2qlq4

serviceAccountの名前が変わり、マウントされているSecretも更新された。

あとはRoleとRolebindingを作り、このServiceAccountに権限を付与することで、Pod単位での権限管理が可能となる。