Featured image of post Specify the API Group of the resource with kubectl

Specify the API Group of the resource with kubectl

kubectlで同じKindのリソースについてAPI Groupを指定する方法がわかんなくて消耗したのでメモ

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時点でEventAPI Groupevents.k8s.ioになっていて、
それまであったcore版のEventOLD 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 Groupcoreで指定されてしまう。

# "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 Groupkubectlで指定できた。

おわり

ちゃんとヘルプを読んでいればなんてことない話だったんだけど、
自分は数時間ムダにしてしまったのでメモにした。

やっぱり公式ドキュメントやヘルプを読むのは大事。

おまけ

ごろごろするねこ