본문으로 건너뛰기
버전: 1.0.3

7.1. 접근 권한 (RBAC)

어떨 때 보는가

  • 팀원에게 특정 네임스페이스만 볼 수 있게 하고 싶을 때
  • "권한이 없습니다" 오류가 날 때
  • 파드가 클러스터 API 를 부르지 못할 때

RBAC 란 무엇인가

RBAC(Role-Based Access Control)는 역할 기반 접근 제어 입니다. 사람마다 권한을 따로 주지 않고, 역할 을 만들어 그 역할에 권한을 담은 뒤 사람에게 역할을 주는 방식입니다.

방식인원이 늘면
사람마다 권한 부여"김OO 은 파드 조회 가능, 이OO 도 파드 조회 가능..."사람 수만큼 설정이 늘어납니다
역할 기반"개발자 역할 = 파드 조회. 김OO·이OO 은 개발자"역할 하나에 사람만 추가합니다

Kubernetes 는 모든 조작이 API 호출입니다. Console 에서 버튼을 누르는 것도, 명령어를 치는 것도, 파드가 다른 자원을 읽는 것도 전부 API 를 부릅니다. RBAC 는 그 API 호출 하나하나를 허용할지 판단합니다.

세 가지 자원으로 나눈 이유

RBAC 는 세 가지 자원으로 이루어집니다.

자원담는 것답하는 질문
롤 (Role)할 수 있는 일"무엇을 할 수 있는가"
대상 (Subject)사용자·그룹·서비스 어카운트"누구인가"
롤 바인딩 (RoleBinding)둘의 연결"누가 무엇을 할 수 있는가"

나눈 덕분에 역할 하나를 여러 사람에게 재사용 할 수 있고, 사람이 바뀌어도 역할은 그대로 둘 수 있습니다.

롤을 만들어도 바인딩하지 않으면 아무 효력이 없습니다. 권한 문제의 절반은 여기서 생깁니다. 역할을 만든 것과 그 역할을 준 것은 다른 일입니다.

접근 권한 구조

접근 권한 구조

서비스 어카운트란

파드가 클러스터 API 를 부를 때 쓰는 계정 입니다.

사람은 외부 인증 서버(SSO)에 계정이 있지만, 파드는 그런 계정이 없습니다. 그렇다고 아무나 API 를 부르게 두면 안 되므로, 클러스터 안에서 쓰는 계정을 따로 둡니다.

보안 > 서비스 계정 으로 들어갑니다.

서비스 어카운트 목록

파드를 만들 때 서비스 어카운트를 지정하면, 그 계정의 인증 토큰이 파드 안에 자동으로 주입됩니다. 파드 안의 프로그램은 그 토큰으로 API 를 부릅니다.

파드 상세 화면에서 어떤 서비스 어카운트를 쓰는지 확인할 수 있습니다(3.1 장).

서비스 어카운트를 쓰는 이유

대부분의 애플리케이션은 클러스터 API 를 부를 일이 없습니다. 웹 서버는 자기 일만 하면 됩니다.

하지만 이런 경우에는 필요합니다.

상황필요한 권한
다른 파드 목록을 읽어 동작파드 조회
ConfigMap 변경을 감지해 다시 읽기ConfigMap 조회·감시
자기 복제본 수를 조절Deployment 수정
운영 도구 (모니터링, 로그 수집)여러 자원 조회

네임스페이스마다 default 서비스 어카운트가 자동으로 있습니다. 파드에 계정을 지정하지 않으면 이것이 쓰입니다.

default 에 권한을 주지 마십시오. 그 네임스페이스의 모든 파드 가 그 권한을 갖게 됩니다. 권한이 필요한 파드마다 전용 서비스 어카운트를 만드십시오.

롤이란

할 수 있는 일을 모아 둔 것 입니다. "어떤 자원에 어떤 동작을 할 수 있다" 를 나열합니다.

보안 > 역할 에서 봅니다.

롤 목록

범위가 다른 두 종류가 있습니다.

종류적용 범위특징
Role한 네임스페이스 안에서만그 네임스페이스에 만들어집니다
ClusterRole클러스터 전체네임스페이스에 속하지 않습니다

노드나 PV 처럼 네임스페이스에 속하지 않는 자원 은 ClusterRole 로만 권한을 줄 수 있습니다.

롤에 담기는 동작

동작
get하나를 조회
list목록을 조회
watch변경을 실시간으로 받음
create만들기
update통째로 바꾸기
patch일부만 바꾸기
delete지우기
deletecollection여러 개를 한 번에 지우기

Console 화면을 보려면 listwatch 가 함께 필요합니다. get 만 있으면 목록이 비어 보입니다. 목록 화면은 list 로 전체를 읽고 watch 로 변경을 받기 때문입니다.

RBAC 에는 "거부" 가 없습니다. 허용만 있고, 허용되지 않은 것은 자동으로 거부입니다. 그래서 "이것만 빼고 다 허용" 같은 설정은 만들 수 없습니다.

미리 만들어진 롤

클러스터에는 기본 ClusterRole 이 있습니다. 새로 만들기 전에 이것으로 충분한지 보십시오.

권한쓰는 경우
view대부분의 자원을 볼 수 있습니다. Secret 은 제외확인만 하는 사람
edit자원을 만들고 고칠 수 있습니다. 권한 설정은 제외애플리케이션 담당자
admin네임스페이스 안의 모든 것. 권한 설정 포함팀 리더
cluster-admin클러스터 전체의 모든 것운영 담당자만

view 에서 Secret 이 빠진 것은 의도된 것입니다. Secret 에는 비밀번호가 들어 있어 "볼 수만 있는" 권한에 포함하면 안 되기 때문입니다.

롤 바인딩이란

롤을 대상에 연결하는 것 입니다. 보안 > 역할 바인딩 에서 봅니다.

롤 바인딩 목록
종류적용 범위
RoleBinding한 네임스페이스 안
ClusterRoleBinding클러스터 전체

연결 대상은 세 종류입니다.

종류
ServiceAccount파드가 쓰는 계정
User사람 계정
Group사람 계정의 묶음 (7.2 장)

Role 과 ClusterRole 조합

롤과 바인딩의 종류를 조합하면 세 가지 경우가 됩니다.

바인딩결과
RoleRoleBinding그 네임스페이스 안에서만
ClusterRoleRoleBinding그 네임스페이스 안에서만
ClusterRoleClusterRoleBinding클러스터 전체

두 번째가 유용합니다. edit 같은 ClusterRole 을 만들어 두고, 네임스페이스마다 RoleBinding 으로 붙이면 역할은 하나인데 범위는 네임스페이스별 이 됩니다. 같은 권한 묶음을 여러 번 만들지 않아도 됩니다.

Role 을 ClusterRoleBinding 으로 연결하는 조합은 없습니다. Role 은 네임스페이스에 속해 있어 클러스터 전체로 확장할 수 없습니다.

만들기 — YAML

세 자원이 어떻게 이어지는지 한 번에 보는 것이 이해에 빠릅니다. 아래는 my-app 네임스페이스에서 파드를 읽기만 하는 계정 을 만드는 전체 예입니다.

1. 서비스 어카운트

apiVersion: v1
kind: ServiceAccount
metadata:
name: log-reader
namespace: my-app
automountServiceAccountToken: false # API 를 쓰지 않는 파드면 꺼 둡니다

2. 롤

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: my-app
rules:
- apiGroups: [""] # 핵심 그룹은 빈 문자열입니다
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
항목설명
apiGroups파드·Service·ConfigMap 등은 "", Deployment 는 "apps", 롤은 "rbac.authorization.k8s.io"
resources복수형 으로 씁니다. 로그·터미널처럼 딸린 것은 pods/log·pods/exec
verbsget·list·watch·create·update·patch·delete

get 만 주면 목록 화면이 비어 보입니다. 이름을 알고 하나를 볼 때가 get, 목록을 볼 때는 list 가 필요합니다. 화면이 실시간으로 갱신되려면 watch 도 있어야 합니다. 읽기 권한은 셋을 함께 주는 것이 기본 입니다.

3. 롤 바인딩

여기까지 해야 효력이 생깁니다. 롤만 만들고 바인딩하지 않으면 아무 일도 일어나지 않습니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: log-reader-can-read-pods
namespace: my-app
subjects: # 누구에게
- kind: ServiceAccount
name: log-reader
namespace: my-app
roleRef: # 어떤 롤을
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader

사람 계정과 그룹에 주기

subjects 의 종류만 다릅니다. SSO 로 로그인하는 사용자는 이름 앞에 정해진 접두가 붙습니다 (7.2 장).

subjects:
- kind: User
name: "oidc:hong@example.com"
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: "oidc:dev-team"
apiGroup: rbac.authorization.k8s.io

접두와 철자가 정확해야 합니다. 틀려도 오류가 나지 않고 그냥 권한이 없는 상태가 됩니다. 실제 이름은 로그인한 뒤 오류 메시지에 나오는 값을 확인하는 것이 확실합니다.

미리 만들어진 롤을 네임스페이스에 붙이기

권한 묶음을 직접 만들지 않고 기본 제공 롤을 쓰는 편이 간단합니다. ClusterRole 을 RoleBinding 으로 붙이면 그 네임스페이스 안에서만 효력이 생깁니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-team-edit
namespace: my-app
subjects:
- kind: Group
name: "oidc:dev-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole # 클러스터 롤을
name: edit # 네임스페이스 범위로 붙입니다

이 방식이 실무에서 가장 많이 쓰입니다. 팀마다 네임스페이스를 주고 위 바인딩만 하나씩 만들면 됩니다.

파드에 계정 붙이기

spec:
serviceAccountName: log-reader
containers:
- name: app
image: registry.example.com/my-app:1.0

지정하지 않으면 그 네임스페이스의 default 계정이 쓰입니다.

권한이 없다는 오류가 날 때

순서확인할 것
1그 사용자·서비스 어카운트에 걸린 롤 바인딩이 있는가
2바인딩된 롤이 해당 자원과 동작을 허용하는가
3바인딩 범위가 맞는가 (다른 네임스페이스의 바인딩은 효력이 없습니다)
4그룹으로 줬다면 그룹 이름 철자가 맞는가
5목록이 비어 보이면 list·watch 가 있는가

Console 은 권한이 없는 메뉴를 숨깁니다. 메뉴가 보이지 않으면 권한이 없는 것입니다.

오류 메시지에는 대개 "누가 무엇에 어떤 동작을 하려다 거부됐는지" 가 들어 있습니다. 그 내용을 그대로 보고 필요한 동작을 롤에 추가하십시오.

권한 설계 지침

  • 필요한 최소 권한만 줍니다. 조회만 필요하면 get·list·watch 로 충분합니다.
  • ClusterRoleBinding 은 꼭 필요할 때만 씁니다. 클러스터 전체에 영향을 줍니다.
  • 사람에게는 그룹으로 권한을 주면 인원 변동에 대응하기 쉽습니다(7.2 장).
  • Secret 조회 권한은 따로 관리하십시오. view 롤에는 빠져 있는 것이 기본입니다.
  • cluster-admin 은 운영 담당자에게만 줍니다. 이 권한이 있으면 다른 모든 권한 설정을 바꿀 수 있습니다.
  • 파드에는 꼭 필요한 파드에만 서비스 어카운트를 붙이고 권한을 줍니다.