/엔지니어/Docker / 컨테이너/Kubernetes RBAC 완전 가이드 — Rol
Docker / 컨테이너고급linuxkubernetesrbacsecurity

Kubernetes RBAC 완전 가이드 — Role·RoleBinding·ServiceAccount 권한 제어

Role·ClusterRole·바인딩·ServiceAccount로 클러스터 권한을 최소화하는 법. kubectl auth can-i 디버깅과 CI 배포용 최소권한 예제까지 정리합니다.

RBAC란 — 누가·무엇을·어디서

Kubernetes RBAC(Role-Based Access Control)는 "어떤 주체(subject)가 어떤 리소스에 어떤 동작(verb)을 할 수 있는가"를 정의하는 권한 모델입니다. 클러스터를 여러 사람·팀·CI 파이프라인이 공유할 때, 최소권한 원칙을 강제하는 핵심 장치입니다.

RBAC는 네 가지 리소스의 조합으로 동작합니다.

리소스범위역할
Role네임스페이스권한의 묶음(정책)
ClusterRole클러스터 전체권한의 묶음(전역/노드/PV 등)
RoleBinding네임스페이스주체 ↔ Role 연결
ClusterRoleBinding클러스터 전체주체 ↔ ClusterRole 연결

핵심 규칙: Role/ClusterRole은 "무엇을 할 수 있는가"만 정의하고, 실제로 누구에게 부여할지는 Binding이 결정합니다.

RBAC는 덧셈만 있고 뺄셈이 없습니다(purely additive). "이건 금지"라는 거부 규칙이 없고, 명시적으로 허용된 것만 가능합니다. 여러 바인딩의 권한은 합집합으로 누적됩니다.


주체(Subject)의 세 종류

바인딩이 권한을 부여하는 대상은 세 가지입니다.

  • User: 사람 사용자(인증서·OIDC 등 외부 인증. K8s에 User 오브젝트는 없음)
  • Group: 사용자 그룹
  • ServiceAccount: Pod 안에서 동작하는 워크로드의 신원. CI 배포, 오퍼레이터, 앱이 API를 호출할 때 사용.

Role 만들기 — 네임스페이스 권한

dev 네임스페이스에서 Pod를 조회·로그 확인만 할 수 있는 Role입니다.

YAML
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: pod-reader
rules:
- apiGroups: [""]                      # "" = core API 그룹
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

verb는 get list watch create update patch delete deletecollection 중에서 고릅니다. resourcespods/log, pods/exec 같은 서브리소스도 별도로 지정할 수 있습니다.


RoleBinding — 주체에 연결

위 Role을 특정 ServiceAccount에 부여합니다.

YAML
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-deployer
  namespace: dev
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-can-read-pods
  namespace: dev
subjects:
- kind: ServiceAccount
  name: ci-deployer
  namespace: dev
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
Bash
kubectl apply -f rbac.yaml

roleRef한 번 만들면 수정할 수 없습니다. 참조할 Role을 바꾸려면 RoleBinding을 삭제하고 다시 만들어야 합니다.


ClusterRole과 재사용

ClusterRole은 클러스터 전역 리소스(노드, PersistentVolume, 네임스페이스 등)에 쓰거나, 여러 네임스페이스에서 재사용할 공통 권한을 정의할 때 씁니다.

핵심 패턴: ClusterRole을 RoleBinding으로 바인딩하면, 그 클러스터롤의 권한이 해당 네임스페이스에만 적용됩니다.

YAML
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deploy-in-dev
  namespace: dev
subjects:
- kind: ServiceAccount
  name: ci-deployer
  namespace: dev
roleRef:
  kind: ClusterRole          # 클러스터롤을...
  name: edit                 # (기본 제공되는 편집 권한)
  apiGroup: rbac.authorization.k8s.io

view / edit / admin / cluster-admin은 K8s가 기본 제공하는 ClusterRole입니다. 대부분의 실전 요구는 이들을 RoleBinding으로 특정 네임스페이스에 묶는 것으로 해결됩니다.


Pod에 ServiceAccount 연결

워크로드가 API 서버를 호출하려면 Pod에 SA를 지정합니다. 토큰은 자동으로 마운트됩니다.

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployer
  namespace: dev
spec:
  template:
    spec:
      serviceAccountName: ci-deployer
      # API 호출이 필요 없는 Pod는 토큰 자동 마운트를 끈다:
      automountServiceAccountToken: false
      containers:
      - name: app
        image: myapp:1.0

API를 호출하지 않는 일반 앱 Pod는 automountServiceAccountToken: false로 토큰 마운트를 꺼 두는 것이 보안상 안전합니다. 컨테이너가 탈취돼도 API 접근 토큰이 노출되지 않습니다.


권한 확인 — kubectl auth can-i

RBAC 디버깅의 핵심 명령입니다. 특정 주체가 어떤 동작을 할 수 있는지 직접 물어봅니다.

Bash
# 내가 dev에서 pod을 만들 수 있나?
kubectl auth can-i create pods -n dev

# 특정 ServiceAccount 관점에서 확인 (--as)
kubectl auth can-i list pods -n dev \
  --as=system:serviceaccount:dev:ci-deployer

# 이 SA가 할 수 있는 모든 것
kubectl auth can-i --list -n dev \
  --as=system:serviceaccount:dev:ci-deployer

ServiceAccount 사용자 이름 형식은 항상 system:serviceaccount:<네임스페이스>:<이름>입니다.


최소권한 실전 예시 — CI 배포용 SA

CI가 dev에서 Deployment만 관리하면 되는데 cluster-admin을 주는 것은 흔한 실수입니다. 딱 필요한 권한만 정의합니다.

YAML
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: deployment-manager
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch"]
  • 삭제 권한(delete)을 빼면 CI가 실수로 리소스를 지우는 사고를 원천 차단합니다.
  • 네임스페이스를 넘는 접근이 없으므로 prod는 영향받지 않습니다.

자주 겪는 문제

  • Forbidden 에러: 메시지에 필요한 apiGroup/resource/verb가 그대로 적혀 있습니다. 그걸 Role의 rules에 추가하세요.
  • apiGroup 헷갈림: Pod·Service·ConfigMap은 core(""), Deployment는 apps, Ingress는 networking.k8s.io. kubectl api-resources로 확인.
  • 바인딩은 됐는데 권한이 없음: roleRef 이름 오타 또는 SA 네임스페이스 불일치가 대부분. kubectl auth can-i --list --as=...로 실제 부여된 권한을 확인.
  • 과도한 ClusterRoleBinding: cluster-admin을 SA에 ClusterRoleBinding으로 묶으면 전 클러스터 장악입니다. 정말 필요한지 재검토하세요.

RBAC는 처음엔 리소스가 네 개라 복잡해 보이지만, "권한 묶음(Role) + 연결(Binding)"이라는 한 문장으로 정리됩니다. kubectl auth can-i를 옆에 두고 실제로 물어보며 좁혀 가면, 최소권한 구성이 훨씬 수월해집니다.

#kubernetes#rbac#security#serviceaccount#권한
편집 안내 · Editorial Note

이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.

질문 & 답변 (Q&A)

이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.