LabHub
배우기 러닝패스 코스

KCNA — Kubernetes・クラウドネイティブ入門

名前は同じなのに権限が違う

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

서비스어카운트 reader 하나에 Role·RoleBinding·ClusterRole·ClusterRoleBinding 을 차례로 붙이며, 권한이 어디까지(네임스페이스/클러스터) 그리고 무엇까지(동사·리소스) 미치는지를 kubectl auth can-i --as 로 직접 확인합니다. 토큰 자동 마운트를 끄는 법도 함께 봅니다.

왜 중요한가

쿠버네티스 API 서버에 들어오는 모든 요청은 "누가(주체) 무엇을(동사) 어디에(리소스·네임스페이스)" 로 판정됩니다. RBAC 은 허용 목록만 있고 거부 규칙이 없어서, 권한은 바인딩이 늘수록 합집합으로만 커집니다. 이름이 같은 reader 라도 어떤 바인딩이 어느 범위에 붙었느냐에 따라 할 수 있는 일이 완전히 달라집니다.

Role 은 한 네임스페이스 안에서만 유효하고, 노드처럼 네임스페이스가 없는 리소스는 ClusterRole 과 ClusterRoleBinding 으로만 권한을 줄 수 있습니다. 또 파드는 기본으로 서비스어카운트 토큰을 받으므로, API 를 쓰지 않는 파드에서 이를 끄는 것이 최소 권한의 첫걸음입니다.

단계

  1. 네임스페이스 kcna-rbac 와 서비스어카운트 reader 를 만듭니다.
  2. Role pod-viewer(pods get/list/watch)와 RoleBinding reader-pods 를 만듭니다.
  3. 같은 권한이 default 네임스페이스에서는 통하지 않음을 확인해 scope.txt 에 적습니다.
  4. 별도의 Role cm-viewer(configmaps get/list)와 RoleBinding reader-cms 를 만듭니다.
  5. ClusterRole node-viewer 와 ClusterRoleBinding reader-nodes 로 노드 조회를 허용합니다.
  6. 파드 app 을 reader 로 돌리되 토큰 자동 마운트를 끕니다.
  7. reader 가 파드를 만들거나 와일드카드 권한을 쓰지 못함을 확인해 write-check.txt 에 적습니다.
  8. 네 가지 can-i 결과를 /root/kcna-rbac/report.txt 에 장부로 남깁니다.

참고

권한 없는 신입 계정이 도착하다

네임스페이스 kcna-rbac 를 만들고, 그 안에 서비스어카운트 reader 를 만듭니다.

서비스어카운트는 사람이 아닌 워크로드가 API 서버에 자신을 밝히는 신원입니다. 네임스페이스에 속하는 오브젝트라서 네임스페이스를 먼저 만들어야 합니다. create 를 --dry-run=client -o yaml 로 뽑아 apply 하면 여러 번 돌려도 안전합니다. 만든 직후의 reader 는 아무 권한도 없습니다.

파드를 보게만 해 주고 지우지는 못하게

네임스페이스 kcna-rbac 에 Role pod-viewer 를 만듭니다. 규칙은 코어 그룹("")의 pods 에 대한 get·list·watch 딱 그것뿐이어야 합니다. 그리고 RoleBinding reader-pods 로 이 Role 을 서비스어카운트 kcna-rbac:reader 에 묶습니다.

RBAC 은 허용만 있고 거부는 없습니다. Role 은 "무엇을 할 수 있는가" 의 목록이고, RoleBinding 은 그 목록을 "누구에게" 줄지 정합니다. 파드는 코어 API 그룹이라 apiGroups 가 빈 문자열입니다. kubectl create role 의 --verb/--resource, kubectl create rolebinding 의 --role/--serviceaccount (형식은 네임스페이스:이름) 옵션을 살펴보세요. 확인은 kubectl auth can-i <동사> pods --as=system:serviceaccount:<ns>:<이름> 로 합니다.

옆 네임스페이스에서는 아무것도 안 보인다

새 오브젝트는 만들지 않습니다. reader 가 default 네임스페이스에서 파드를 list 할 수 있는지 kubectl auth can-i 로 확인하고, 그 결과를 /root/kcna-rbac/scope.txtlist-pods-default=<yes|no> 한 줄로 적습니다.

Role 과 RoleBinding 은 네임스페이스에 속합니다. 그래서 그 권한은 바인딩이 있는 네임스페이스 안에서만 유효합니다. -n 값만 바꿔 같은 질문을 두 번 던져 보세요. 추측으로 적지 말고 can-i 가 돌려준 값을 그대로 옮기세요.

권한은 덧붙이는 게 아니라 따로 묶는다

기존 pod-viewer 는 건드리지 않고, 네임스페이스 kcna-rbac별도의 Role cm-viewer 를 만듭니다. 규칙은 코어 그룹의 configmaps 에 대한 get·list 입니다. RoleBinding reader-cms 로 reader 에 묶습니다. reader 는 컨피그맵을 list 할 수 있지만 delete 는 할 수 없어야 합니다.

한 주체에 여러 바인딩이 붙으면 권한은 합집합이 됩니다. 그래서 역할을 용도별로 잘게 나눠 두면 나중에 하나만 떼어 내기 쉽습니다. pod-viewer 에 configmaps 를 끼워 넣으면 채점기가 잡습니다. 02 단계와 같은 방식으로 역할과 바인딩을 하나씩 만들면 됩니다.

노드는 네임스페이스 밖에 산다

ClusterRole node-viewer(코어 그룹 nodes 에 대한 get·list)를 만들고, ClusterRoleBinding reader-nodes 로 서비스어카운트 kcna-rbac:reader 에 묶습니다. reader 가 노드를 list 할 수 있어야 합니다.

노드·PV·StorageClass 같은 클러스터 범위 리소스는 네임스페이스가 없어서 Role 로는 권한을 줄 수 없습니다. ClusterRole 을 RoleBinding 으로 묶으면 여전히 한 네임스페이스 안으로만 범위가 좁혀지므로, 노드를 보려면 ClusterRoleBinding 이 필요합니다. kubectl create clusterrolebinding 의 --clusterrole 옵션을 보세요. 노드에 대한 can-i 에는 -n 을 붙이지 않습니다.

API 를 쓸 일 없는 파드에 열쇠를 쥐여 주지 않는다

네임스페이스 kcna-rbac 에 파드 app(이미지 nginx:1.27-alpine)을 만듭니다. 이 파드는 서비스어카운트 reader 로 돌되, 서비스어카운트 토큰이 자동으로 마운트되지 않도록 automountServiceAccountTokenfalse 로 둡니다.

파드는 기본적으로 자기 서비스어카운트의 토큰을 kube-api-access-* 볼륨으로 받습니다. 컨테이너가 뚫리면 그 토큰으로 API 를 부를 수 있으니, API 를 쓰지 않는 파드는 토큰을 받지 않는 게 좋습니다. 파드 spec 에 serviceAccountName 과 automountServiceAccountToken 두 필드를 함께 적으세요. kubectl get pod app -o yaml 에서 volumes 에 kube-api-access 가 없는지도 확인해 보세요.

읽기 전용 계정이 파드를 만들려 한다면

reader 가 네임스페이스 kcna-rbac 에서 파드를 create 할 수 있는지, 그리고 모든 리소스에 모든 동사(와일드카드)를 쓸 수 있는지 kubectl auth can-i 로 확인합니다. 둘 다 no 여야 합니다. 파드 create 결과를 /root/kcna-rbac/write-check.txtcreate-pods=<yes|no> 한 줄로 적습니다.

지금까지 준 동사는 get·list·watch 뿐입니다. create 는 따로 허용하지 않는 한 거부됩니다. 와일드카드 질문은 리소스와 동사 자리에 따옴표로 감싼 별표를 넣어 던질 수 있습니다. 여기서 yes 가 나온다면 앞 단계에서 권한을 너무 넓게 준 것이니 Role 규칙을 다시 보세요.

reader 의 권한 지도를 장부로 남기기

reader 의 권한을 /root/kcna-rbac/report.txt 에 정확히 네 줄로 적습니다 — list-pods-in-ns=yes, list-pods-in-default=no, list-nodes=yes, create-pods=no. 값은 실제 kubectl auth can-i 결과와 일치해야 합니다.

채점기는 각 줄을 서비스어카운트 reader 로 가장한 실제 can-i 결과와 대조합니다. 네 질문은 각각 kcna-rbac 의 pods list, default 의 pods list, 클러스터 범위 nodes list, kcna-rbac 의 pods create 입니다. 직접 물어본 답을 옮기세요.