作業メモ。
Kubernetes完全ガイド impress top gearシリーズを読みながら手元で確認した時のメモ。
Kubernetes の ServiceAccount を作成し、Pod から kubectl を実行した。
環境
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:03:09Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
ServiceAccount を作成して Pod から kubectl を使って Pod の情報を取得する
参考公式ドキュメント。
Configure Service Accounts for Pods
ServiceAccount の作成
ServiceAccount を作成する。
以下のマニュフェストを作成する。
apiVersion: v1
kind: ServiceAccount
metadata:
name: sample-serviceaccount
namespace: default
# ServiceAccount の作成
$kubectl apply -f sample-serviceaccount.yaml
serviceaccount "sample-serviceaccount" created
# 最初から存在する default 以外に作成した serviceaccount が存在する
$kubectl get serviceaccount
NAME SECRETS AGE
default 1 16d
sample-serviceaccount 1 35s
ServiceAccount を作成すると Secret も作成されている。
# マニュフェストにはない secret が追加されている
$kubectl get serviceaccount sample-serviceaccount -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sample-serviceaccount","namespace":"default"}}
creationTimestamp: 2019-01-05T21:07:40Z
name: sample-serviceaccount
namespace: default
resourceVersion: "2175514"
selfLink: /api/v1/namespaces/default/serviceaccounts/sample-serviceaccount
uid: efcc6da1-112d-11e9-b090-0ae6cc179478
secrets:
- name: sample-serviceaccount-token-2tml5
# serviceaccount 名を使って secret が追加されている
$kubectl get secret
NAME TYPE DATA AGE
default-token-9shpr kubernetes.io/service-account-token 3 16d
sample-serviceaccount-token-2tml5 kubernetes.io/service-account-token 3 1m
test-secret Opaque 2 5d
# Secret を見る
$kubectl get secret sample-serviceaccount-token-2tml5 -o yaml
apiVersion: v1
data:
ca.crt: ・・・
namespace: ZGVmYXVsdA==
token: ・・・
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: sample-serviceaccount
kubernetes.io/service-account.uid: efcc6da1-112d-11e9-b090-0ae6cc179478
creationTimestamp: 2019-01-05T21:07:40Z
name: sample-serviceaccount-token-2tml5
namespace: default
resourceVersion: "2175513"
selfLink: /api/v1/namespaces/default/secrets/sample-serviceaccount-token-2tml5
uid: efce8bb3-112d-11e9-b090-0ae6cc179478
type: kubernetes.io/service-account-token
Secret はトークンと証明書から構成されている。
Pod から Kubernetes API へリクエストする場合、上記を利用する。
Pod を起動して Kubernetes API へリクエストする(NG)
Pod 作成時に ServiceAccount を指定する。
以下のように指定する事ができる。
apiVersion: v1
kind: Pod
metadata:
name: sample-kubectl
spec:
serviceAccountName: sample-serviceaccount
containers:
- name: kubectl-container
image: lachlanevenson/k8s-kubectl:v1.10.4
command: ["sleep", "86400"]
なお、ServiceAccount を明示的に指定しない場合 default
という ServiceAccount が設定される。
作成した ServiceAccount を指定して起動してみる。
起動すると ServiceAccount の Secret がマウントされている。
$ kubectl apply -f sample-kubectl.yaml
pod "sample-kubectl" created
# secret がマウントされている
$kubectl get pod sample-serviceaccount-pod -o yaml |less
(一部略)
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: sample-serviceaccount-token-mcczl
readOnly: true
volumes:
- name: sample-serviceaccount-token-mcczl
secret:
defaultMode: 420
secretName: sample-serviceaccount-token-mcczl
# secret の情報が配置されている
$kubectl exec -it sample-kubectl -- ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt namespace token
Pod ではマウントした Secret を使って認証を行う。
この状態で kubectl get pods
を実行してPod 情報を取得できるかやってみる。
$kubectl exec -it sample-kubectl -- kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:sample-serviceaccount" cannot list pods in the namespace "default"
command terminated with exit code 1
この状態ではNG。
エラーメッセージに書いてあるように Pod 情報を取得する権限がないため。
権限を付与する
先程作成した ServiceAccount には Pod を取得する権限が無いために失敗した。
Kubernetes では RBAC(Role Based Access Control)を採用しており、どういった操作を出来るかということを記載した Role を作成し、ServiceAccount などの User に対して Role を紐付ける(RoleBinding)ことで権限管理を行っている。
Role と RoleBiding には大きく分けて2種類ある。
基本的には設定範囲が違う。
- namespace レベルの指定:Role と RoleBinding
- cluster レベルの指定:ClusterRole と ClusterRoleBinding
違いとして例えば namspece レベルの Role を作成したとする。
この場合、別途新しい namespace が作成され、同じような権限の設定を行いたい時には新しい namespace の Role と Rolebinding が必要。
一方、CluserRole を作成指定場合、cluster ワイドなので新しい ClusterRole の作成は不要。
また、 Kuberntes システムコンポーネントでも ClusterRole を使っておりいくつかのプリセットも存在する。
その為、ざっくりした権限付与で良い場合、ClusterRole のプリセットを使う方法も有効。
確認してみる。
# clusterrole 一覧を確認.多くの情報が表示される.system と表示されているのが system で使っているもの
$kubectl get clusterrole
NAME AGE
admin 16d
aws-node 16d
cluster-admin 16d
edit 16d
eks:node-bootstrapper 16d
system:aggregate-to-admin 16d
system:aggregate-to-edit 16d
system:aggregate-to-view 16d
system:auth-delegator 16d
system:aws-cloud-provider 16d
system:basic-user 16d
system:certificates.k8s.io:certificatesigningrequests:nodeclient 16d
(略)
# view という clustrrole の詳細を確認。pod については get/list/watch が可能
$ kubectl describe clusterrole view
Name: view
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate=true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
(略)
pods [] [] [get list watch]
pods/log [] [] [get list watch]
pods/status [] [] [get list watch]
horizontalpodautoscalers.autoscaling [] [] [get list watch]
poddisruptionbudgets.policy [] [] [get list watch]
上記 clusterrole を 作成した serviceaccount に付与するために ClusterRoleBinding を作成する。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: sample-clusterrolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: sample-serviceaccount
namespace: default
# ClusterRoleBinding を作成
$kubectl apply -f sample-clusterrolebinding.yaml
clusterrolebinding.rbac.authorization.k8s.io "sample-clusterrolebinding" created
# ServiceAccont の sample-serviceaccount と紐付いている
$kubectl describe clusterrolebinding sample-clusterrolebinding
Name: sample-clusterrolebinding
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"sample-clusterrolebinding","namespace":""...
Role:
Kind: ClusterRole
Name: view
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount sample-serviceaccount default
Pod から Kubernetes API へリクエストする(OK)
権限を付与したので先程の Pod から kubectl get pods
を実行する。
$ kubectl exec -it sample-kubectl -- kubectl get pods
NAME READY STATUS RESTARTS AGE
1-sample-pod 1/1 Running 0 11d
2-sample-pod 1/1 Running 0 11d
dapi-envars-fieldref 1/1 Running 0 5d
Pod の再起動はしていないが成功。
トークンの認証は以前から成功しており、権限を付与したことで認可ができたので成功した状況と思われる。