Post

Part 17/26: RBAC와 ServiceAccount

Part 17/26: RBAC와 ServiceAccount

Kubernetes의 RBAC(Role-Based Access Control)은 “누가” “무엇을” “어디서” 할 수 있는지를 제어한다. API 요청의 인증(Authentication) 이후 인가(Authorization) 단계에서 RBAC 규칙이 적용된다.

RBAC 기본 개념

핵심 구성 요소

1
2
3
4
5
6
7
8
9
10
11
12
┌─────────────────────────────────────────────────────────────┐
│                         RBAC                                │
├─────────────────────────────────────────────────────────────┤
│  Subject          Role/ClusterRole      RoleBinding/       │
│  (누가)     +     (무엇을)         +    ClusterRoleBinding │
│                                          (연결)             │
│  - User                                                     │
│  - Group           - rules:                                 │
│  - ServiceAccount    - apiGroups                           │
│                      - resources                            │
│                      - verbs                                │
└─────────────────────────────────────────────────────────────┘

Subject: 권한을 부여받는 대상

  • User: 사람 (Kubernetes가 관리하지 않음)
  • Group: 사용자 그룹
  • ServiceAccount: Pod가 사용하는 계정

Role/ClusterRole: 권한 정의

  • Role: Namespace 범위
  • ClusterRole: 클러스터 전체 범위

RoleBinding/ClusterRoleBinding: Subject와 Role 연결

  • RoleBinding: Namespace 내 권한 부여
  • ClusterRoleBinding: 클러스터 전체 권한 부여

Role과 ClusterRole

Role (Namespace 범위)

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]           # core API group (v1)
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: [""]
  resources: ["pods/log"]   # subresource
  verbs: ["get"]

ClusterRole (클러스터 범위)

1
2
3
4
5
6
7
8
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

ClusterRole이 필요한 경우:

  • 클러스터 범위 리소스 (nodes, persistentvolumes 등)
  • 모든 Namespace의 리소스에 대한 권한
  • 비리소스 URL (/healthz, /api 등)

apiGroups

apiGroup리소스 예시
”” (core)pods, services, secrets, configmaps
appsdeployments, replicasets, statefulsets
batchjobs, cronjobs
networking.k8s.ioingresses, networkpolicies
rbac.authorization.k8s.ioroles, rolebindings
storage.k8s.iostorageclasses, csidrivers
1
2
3
# API 그룹 확인
kubectl api-resources
kubectl api-resources -o wide  # 상세 정보

verbs (동작)

Verb설명HTTP Method
get단일 리소스 조회GET
list리소스 목록 조회GET
watch변경 감시GET (watch)
create리소스 생성POST
update전체 업데이트PUT
patch부분 업데이트PATCH
delete단일 삭제DELETE
deletecollection복수 삭제DELETE

resourceNames (특정 리소스만)

1
2
3
4
5
6
7
8
9
10
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: configmap-updater
  namespace: default
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["app-config"]  # 특정 ConfigMap만
  verbs: ["get", "update"]

RoleBinding과 ClusterRoleBinding

RoleBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
  name: monitoring-sa
  namespace: monitoring
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-binding
subjects:
- kind: Group
  name: system:masters
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: admin@example.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

RoleBinding으로 ClusterRole 참조

ClusterRole을 RoleBinding으로 참조하면 특정 Namespace에서만 해당 권한이 적용된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ClusterRole 정의
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-manager
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["*"]
---
# RoleBinding으로 참조 → development namespace에서만 적용
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-manager-binding
  namespace: development
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole  # ClusterRole 참조
  name: pod-manager
  apiGroup: rbac.authorization.k8s.io

활용 패턴: 공통 ClusterRole을 정의하고, 각 Namespace에서 RoleBinding으로 재사용.

ServiceAccount

ServiceAccount 개념

Pod가 API Server와 통신할 때 사용하는 신원(identity)이다.

1
2
3
4
5
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
  namespace: default

Pod에서 ServiceAccount 사용

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  serviceAccountName: my-service-account
  containers:
  - name: app
    image: myapp:1.0

기본 동작:

  • 지정하지 않으면 default ServiceAccount 사용
  • ServiceAccount 토큰이 /var/run/secrets/kubernetes.io/serviceaccount/에 마운트됨

자동 토큰 마운트 비활성화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: ServiceAccount
metadata:
  name: no-token-sa
automountServiceAccountToken: false
---
# 또는 Pod 수준에서
apiVersion: v1
kind: Pod
metadata:
  name: no-token-pod
spec:
  serviceAccountName: my-sa
  automountServiceAccountToken: false
  containers:
  - name: app
    image: myapp:1.0

ServiceAccount에 권한 부여

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# ServiceAccount 생성
apiVersion: v1
kind: ServiceAccount
metadata:
  name: deployment-manager
  namespace: production
---
# Role 생성
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployment-role
  namespace: production
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "update", "delete"]
---
# RoleBinding으로 연결
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deployment-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: deployment-manager
  namespace: production
roleRef:
  kind: Role
  name: deployment-role
  apiGroup: rbac.authorization.k8s.io

기본 ClusterRole

Kubernetes에 내장된 기본 ClusterRole들:

ClusterRole설명
cluster-admin모든 권한 (superuser)
adminNamespace 관리자 권한
edit대부분의 리소스 읽기/쓰기
view읽기 전용
1
2
3
4
5
# 기본 ClusterRole 확인
kubectl get clusterrole | grep -E "^(cluster-admin|admin|edit|view)"

# 상세 확인
kubectl describe clusterrole edit

system: 접두사

system: 접두사가 붙은 Role/ClusterRole은 시스템 컴포넌트용이다.

  • system:node: kubelet용
  • system:kube-scheduler: 스케줄러용
  • system:kube-controller-manager: 컨트롤러 매니저용

주의: 시스템 역할을 수정하지 않는 것이 좋다.

권한 확인

kubectl auth can-i

1
2
3
4
5
6
7
8
9
10
11
# 현재 사용자의 권한 확인
kubectl auth can-i create deployments
kubectl auth can-i delete pods --namespace production

# 다른 사용자 확인 (admin 권한 필요)
kubectl auth can-i create pods --as jane
kubectl auth can-i list secrets --as system:serviceaccount:default:my-sa

# 모든 권한 나열
kubectl auth can-i --list
kubectl auth can-i --list --as jane --namespace development

권한 검증 예시

1
2
3
4
5
6
# ServiceAccount 권한 테스트
kubectl auth can-i get pods --as system:serviceaccount:default:my-sa
# yes

kubectl auth can-i delete pods --as system:serviceaccount:default:my-sa
# no

실전 시나리오

개발자용 Namespace 권한

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 개발자 그룹에게 development namespace 전체 권한
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-admin
  namespace: development
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io

읽기 전용 접근

1
2
3
4
5
6
7
8
9
10
11
12
13
# 모니터링 서비스에게 모든 namespace 읽기 권한
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: monitoring-view
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitoring
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

CI/CD 파이프라인용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# CI/CD ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cicd-deployer
  namespace: cicd
---
# 배포 권한
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: deployer
rules:
- apiGroups: ["", "apps", "networking.k8s.io"]
  resources: ["deployments", "services", "ingresses", "configmaps", "secrets"]
  verbs: ["get", "list", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
# production namespace에만 적용
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cicd-deployer-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: cicd-deployer
  namespace: cicd
roleRef:
  kind: ClusterRole
  name: deployer
  apiGroup: rbac.authorization.k8s.io

특정 리소스만 접근

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 특정 ConfigMap과 Secret만 접근 가능
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-config-reader
  namespace: production
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["app-config", "feature-flags"]
  verbs: ["get", "watch"]
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["app-credentials"]
  verbs: ["get"]

트러블슈팅

권한 거부 디버깅

1
2
3
4
5
6
7
8
9
10
11
12
# 에러 예시
# Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods"

# 1. 현재 권한 확인
kubectl auth can-i --list --as jane

# 2. 관련 RoleBinding 확인
kubectl get rolebindings,clusterrolebindings -o wide | grep jane

# 3. Role 상세 확인
kubectl describe role <role-name>
kubectl describe clusterrole <clusterrole-name>

일반적인 실수

1. apiGroups 누락:

1
2
3
4
5
6
7
8
9
10
11
# 잘못됨 - deployments는 apps 그룹
rules:
- apiGroups: [""]
  resources: ["deployments"]  # 실패
  verbs: ["get"]

# 올바름
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get"]

2. Namespace 불일치:

1
2
3
4
5
# RoleBinding은 반드시 대상 Namespace에 있어야 함
kind: RoleBinding
metadata:
  name: binding
  namespace: production  # 이 namespace에서만 유효

3. Subject 형식 오류:

1
2
3
4
5
6
7
8
9
10
# ServiceAccount subject
subjects:
- kind: ServiceAccount
  name: my-sa
  namespace: default  # ServiceAccount는 namespace 필요
# User subject
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io  # User는 apiGroup 필요

기술 면접 대비

자주 묻는 질문

Q: Role과 ClusterRole의 차이는?

A: Role은 Namespace 범위의 권한을 정의하고, 해당 Namespace 내 리소스에만 적용된다. ClusterRole은 클러스터 전체 범위로, nodes나 PersistentVolumes 같은 클러스터 범위 리소스나 모든 Namespace의 리소스에 대한 권한을 정의할 수 있다. ClusterRole을 RoleBinding으로 참조하면 특정 Namespace에서만 적용되어 재사용성이 높아진다.

Q: RoleBinding과 ClusterRoleBinding의 차이는?

A: RoleBinding은 특정 Namespace 내에서 Subject에게 Role(또는 ClusterRole)의 권한을 부여한다. ClusterRoleBinding은 클러스터 전체에서 권한을 부여한다. RoleBinding이 ClusterRole을 참조해도 해당 Namespace 내로 권한이 제한된다.

Q: ServiceAccount가 필요한 이유는?

A: Pod 내 애플리케이션이 Kubernetes API와 상호작용해야 할 때 신원(identity)을 제공한다. 기본 ServiceAccount는 권한이 제한되어 있으므로, 필요한 권한만 가진 ServiceAccount를 생성하여 최소 권한 원칙을 적용할 수 있다. 또한 ServiceAccount 토큰을 통해 Pod를 인증한다.

Q: kubectl auth can-i 명령의 용도는?

A: 특정 동작에 대한 권한이 있는지 확인한다. 현재 사용자의 권한은 물론, --as 플래그로 다른 사용자나 ServiceAccount의 권한도 확인할 수 있다. RBAC 설정 검증이나 트러블슈팅에 유용하다.

Q: 최소 권한 원칙(Principle of Least Privilege)을 RBAC에서 어떻게 적용하는가?

A: 필요한 권한만 부여한다. 넓은 범위의 기본 ClusterRole(cluster-admin, admin) 대신 필요한 리소스와 동작만 포함한 커스텀 Role을 만든다. ClusterRole 대신 Role, ClusterRoleBinding 대신 RoleBinding을 사용하여 범위를 제한한다. resourceNames로 특정 리소스만 지정할 수 있다.

CKA 시험 대비 필수 명령어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Role/ClusterRole 생성
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n development
kubectl create clusterrole deployment-reader --verb=get,list --resource=deployments

# RoleBinding/ClusterRoleBinding 생성
kubectl create rolebinding pod-reader-binding --role=pod-reader --user=jane -n development
kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=admin

# ServiceAccount 생성
kubectl create serviceaccount my-sa -n default

# ServiceAccount에 바인딩
kubectl create rolebinding sa-binding --role=pod-reader --serviceaccount=default:my-sa -n default

# 권한 확인
kubectl auth can-i list pods
kubectl auth can-i create deployments --as jane
kubectl auth can-i --list --as system:serviceaccount:default:my-sa

# 조회
kubectl get roles,rolebindings -n <namespace>
kubectl get clusterroles,clusterrolebindings
kubectl describe role <role-name> -n <namespace>

# API 리소스 확인
kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false

CKA 빈출 시나리오

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 시나리오 1: 특정 namespace에서 Pod 관리 권한
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-manager
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-pod-manager
  namespace: development
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-manager
  apiGroup: rbac.authorization.k8s.io

# 시나리오 2: ServiceAccount에 ClusterRole 바인딩
apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-sa
  namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dashboard-view
subjects:
- kind: ServiceAccount
  name: dashboard-sa
  namespace: monitoring
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

# 시나리오 3: 명령형으로 빠르게 생성
# kubectl create role deployment-reader --verb=get,list --resource=deployments -n prod
# kubectl create rolebinding deployer --role=deployment-reader --user=jane -n prod

다음 단계

This post is licensed under CC BY 4.0 by the author.