CKA를 준비해보자 23일차 - API Groups, RBAC, ClusterRole

0

CKA

목록 보기
23/43

API Groups

kube apiserver는 여러 그룹화된 API들이 존재하는데, 다음과 같이 나눌 수 있다.
1. /metrics
2. /healthz
3. /version
4. /api
5. /apis
6. /logs

apiapis가 헷갈릴 수 있는데, 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)을 취하려면, 해당 하는 권한이 있어야 한다는 것이다.

Authorization

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-userkubernetes-admin user가 있는 것이다.

Role1(developer) --> pod(create, update)
Role2(administrator) --> pod(create, update, delete)

user1 -> Role1(developer)
user2 -> Role2(administrator)

user1Role1 역할을 부여받으므로 pod에 대한 create, update가 가능하고, user2Role2 역할을 부여받으므로 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를 쓴다는 것이다.

RBAC(Role, RoleBindings)

그럼 role을 어떻게 만들 수 있을까?? role은 kubernetes의 object로서 다음과 같은 manifest를 만들어서 role을 추가할 수 있다.

  • developer-role.yaml
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이다.

  • devuser-developer-binding.yaml
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은 두 부분으로 나뉘는 것을 볼 수 있다.

  1. subjects: role을 적용시킬 user의 list이다. 여기서는 dev-user만 존재한다.
  2. roleRef: 어떤 role을 subjects에게 적용시킬 지 지정한다. 여기서는 위에서 만든 developer role을 지정하였다.

중요: RoleRoleBinding은 둘 다 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-usertest 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"]

Cluster Roles

Role과 Rolebinding은 모두 namespace scope에 영향을 받는다고했다. 즉, 만약 blue라는 namespace로 만들어졌다면 blue namespace에서만 role이 동작하는 것이다.

즉, RoleRolebinding은 namespace scope를 가진 resource에서만 유효하다는 것이다. 따라서, pods, replicasets, jobs 등등 namespace의 영향을 받는 resource들은 RoleRolebinding을 통해서 권한을 부여할 수 있지만, 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만 부여하도록 할 수 있다.

Userresource with cluster scopeverbs
cluster adminNodesview, create, delete
storage adminPVview, create, delete

이중 cluster admin을 위한 ClusterRole을 만들어보도록 하자. 전반적인 내용 자체는 Role과 동일하기 때문에 어려울 것이 없다.

  • cluster-admin-role.yaml
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을 만들어보도록 하자.

  • cluster-admin-role-binding.yaml
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-admincluster-administrator role을 부여하여 cluster scope의 resource에 접근할 수 있는 권한을 부여한 것이다.

0개의 댓글