Kubernetes RBAC를 처음 배울 때 자주 헷갈리는 지점이 있다. Role과 ClusterRole, RoleBinding과 ClusterRoleBinding, 그리고 --role과 --clusterrole의 경계다. 이름이 비슷해서 “권한을 준다”는 느낌만 남기 쉽지만, 실제 운영에서는 이 경계가 권한 범위를 결정한다.
이번 실습의 목표는 release bot이 한 namespace 안에서 workload 상태만 읽게 만드는 것이었다. 필요한 권한은 Pods, Deployments, ReplicaSets에 대한 read-only 접근이었다. Secrets 조회, Pod 삭제, 전체 namespace 조회는 허용하면 안 됐다.
핵심은 Role + RoleBinding을 쓰고, kubectl auth can-i로 허용되는 작업과 거부되는 작업을 모두 확인하는 것이다. RBAC 검증은 yes만 보면 부족하다. 최소 권한을 증명하려면 no가 나와야 하는 명령도 같이 확인해야 한다.
참고 문서:
release bot 역할을 하는 ServiceAccount를 하나 만들고, 같은 namespace 안의 workload만 읽을 수 있는 Role을 붙인다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: release-reader
namespace: cka-a04-retest
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: release-read-workloads
namespace: cka-a04-retest
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: release-read-workloads
namespace: cka-a04-retest
subjects:
- kind: ServiceAccount
name: release-reader
namespace: cka-a04-retest
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: release-read-workloads
여기서 Role은 namespace-scoped 리소스다. 같은 이름의 Role이 있어도 namespace가 다르면 별개의 권한이다. RoleBinding은 이 Role을 ServiceAccount에 연결한다.
먼저 ServiceAccount, Role, RoleBinding이 namespace 안에 만들어졌는지 확인했다.
kubectl get sa,role,rolebinding -n cka-a04-retest
NAME SECRETS AGE
serviceaccount/default 0 6m2s
serviceaccount/release-reader 0 5m49s
NAME CREATED AT
role.rbac.authorization.k8s.io/release-read-workloads 2026-08-29T08:08:14Z
NAME ROLE AGE
rolebinding.rbac.authorization.k8s.io/release-read-workloads Role/release-read-workloads 9s
Role에는 Pods, Deployments, ReplicaSets 읽기 권한만 들어 있다.
kubectl describe role release-read-workloads -n cka-a04-retest
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch]
deployments.apps [] [] [get list watch]
replicasets.apps [] [] [get list watch]
RoleBinding도 ClusterRole이 아니라 namespaced Role을 참조한다.
kubectl describe rolebinding release-read-workloads -n cka-a04-retest
Role:
Kind: Role
Name: release-read-workloads
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount release-reader cka-a04-retest
kubectl auth can-i는 특정 주체가 특정 API 작업을 할 수 있는지 확인하는 명령이다. ServiceAccount 권한을 확인할 때는 --as=system:serviceaccount:<namespace>:<serviceaccount> 형식을 사용한다.
이번 실습에서는 다음 작업이 허용되어야 했다.
get pods: yes
list deployments: yes
watch replicasets: yes
이 결과는 release bot이 rollout 상태를 읽는 데 필요한 기본 workload 조회 권한을 갖고 있음을 보여준다.
최소 권한은 허용 목록만으로는 증명되지 않는다. 필요 없는 권한이 실제로 막혀 있는지도 봐야 한다.
이번 실습에서는 다음 작업이 거부되어야 했다.
get secrets: no
delete pods: no
get pods --all-namespaces: no
이 세 가지는 의미가 다르다. Secrets 조회가 막혔다는 것은 민감한 설정과 토큰에 접근하지 못한다는 뜻이다. Pod 삭제가 막혔다는 것은 release bot이 workload를 파괴할 수 없다는 뜻이다. --all-namespaces 조회가 막혔다는 것은 권한이 특정 namespace 안에 갇혀 있다는 뜻이다.
ClusterRoleBinding도 만들어지지 않았는지 확인했다.
kubectl get clusterrolebinding | grep release-reader || echo "no clusterrolebinding for release-reader"
no clusterrolebinding for release-reader
이번 요구사항은 한 namespace 안의 workload 상태를 읽는 것이다. cluster-wide 권한이 필요하지 않다. 그래서 Role + RoleBinding이 맞다.
ClusterRole은 cluster-scoped 리소스에 대한 권한을 정의하거나 여러 namespace에 재사용할 수 있는 권한 묶음을 만들 때 쓴다. ClusterRoleBinding은 그 권한을 cluster 전체에 붙인다. 요구사항이 namespace 하나로 충분한데 ClusterRoleBinding을 쓰면 권한 경계가 넓어진다.
이번 실습에서 release bot은 cka-a04-retest 안의 Pods, Deployments, ReplicaSets만 읽으면 된다. Secrets도 필요 없고, Pod 삭제도 필요 없고, 다른 namespace 조회도 필요 없다. 이 정도 요구사항에는 namespaced Role이 더 작고 명확하다.
RBAC가 예상대로 동작하지 않을 때는 리소스를 순서대로 분해해서 본다.
kubectl get serviceaccount release-reader -n cka-a04-retest
kubectl describe role release-read-workloads -n cka-a04-retest
kubectl describe rolebinding release-read-workloads -n cka-a04-retest
kubectl auth can-i get pods -n cka-a04-retest --as=system:serviceaccount:cka-a04-retest:release-reader
kubectl auth can-i list deployments -n cka-a04-retest --as=system:serviceaccount:cka-a04-retest:release-reader
kubectl auth can-i watch replicasets -n cka-a04-retest --as=system:serviceaccount:cka-a04-retest:release-reader
kubectl auth can-i get secrets -n cka-a04-retest --as=system:serviceaccount:cka-a04-retest:release-reader
kubectl auth can-i delete pods -n cka-a04-retest --as=system:serviceaccount:cka-a04-retest:release-reader
kubectl auth can-i get pods --all-namespaces --as=system:serviceaccount:cka-a04-retest:release-reader
RBAC는 세 가지 질문으로 보면 이해하기 쉽다.
Who
-> ServiceAccount release-reader
What
-> pods, deployments, replicasets
Which action
-> get, list, watch
Kubernetes 리소스로 풀면 이렇게 연결된다.
ServiceAccount
-> RoleBinding subject
-> Role
-> rules: resources + verbs
Role은 “무엇을 할 수 있는가”를 정의한다. RoleBinding은 “누가 그 Role을 받는가”를 정한다. ServiceAccount는 workload가 Kubernetes API를 호출할 때 쓰는 identity다.
이번 실습의 핵심은 RBAC를 만들었다는 사실보다 권한 범위를 증명했다는 점이다. get pods, list deployments, watch replicasets는 yes가 나와야 했다. 반대로 get secrets, delete pods, get pods --all-namespaces는 no가 나와야 했다.
RBAC는 허용만 확인하면 반쪽짜리 검증이 된다. 운영에서 중요한 것은 필요한 작업은 되게 하고, 필요 없는 작업은 막는 것이다. kubectl auth can-i를 쓸 때도 이 습관을 들이면 권한 설계가 훨씬 선명해진다.