namespace/dev created
namespace/prod created
namespace/test created
role.rbac.authorization.k8s.io/dev-ro created
clusterrole.rbac.authorization.k8s.io/all-rw created
clusterrolebinding.rbac.authorization.k8s.io/owner-binding created
rolebinding.rbac.authorization.k8s.io/auditor-binding created
「owner」インスタンスで次のコマンドを実行し、すべての Namespace の hello-server Pod 全一覧を表示します。
kubectl get pods -l app=hello-server --all-namespaces
出力:
NAMESPACE NAME READY STATUS RESTARTS AGE
dev hello-server-6c6fd59cc9-h6zg9 1/1 Running 0 6m
prod hello-server-6c6fd59cc9-mw2zt 1/1 Running 0 44s
test hello-server-6c6fd59cc9-sm6bs 1/1 Running 0 39s
「auditor」インスタンスで次のコマンドを実行し、すべての Namespace の hello-server Pod 全一覧を表示します。
kubectl get pods -l app=hello-server --all-namespaces
次のようなエラーが表示されます。
Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods at the cluster scope: Required "container.pods.list" permission
このエラーは実行者に十分な権限がないことを示しています。監査者ロールで表示できるのは dev Namespace 内のリソースに限られるため、リソースを表示するときには dev Namespace を指定する必要があります。
次に、dev Namespace 内の Pod を表示してみましょう。
「auditor」インスタンスで次のコマンドを実行します。
kubectl get pods -l app=hello-server --namespace=dev
出力:
NAME READY STATUS RESTARTS AGE
hello-server-6c6fd59cc9-h6zg9 1/1 Running 0 13m
test Namespace 内の Pod を表示してみます。
kubectl get pods -l app=hello-server --namespace=test
出力:
Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods in the namespace "test": Required "container.pods.list" permission.
prod Namespace 内の Pod を表示してみます。
kubectl get pods -l app=hello-server --namespace=prod
出力:
Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods in the namespace "prod": Required "container.pods.list" permission.
kubectl create -n dev -f manifests/hello-server.yaml
出力:
Error from server (Forbidden): error when creating "manifests/hello-server.yaml": services is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot create services in the namespace "dev": Required "container.services.create" permission.
Error from server (Forbidden): error when creating "manifests/hello-server.yaml": deployments.extensions is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot create deployments.extensions in the namespace "dev": Required "container.deployments.create" permission.
「auditor」インスタンスで、Deployment を削除してみます。
kubectl delete deployment -n dev -l app=hello-server
出力:
Error from server (Forbidden): deployments.extensions "hello-server" is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot update deployments.extensions in the namespace "dev": Required "container.deployments.update" permission.
タスク 3. シナリオ 2: クラスタ アプリケーションへの API 権限の割り当て
このシナリオでは、Kubernetes API へのアクセスを必要とするアプリケーションをデプロイし、一般的なユースケースをトラブルシューティングしながら RBAC ルールを構成します。
サンプル アプリケーションをデプロイする
サンプル アプリケーションは、API サーバーからデフォルトの Namespace 内のすべての Pod を定期的に取得し、各 Pod にタイムスタンプ ラベルを適用する単一の Pod として動作します。
role.rbac.authorization.k8s.io/pod-labeler created
serviceaccount/pod-labeler created
rolebinding.rbac.authorization.k8s.io/pod-labeler created
deployment.apps/pod-labeler created
NAME READY STATUS RESTARTS AGE
pod-labeler-6d9757c488-tk6sp 0/1 Error 1 1m
admin インスタンスで、次のコマンドを実行して Pod のイベント ストリームを表示します。
kubectl describe pod -l app=pod-labeler | tail -n 20
次のように表示されます。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7m35s default-scheduler Successfully assigned default/pod-labeler-5b4bd6cf9-w66jd to gke-rbac-demo-cluster-default-pool-3d348201-x0pk
Normal Pulling 7m34s kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk pulling image "gcr.io/pso-examples/pod-labeler:0.1.5"
Normal Pulled 6m56s kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Successfully pulled image "gcr.io/pso-examples/pod-labeler:0.1.5"
Normal Created 5m29s (x5 over 6m56s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Created container
Normal Pulled 5m29s (x4 over 6m54s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Container image "gcr.io/pso-examples/pod-labeler:0.1.5" already present on machine
Normal Started 5m28s (x5 over 6m56s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Started container
Warning BackOff 2m25s (x23 over 6m52s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Back-off restarting failed container
admin インスタンスで、次のコマンドを実行して Pod のログを確認します。
kubectl logs -l app=pod-labeler
出力:
Attempting to list pods
Traceback (most recent call last):
File "label_pods.py", line 13, in
ret = v1.list_namespaced_pod("default",watch=False)
File "build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py", line 12310, in list_namespaced_pod
File "build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py", line 12413, in list_namespaced_pod_with_http_info
File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 321, in call_api
File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 155, in __call_api
File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 342, in request
File "build/bdist.linux-x86_64/egg/kubernetes/client/rest.py", line 231, in GET
File "build/bdist.linux-x86_64/egg/kubernetes/client/rest.py", line 222, in request
kubernetes.client.rest.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Date': 'Fri, 25 May 2018 15:33:15 GMT', 'Audit-Id': 'ae2a0d7c-2ab0-4f1f-bd0f-24107d3c144e', 'Content-Length': '307', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff'})
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods is forbidden: User \"system:serviceaccount:default:default\" cannot list pods in the namespace \"default\": Unknown user \"system:serviceaccount:default:default\"","reason":"Forbidden","details":{"kind":"pods"},"code":403}
このエラーから、API を使用して Pod を一覧表示しようとしたときに、権限のエラーが発生していることがわかります。
次の手順では、正しい ServiceAccount を使用していることを確認します。
ServiceAccount 名を修正する
Pod の構成を調べると、カスタム サービス アカウントではなく、デフォルトの ServiceAccount が使用されていることがわかります。
NAME READY STATUS RESTARTS AGE
pod-labeler-c7b4fd44d-mr8qh 0/1 CrashLoopBackOff 3 1m
この出力を表示するには、前述のコマンドの再実行が必要になる場合があります。
admin インスタンスで、Pod のログを確認します。
kubectl logs -l app=pod-labeler
出力:
File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 292, in PATCH
return self.request("PATCH", url,
File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 231, in request
raise ApiException(http_resp=r)
kubernetes.client.rest.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Audit-Id': 'f6c67c34-171f-42f3-b1c9-833e00cedd5e', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'Date': 'Mon, 23 Mar 2020 16:35:18 GMT', 'Content-Length': '358'})
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods \"pod-labeler-659c8c99d5-t96pw\" is forbidden: User \"system:serviceaccount:default:pod-labeler\" cannot patch resource \"pods\" in API group \"\" in the namespace \"default\"","reason":"Forbidden","details":{"name":"pod-labeler-659c8c99d5-t96pw","kind":"pods"},"code":403}
NAME READY STATUS RESTARTS NAME READY STATUS RESTARTS AGE LABELS
pod-labeler-659c8c99d5-5qsmw 1/1 Running 0 31s app=pod-labeler,pod-template-hash=659c8c99d5,updated=1584982487.6428008
Pod のログを表示し、エラーがなくなっていることを確認します。
kubectl logs -l app=pod-labeler
出力:
Attempting to list pods
labeling pod pod-labeler-659c8c99d5-5qsmw
labeling pod pod-labeler-659c8c99d5-t96pw
...
重要ポイント
コンテナと API サーバーのログは、ロールベース アクセス制御の問題を診断する手がかりを得るために適したソースです。