Summary
We can use the expression <Resource>.<API Group>
to specify the API Group with kubectl.
# Example: the expressions of "Event v1 core" and "Event v1 events.k8s.io"
kubectl auth can-i get events
kubectl auth can-i get events.events.k8s.io
Prerequisites
- Kubernetes API v1.21.1
- kubectl v1.21.5
Same resource, different API Groups
In Kubernetes API 1.21, there are some different API Groups for the same kind of resource.
For example:
# in Kubernetes 1.21, there are two different API Groups for Events resource
$ kubectl api-resources | grep event
events ev v1 true Event
events ev events.k8s.io/v1 true Event
But if we specify “events” resource with kubectl 1.21, it will be treated as “Event v1 core”.
# create a serviceaccount with permissions to view only "Event v1 core"
$ kubectl -n default create serviceaccount user01
$ kubectl -n default create role event-corev1-reader --verb="get,list" --resource="events"
$ kubectl -n default create rolebinding event-corev1-reader --role=event-corev1-reader --serviceaccount=default:user01
# Check the permissions of the serviceaccount
# https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/#without-using-a-proxy
$ kubectl -n default run nginx --image=nginx --restart=Never --rm -it --overrides='{ "spec": { "serviceAccountName" : "user01" } }' -- /bin/bash
# The serviceaccount can list "Event v1 core"
(root@nginx)$ curl -I -X GET -k https://kubernetes.default.svc/api/v1/namespaces/default/events -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
HTTP/2 200
...
# The serviceaccount is not allowed to list "Event v1 events.k8s.io"
(root@nginx)$ curl -I -X GET -k https://kubernetes.default.svc/apis/events.k8s.io/v1/namespaces/default/events -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
HTTP/2 403
...
So, how can we specify the API Group “events.k8s.io” with kubectl?
According to the help, we can use the expression <Resource>.<API Group>
.
$ kubectl create role --help
...
Usage:
kubectl create role NAME --verb=verb --resource=resource.group/subresource
[--resource-name=resourcename] [--dry-run=server|client|none] [options]
...
This expression can be used with other kubectl subcommands such as kubectl auth can-i
.
# create a serviceaccount with permissions to view only "Event v1 events.k8s.io"
$ kubectl -n default create serviceaccount user02
$ kubectl -n default create role event-eventsk8siov1-reader --verb="get,list" --resource="events.events.k8s.io"
$ kubectl -n default create rolebinding event-eventsk8siov1-reader --role=event-eventsk8siov1-reader --serviceaccount=default:user02
# user01 can view only "Event v1 core"
$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user01
yes
$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user01
no
# user02 can view only "Event v1 events.k8s.io"
$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user02
no
$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user02
yes
(The following is the same content in Japanese.)
まとめ
リソースが同じでもAPI Groupが異なるものをkubectl
で指定したいときは<Resource>.<API Group>
とすれば良い。
# "Event v1 core"と"Event v1 events.k8s.io"をそれぞれ指定して権限を確認する例
kubectl auth can-i get events
kubectl auth can-i get events.events.k8s.io
環境
- Kubernetes API v1.21.1
- kubectl v1.21.5
同じリソース名でAPI versionが複数あるとき
Kubernetes API
ではv1.21時点でEvent
のAPI Group
がevents.k8s.ioになっていて、
それまであったcore版のEvent
はOLD API VERSIONSという扱い。
# 1.22時点では2種類のAPI Groupが存在する
$ kubectl api-resources | grep event
events ev v1 true Event
events ev events.k8s.io/v1 true Event
しかし、v1.22のkubectl
で普通にevents
に対するRole
を作成するとAPI Group
がcore
で指定されてしまう。
# "event"を指定してRoleを作成する
$ kubectl -n default create serviceaccount user01
$ kubectl -n default create role event-corev1-reader --verb="get,list" --resource="events"
$ kubectl -n default create rolebinding event-corev1-reader --role=event-corev1-reader --serviceaccount=default:user01
# Podを立てて確認してみる
# https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/#without-using-a-proxy
$ kubectl -n default run nginx --image=nginx --restart=Never --rm -it --overrides='{ "spec": { "serviceAccountName" : "user01" } }' -- /bin/bash
# coreのAPIは利用可能
(root@nginx)$ curl -I -X GET -k https://kubernetes.default.svc/api/v1/namespaces/default/events -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
HTTP/2 200
...
# events.k8s.ioのAPIは認可エラーで利用不可
(root@nginx)$ curl -I -X GET -k https://kubernetes.default.svc/apis/events.k8s.io/v1/namespaces/default/events -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
HTTP/2 403
...
じゃあk8s.events.io
版への権限はどうやって付与するんだろう?と試行錯誤していたら、helpにちゃんと書いてあった…
$ kubectl create role --help
...
Usage:
kubectl create role NAME --verb=verb --resource=resource.group/subresource
[--resource-name=resourcename] [--dry-run=server|client|none] [options]
...
リソースの後に続いて.<API Group>
を指定すればいいらしい。
(何も指定しない場合はcoreになるっぽい?)
この方法で再度Role
を指定しなおす。
$ kubectl -n default create serviceaccount user02
$ kubectl -n default create role event-eventsk8siov1-reader --verb="get,list" --resource="events.events.k8s.io"
$ kubectl -n default create rolebinding event-eventsk8siov1-reader --role=event-eventsk8siov1-reader --serviceaccount=default:user02
他のコマンドでリソースを指定するときも同様にできるらしいので、今度はPod
を建てずにkubectl auth
で確認してみる。
# user01: core版のみの閲覧権限
$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user01
yes
$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user01
no
# user02: events.k8s.io版のみの閲覧権限
$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user02
no
$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user02
yes
やったぜ。
異なるAPI Group
をkubectl
で指定できた。
おわり
ちゃんとヘルプを読んでいればなんてことない話だったんだけど、
自分は数時間ムダにしてしまったのでメモにした。
やっぱり公式ドキュメントやヘルプを読むのは大事。