kube apiserver는 여러 그룹화된 API들이 존재하는데, 다음과 같이 나눌 수 있다.
1. /metrics
2. /healthz
3. /version
4. /api
5. /apis
6. /logs
api
와 apis
가 헷갈릴 수 있는데, core api와 named apis로 나눌 수 있다. 우리가 흔히 아는 핵심적인 core kubernetes resource들은 core api에 속하는 것이다.
1. namespaces
2. pods
3. rc
4. events
5. endpoints
/api(core) -> /v1 -> 6. nodes
7. bindings
8. pv
9. pvc
10. configmaps
11. secrets
12. services
/api/v1
아래에 위와 같은 resource들이 kubernetes의 core로 존재하는 것이다.
named apis
는 조금 다른데, v1
아래에 모든 resource들이 있는 것이 아니라, 다양한 버전들이 있다.
[API Groups] [Resources]
---------------------------------------------------------------------
/certificates.k8s.io -> /v1
/extensions -> /v1
/apis(named) -> /apps -> /v1 -> [/deployments, ...]
/networking.k8s.io -> /v1 -> [/networkpolicies, ...]
/storage.k8s.io -> /v1
/authentication.k8s.io -> /v1
이렇게 /apis
아래에는 각 api group들이 있고 이 아래로 resource들이 쭉 있는 것이다.
각 resources
들은 list
, get
, create
, delete
, update
, watch
등의 verb를 갖는데, 가령 /apis/apps/v1/deployments
가 앞서 말한 verb들을 갖는 것이다.
| [API Groupd] | [Resources] | [verbs] |
----------------------------------------------------------------------
| 1. deployments | list, get, create |
|/apis -> /apps -> /v1 -> 2. relicasets | delete, update, watch |
| 3. statefulsets | |
----------------------------------------------------------------------
따라서, 각 user가 kube apiserver에 접근하여 /apis
를 통해 특정 API group의 resource에 action(verb)을 취하려면, 해당 하는 권한이 있어야 한다는 것이다.
kubernetes cluster에 접근하는 user들은 각기 다른 목적을 가지고 cluster에 접근한다. 가령 관리자는 kubernetes cluster에 대한 운용을 위해서 접근하고, 개발자는 application 구동을 위해서, CICD robot은 test를 위해 접근한다.
그런데 만약 관리자와 개발자, 로봇이 같은 권한을 가지게 되면 어떻게될까?? 관리자의 허락도 없이 node를 삭제하고 resource들을 변경하여 혼란을 야기할 수 있다. 따라서 각 user들이 cluster의 resource에 할 수 있는 동작의 권한을 다르게 주어 cluster를 안전하게 사용하고자하는 것이다.
kubernetes에서 권한을 관리하는 매커니즘은 다양하게 존재했지만, 현재는 RBAC
방식이 표준으로 사용된다.
RBAC
접근 방식은 role-based-access-control로 롤(역할)기반으로 kube apiserver에 접근하도록 하는 방법이다. 즉, user 계정 각각이 어떤 권한을 부여받기 보다는, 권한에 대한 정보가 담긴 role이라는 객체가 있고 이 role객체를 각 user 계정이 레퍼런싱하여 해당 role에 맞는 권한을 부여받는 것이다.
즉, 다음과 같다.
user1 --> pod(create, delete, update)
user2 --> pod(create, delete)
user3 --> pod(create, update)
이렇게 각 user가 특정 resource에 대한 verb 권한을 부여받는 것이 아니라, 다음과 같이 role을 만들고 이 role을 바인딩하는 것이다.
참고로 여기서 말하는 user는 이전 시간에 kubeconfig
에서 말했던 users
에서의 user이다.
따라서 다음의 명령어로 확인이 가능하다.
kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://controlplane:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: dev-user
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
여기서는 dev-user
와 kubernetes-admin
user가 있는 것이다.
Role1(developer) --> pod(create, update)
Role2(administrator) --> pod(create, update, delete)
user1 -> Role1(developer)
user2 -> Role2(administrator)
user1
은 Role1
역할을 부여받으므로 pod에 대한 create, update가 가능하고, user2
는 Role2
역할을 부여받으므로 pod에 대한 create, update, delete가 가능하다.
참고로, RBAC말고도 Node, Admission hook 등의 방법들이 있는데 현재 kube-apiserver가 어떤 권한 부여 방법을 사용하고 있는 지 option
을 통해서 확인할 수 있다.
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep auth
- --authorization-mode=Node,RBAC
- --enable-bootstrap-token-auth=true
--authorization-mode
가 바로 현재 kube-apiserver가 어떤 권한 부여 방법을 사용하고 있는 지 알려주는 부분으로 Node
방식 다음에 RBAC
를 쓴다는 것이다.
그럼 role을 어떻게 만들 수 있을까?? role은 kubernetes의 object로서 다음과 같은 manifest를 만들어서 role을 추가할 수 있다.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["list", "get", "create", "updates", "delete"]
다음과 같이 Role
kubernetes object를 만들면 된다. 위의 경우는 pods
resource애 대한 list
, get
, create
, updates
, delete
verb의 권한을 요청하는 것이다. 여기서 재밌는 것은 apiGroups
를 ""
로 해주었는데, 위에서 보았듯이 core api의 경우는 apiGroups
가 따로 없기 때문에 ""
을 써주면 된다.
rules
를 보면 알겠지만 배열인 것을 알 수 있다. 따라서, 하나의 role
에 여러 권한들을 넣을 수 있다.
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["list", "get", "create", "updates", "delete"]
- apiGroups: [""]
resources: ["ConfigMap"]
verbs: ["create"]
다음으로 role
을 user에게 연결해야하는데, 이를 가능하게해주는 것이 RoleBinding
이다.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
RoleBinding
은 두 부분으로 나뉘는 것을 볼 수 있다.
dev-user
만 존재한다.developer
role을 지정하였다.중요: Role
과 RoleBinding
은 둘 다 namespace scope를 갖는다. 따라서, namespace에 대한 지정을 정확하게 해주어야 한다. 위의 경우는 default
namespace로 처리하고 있는 것이다.
role과 rolebinding을 보는 방법은 다음과 같다.
kubectl get roles
kubectl get rolebindings
그런데 내 계정이 정확히 role, role-binding이 되었는 지 어떻게 알 수 있을까?? 이를 확인하는 방법인 kubectl auth can-i {verb} {resource}
가 있다.
아래는 deployment
resource를 내가 create
할 수 있는 지 확인하는 명령어이다.
kubectl auth can-i create deployments
yes
만약 계정을 현재 계정이 아니라, 다른 계정으로 바꾸고 싶다면 --as
를 쓰면 된다. 아래는 dev-user
의 권한 check이다.
kubectl auth can-i create deployments --as dev-user
kubectl auth can-i create pod --as dev-user
참고로, 특정 namespace scope도 지정할 수 있다. 아래는 dev-user
가 test
namespace에서 pod
을 생성할 권한이 있는 지 확인하는 것이다.
kubectl auth can-i create pods --as dev-user --namespace test
마지막으로 resource에서 특정 name을 가진 것만 권한을 부여하고 싶을 때가 있을 수 있다. 가령 pod들 중에서 blue
, orange
, green
이 있을 때 blue
, orange
만 권한을 부여하고 싶다면 Role
을 다음과 같이 만들면 된다.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "create", "update"]
resourceNames: ["blue", "orange"]
Role과 Rolebinding은 모두 namespace scope에 영향을 받는다고했다. 즉, 만약 blue
라는 namespace로 만들어졌다면 blue
namespace에서만 role이 동작하는 것이다.
즉, Role
과 Rolebinding
은 namespace scope를 가진 resource에서만 유효하다는 것이다. 따라서, pods
, replicasets
, jobs
등등 namespace의 영향을 받는 resource들은 Role
과 Rolebinding
을 통해서 권한을 부여할 수 있지만, namespace scope가 아니라 cluster scope의 resource의 경우는 이야기가 다르다.
가령 nodes
, pv
, namespace
와 같은 resource들은 namespace scope를 가지지 않고 cluster 자체에 대한 scope를 가진다. 따라서, 이들에게도 권한을 부여하는 role이 따로 필요한 것이다.
그래서 나온 것인 ClusterRoles
, ClusterRoleBinding
이다.
가령, admin 중에 누군가는 node를 관리함으로 ClusterRole
을 node에 대한 것만 부여하도록 할 수 있다. 반면, 누군가는 storage에 관한 admin이므로 storage인 pv에 관한 role만 부여하도록 할 수 있다.
User | resource with cluster scope | verbs |
---|---|---|
cluster admin | Nodes | view, create, delete |
storage admin | PV | view, create, delete |
이중 cluster admin을 위한 ClusterRole
을 만들어보도록 하자. 전반적인 내용 자체는 Role
과 동일하기 때문에 어려울 것이 없다.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-administrator
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list", "get", "create", "delete"]
nodes
에 대해서 list
, get
, create
, delete
권한을 부여하는 cluster role이다.
이제 이 cluster role을 user에게 바인딩하는 ClusterRoleBinding
을 만들어보도록 하자.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-role-binding
subjects:
- kind: User
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-administrator
apiGroup: rbac.authorization.k8s.io
cluster-admin
에 cluster-administrator
role을 부여하여 cluster scope의 resource에 접근할 수 있는 권한을 부여한 것이다.