Theme:

클러스터에 접근하는 모든 사람이 모든 리소스를 생성/삭제할 수 있다면 어떤 일이 벌어질까요?

Kubernetes 클러스터에 여러 팀이 접근하고, Pod 내부의 애플리케이션이 API Server를 호출하는 환경에서는 "누가 무엇을 할 수 있는지"를 명확하게 제어해야 합니다. RBAC(Role-Based Access Control)은 역할 기반으로 리소스 접근 권한을 세밀하게 관리하는 Kubernetes의 핵심 보안 메커니즘입니다.

RBAC의 구성 요소

RBAC는 네 가지 오브젝트로 구성됩니다.

PLAINTEXT
Role / ClusterRole     → "무엇을 할 수 있는가" (권한 정의)
RoleBinding / ClusterRoleBinding → "누가 할 수 있는가" (권한 부여)
오브젝트범위설명
Role네임스페이스특정 네임스페이스의 리소스 권한
ClusterRole클러스터클러스터 전체 또는 비네임스페이스 리소스 권한
RoleBinding네임스페이스Role 또는 ClusterRole을 사용자/SA에 바인딩
ClusterRoleBinding클러스터ClusterRole을 클러스터 전체에 바인딩

Role — 네임스페이스 수준 권한

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

verbs (동작)

verb설명
get단일 리소스 조회
list리소스 목록 조회
watch변경 감시
create생성
update수정
patch부분 수정
delete삭제
deletecollection여러 리소스 일괄 삭제

apiGroups

apiGroups포함 리소스
"" (빈 문자열)Pod, Service, ConfigMap 등 코어 리소스
appsDeployment, StatefulSet, DaemonSet
batchJob, CronJob
networking.k8s.ioIngress, NetworkPolicy
rbac.authorization.k8s.ioRole, RoleBinding

ClusterRole — 클러스터 수준 권한

YAML
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-viewer
rules:
  - apiGroups: [""]
    resources: ["nodes"]       # 비네임스페이스 리소스
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["namespaces"]
    verbs: ["get", "list"]

ClusterRole은 다음 경우에 사용합니다.

  • 노드, PV, 네임스페이스 같은 비네임스페이스 리소스
  • 여러 네임스페이스에 동일한 권한을 부여할 때 (RoleBinding과 조합)

RoleBinding / ClusterRoleBinding

YAML
# RoleBinding — 특정 네임스페이스에 권한 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
  # 사용자
  - kind: User
    name: developer-kim
    apiGroup: rbac.authorization.k8s.io
  # 그룹
  - kind: Group
    name: dev-team
    apiGroup: rbac.authorization.k8s.io
  # ServiceAccount
  - kind: ServiceAccount
    name: app-sa
    namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
YAML
# ClusterRoleBinding — 클러스터 전체에 권한 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-viewer
subjects:
  - kind: Group
    name: ops-team
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view            # 기본 제공 ClusterRole
  apiGroup: rbac.authorization.k8s.io

중요한 조합 패턴

조합효과
Role + RoleBinding특정 네임스페이스에서만 권한
ClusterRole + ClusterRoleBinding클러스터 전체에서 권한
ClusterRole + RoleBinding특정 네임스페이스에서만 ClusterRole의 권한 (재사용)

ServiceAccount

ServiceAccount는 Pod이 API Server에 접근할 때 사용하는 신원입니다.

YAML
# ServiceAccount 생성
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: production
---
# Pod에서 ServiceAccount 사용
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  serviceAccountName: app-sa
  automountServiceAccountToken: true  # 토큰 자동 마운트
  containers:
    - name: app
      image: my-app:1.0

Kubernetes 1.24부터는 default ServiceAccount에 자동으로 토큰이 마운트되지 않으며, 필요한 경우 명시적으로 설정해야 합니다.

실무 권장 사항

YAML
# 불필요한 API 접근 차단
apiVersion: v1
kind: ServiceAccount
metadata:
  name: no-api-access
automountServiceAccountToken: false  # 토큰 마운트 비활성화

API Server에 접근하지 않는 일반 애플리케이션은 automountServiceAccountToken: false로 설정하는 것이 안전합니다.

기본 제공 ClusterRole

Kubernetes는 자주 사용하는 ClusterRole을 기본으로 제공합니다.

ClusterRole권한
view대부분의 리소스 읽기 (Secret 제외)
edit대부분의 리소스 읽기/쓰기 (Role, Binding 제외)
admin네임스페이스 내 모든 권한 (ResourceQuota, 네임스페이스 자체 제외)
cluster-admin클러스터 전체 모든 권한
SHELL
# 기본 ClusterRole 확인
kubectl get clusterroles | grep -E "^(view|edit|admin|cluster-admin)"

최소 권한 원칙 적용

팀별 네임스페이스 격리

YAML
# 개발팀 — 자신의 네임스페이스에서 edit 권한
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-team-edit
  namespace: team-a
subjects:
  - kind: Group
    name: team-a-devs
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
  apiGroup: rbac.authorization.k8s.io

CI/CD 파이프라인 전용 권한

YAML
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cicd-sa
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cicd-deployer
  namespace: production
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "update", "patch"]
  - apiGroups: [""]
    resources: ["configmaps", "secrets"]
    verbs: ["get", "list"]
    resourceNames: ["app-config", "app-secret"]  # 특정 리소스만

resourceNames로 특정 이름의 리소스만 접근하도록 더 세밀하게 제한할 수 있습니다.

권한 확인과 디버깅

SHELL
# 특정 사용자의 권한 확인
kubectl auth can-i create deployments --as developer-kim -n production
# yes

kubectl auth can-i delete pods --as developer-kim -n production
# no

# ServiceAccount의 권한 확인
kubectl auth can-i list pods --as system:serviceaccount:production:app-sa -n production

# 현재 사용자가 할 수 있는 모든 것 확인
kubectl auth can-i --list -n production

실무에서 주의할 점

  • cluster-admin은 최소한으로: 인프라 관리자에게만 부여하세요
  • default ServiceAccount 사용 지양: 각 워크로드에 전용 SA를 생성하세요
  • Secret 접근 제한: view ClusterRole은 Secret을 제외하지만, 명시적으로 확인하세요
  • 정기 감사: 불필요한 RoleBinding을 정기적으로 정리하세요

정리

RBAC는 Role로 "무엇을 할 수 있는지" 정의하고, RoleBinding으로 "누구에게" 부여하는 구조입니다. ServiceAccount로 Pod의 API 접근 권한을 제어하고, 최소 권한 원칙을 적용하여 필요한 만큼만 권한을 부여하는 것이 보안의 핵심입니다.

댓글 로딩 중...