쿠버네티스 운영 실무 · RBAC — Role·ClusterRole·바인딩 · 이론
RBAC — 네 개의 오브젝트와 하나의 함정
한 줄 요약
RBAC 는 "무엇을 할 수 있는가"(Role)와 "누가 어디서 그것을 할 수 있는가"(Binding)를 분리한 모델이고, 범위를 정하는 쪽은 언제나 Binding 이다.
왜 이게 필요했나
권한을 파일 하나에 다 적으면 두 가지가 곧바로 무너진다. 사람이 늘어날 때마다 같은 권한 묶음을 복사해야 하고, 어떤 권한이 어디까지 미치는지 아무도 추적하지 못하게 된다. RBAC 는 이 둘을 갈라 놓는다. 권한의 내용은 Role 과 ClusterRole 이 정의하고, 그 내용을 누구에게 어느 범위로 줄지는 RoleBinding 과 ClusterRoleBinding 이 정한다.
| 오브젝트 | 스코프 | 하는 일 |
| --- | --- | --- |
| Role | 네임스페이스 | 그 네임스페이스 리소스에 대한 규칙 |
| ClusterRole | 클러스터 | 클러스터 범위 리소스 또는 재사용할 공통 권한 |
| RoleBinding | 네임스페이스 | 역할을 주체에게, 이 네임스페이스에서만 |
| ClusterRoleBinding | 클러스터 | 역할을 주체에게, 클러스터 전체에서 |
어떻게 동작하나
규칙 하나는 세 조각이다. apiGroups, resources, verbs.
rules: - apiGroups: [""] # 코어 그룹은 빈 문자열 resources: ["pods"] verbs: ["get", "list", "watch"]apiGroups: [""] 를 빠뜨려 파드가 안 보인다는 문의는 지금도 매주 나온다. 코어 API 그룹의 이름은 빈 문자열이고, Deployment 같은 것은 apps 그룹에 있다.
여기서 가장 중요한 함정이 나온다. ClusterRole 을 RoleBinding 으로 걸면 그 권한은 해당 네임스페이스에서만 유효하다. 즉 역할의 종류가 스코프를 정하는 것이 아니라 바인딩의 종류가 정한다. 이 조합은 실무에서 대단히 유용하다. "읽기 전용" 같은 공통 권한 묶음을 ClusterRole 로 한 번만 정의해 두고, 팀마다 자기 네임스페이스에서 RoleBinding 으로 걸어 쓰면 된다. 같은 ClusterRole 을 ClusterRoleBinding 으로 걸었다면 그 순간 클러스터 전체 권한이 된다. 두 매니페스트의 차이는 단어 하나다.
두 번째로 자주 놓치는 것이 서브리소스다. pods/log 와 pods/exec 는 pods 와 별개의 리소스 이름이다. 파드를 읽을 권한이 있다고 로그가 읽히지 않고, 로그를 읽을 권한이 있다고 셸에 붙을 수 있는 것도 아니다. 로그 수집 봇에게 pods/log 의 get 만 주는 설계가 가능한 이유이고, 반대로 pods/exec 를 아무에게나 열어 두면 컨테이너 안에서 무엇이든 할 수 있게 된다는 뜻이기도 하다.
세 번째는 확인 방법이다. 권한은 작성한 것이 아니라 판정되는 것이므로 눈으로 읽지 말고 물어봐야 한다.
kubectl auth can-i list pods -n rbac-lab \ --as=system:serviceaccount:rbac-lab:app-reader# yes--as 는 impersonation 이다. 서비스 어카운트의 정식 이름 형식이 system:serviceaccount:<네임스페이스>:<이름> 이라는 것만 알면 어떤 주체로든 흉내 내어 물어볼 수 있다. 되는 것과 안 되는 것을 함께 확인해야 의미가 있다. yes 만 확인하면 권한이 필요 이상으로 넓어도 알 수 없다.
현장에서 만나는 모습
첫째, 와일드카드는 한 번 들어가면 안 빠진다. verbs: ["*"] 는 편하지만, 나중에 새 리소스가 생기면 아무도 모르는 사이에 권한이 자동으로 넓어진다. 최소 권한은 취향이 아니라 시간이 지나도 범위가 커지지 않게 만드는 장치다.
둘째, get secrets 는 사실상 자격증명 열람 권한이다. 개발자에게 편의로 준 편집 권한이 프로덕션 데이터베이스 비밀번호 열람 권한과 같아지는 경우가 흔하다. 이 이야기는 다음 모듈로 이어진다.
셋째, 정기 감사. cluster-admin 이 걸린 ClusterRoleBinding 목록, 와일드카드를 쓴 역할, secrets 를 읽을 수 있는 역할 — 이 세 가지 질문은 클러스터마다 주기적으로 던져야 한다. kubectl get clusterrolebindings -o json | jq 몇 줄이면 답이 나오고, 이 습관 하나가 권한 부채가 쌓이는 속도를 크게 낮춘다.
다음 실습에서 할 것
읽기 전용 Role 을 만들어 서비스 어카운트에 바인딩하고 auth can-i 로 경계를 확인한다. 노드 같은 클러스터 범위 리소스를 위한 ClusterRole 을 만들고, 같은 ClusterRole 을 RoleBinding 으로 걸어 스코프가 어떻게 좁아지는지 직접 본다. 서브리소스만 여는 역할을 만들고, 마지막에는 클러스터의 위험한 권한을 훑는 감사 보고서를 JSON 으로 만든다.