はじめに
ServiceAccountは、Podで実行されるプロセスの認証、許可を行います。Pod起動時には必ず割り当てる必要があり、指定しない場合は「default」ServiceAccountが割り当てられます。
ServiceAccountの作成
以下のマニフェストのServiceAccountを作成します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: service-account01
automountServiceAccountToken: false #Podデプロイ時にトークンを自動マウントするかどうか
$ kubectl apply -f serviceAccount01.yaml
serviceaccount/service-account01 created
$ kubectl get serviceaccounts
NAME SECRETS AGE
default 1 112d
service-account01 1 16s
「default」はデフォルトのServiceAccountで、Pod作成時に何も指定しなければこれが割り当てられます。
ServiceAccountの確認
作成したServiceAccountの詳細を確認します。
ServiceAccountを作成すると、それに紐づくSecretが作成されています。
$ kubectl get serviceaccounts service-account01 -o yaml
apiVersion: v1
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","automountServiceAccountToken":false,"kind":"ServiceAccount","metadata":{"annotations":{},"name":"service-account01","namespace":"default"}}
creationTimestamp: "2020-06-17T12:49:24Z"
name: service-account01
namespace: default
resourceVersion: "1842148"
selfLink: /api/v1/namespaces/default/serviceaccounts/service-account01
uid: aab6d349-f30a-4206-9575-118e1c083a60
secrets:
- name: service-account01-token-qfdgb
Secretを確認します。
$ kubectl get secrets
NAME TYPE DATA AGE
default-token-nstst kubernetes.io/service-account-token 3 112d
service-account01-token-qfdgb kubernetes.io/service-account-token 3 55s
$ kubectl get secrets service-account01-token-qfdgb -o yaml
apiVersion: v1
data:
ca.crt: LS0tLS1CRU・・・
token: ZXlKaGJHY2lPaUpTVXpJM・・・・
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: service-account01
kubernetes.io/service-account.uid: aab6d349-f30a-4206-9575-118e1c083a60
creationTimestamp: "2020-06-17T12:49:24Z"
name: service-account01-token-qfdgb
namespace: default
resourceVersion: "1842147"
selfLink: /api/v1/namespaces/default/secrets/service-account01-token-qfdgb
uid: 3ea76e94-e939-4abf-b155-87f66e37beb3
type: kubernetes.io/service-account-token
Podの作成
作成したServiceAccountを指定してPodをデプロイします。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod01
spec:
containers:
- name: nginx
image: nginx:latest
serviceAccountName: service-account01
automountServiceAccountToken: true #トークンを自動マウントする
ServiceAccount作成時にトークの自動マウント(automountServiceAccountToken)はfalseにしましたが、Podのマニフェストではtrueにしています。
ServiceAccountとPodの両方でautomountServiceAccountTokenが設定された場合は、Podの設定が優先されます。
このマニフェストをapplyして、Podの詳細を確認します。
$ kubectl apply -f pod01.yaml
pod/nginx-pod01 created
$ kubectl get pod nginx-pod01 -o yaml
apiVersion: v1
kind: Pod
metadata:
・・・
spec:
automountServiceAccountToken: true
containers:
・・・
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: service-account01-token-qfdgb
readOnly: true
・・・
SecretがVolumeとしてマウントされていますね。
コンテナにログインして確認します。
$ kubectl exec -it nginx-pod01 ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt namespace token
$ kubectl exec -it nginx-pod01 cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6・・・
トークンを利用したAPI Serverへのアクセス
ServiceAccountのトークンをAPI Serverへの認証情報として利用できます。これによって、PodからAPIサーバに対してコマンドを実行できるようになります。
RBACの設定
ServiceAccountとClusterRoleを紐づけます。
ClusterRole
まずはクラスタにあるClusterRoleを確認します。
$ kubectl get clusterrole
NAME AGE
admin 112d
calico-kube-controllers 112d
calico-node 112d
cluster-admin 112d
edit 112d
metallb-system:controller 69d
metallb-system:speaker 69d
system:aggregate-to-admin 112d
system:aggregate-to-edit 112d
・・・
view 112d
$ kubectl describe clusterrole view
Name: view
Labels: kubernetes.io/bootstrapping=rbac-defaults
rbac.authorization.k8s.io/aggregate-to-edit=true
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
bindings [] [] [get list watch]
configmaps [] [] [get list watch]
endpoints [] [] [get list watch]
events [] [] [get list watch]
limitranges [] [] [get list watch]
namespaces/status [] [] [get list watch]
namespaces [] [] [get list watch]
persistentvolumeclaims/status [] [] [get list watch]
persistentvolumeclaims [] [] [get list watch]
pods/log [] [] [get list watch]
pods/status [] [] [get list watch]
pods [] [] [get list watch]
「View」というClusterRoleにはPodのget/list/watchの権限がありますので、これとServiceAccountを紐づけます。
ClusterRoleBinding
以下のマニフェストをapplyします。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: service-account01
namespace: default
$ kubectl apply -f clusterRoleBinding.yaml
clusterrolebinding.rbac.authorization.k8s.io/cluster-role-binding created
$ kubectl get clusterrolebindings.rbac.authorization.k8s.io cluster-role-binding
NAME AGE
cluster-role-binding 75s
$ kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-role-binding
Name: cluster-role-binding
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"cluster-role-binding"},"role...
Role:
Kind: ClusterRole
Name: view
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount service-account01 default
Viewとservice-account01が紐づいたことがわかります。
これでservice-account01が割り当てられたPodは「View」と同じ権限を持ったことになります。
確認
コンテナにログインして確認します。
$ kubectl exec -it nginx-pod01 /bin/bash
root@nginx-pod01:/# TOKEN=`cat /var/run/secrets/kubernetes.io/serviceaccount/token`
root@nginx-pod01:/# curl -H "Authorization: Bearer ${TOKEN}" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes/api/v1/namespaces/default/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/default/pods",
"resourceVersion": "1850682"
},
"items": [
{
"metadata": {
"name": "nginx-pod01",
・・・
Podのリストが表示されていますね。
まとめ
今回はServiceAccountの動作を確認しました。セキュリティは大事ですので、しっかりと押さえないといけないですね。
これだけではなく、RBACなどもこれから確認したいと思います。