Kubernetes(k8s)의 Role-Based Access Control (RBAC)은 사용자, 그룹 또는 서비스 계정(SA)에 클러스터 내의 리소스에 대한 접근을 제어하는 방법이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
labels:
app: test-deployment
spec:
replicas: 3
selector:
matchLabels:
app: test-deployment
template:
metadata:
labels:
app: test-deployment
spec:
containers:
- name: test-deployment
image: nginx:latest
ports:
- containerPort: 80
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: role-dev
rules:
- apiGroups: ["", "apps"]
resources: ["pods", "deployments"]
verbs: ["get", "list", "edit"]
Role은 특정 네임스페이스에 권한 부여를 정의한다.
🪧네임스페이스(namespace)
쿠버네티스의 리소스(파드, 서비스, 시크릿 등)를 논리적으로 그룹화하는 단위
Role은 이러한 네임스페이스에 사용자나 그룹이 수행할 수 있는 행동(예: 읽기, 쓰기, 삭제)과 그 행동이 적용될 리소스(예: 파드, 서비스)를 지정하게 된다.
예를 들어, 특정 네임스페이스(default
)에서 파드
와 디플로이먼트
를 조회(get, list)
하고 수정(edit)
할 수 있는 권한을 Role로 정의하고 이를 사용자에게 부여할 수 있다.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dev-rolebinding
namespace: default
subjects:
- kind: ServiceAccount
name: dev01
apiGroup: ""
roleRef:
kind: Role
name: role-dev
apiGroup: rbac.authorization.k8s.io
RoleBinding은 특정 사용자, 그룹, 또는 서비스 계정에 Role을 연결시키는 방법이다.
이러한 RoleBinding을 통해, 해당 Role에 정의된 권한을 실제 사용자(user)
, 그룹(group)
, 사용자 계정(sa)
에 부여할 수 있다.
RoleBinding은 네임스페이스 범위 내에서만 작동하며, Role이 정의된 동일한 네임스페이스에 존재해야 한다.
ClusterRole은 클러스터 전체에 걸쳐 권한을 정의한다.
ClusterRole은 Role과 비슷하게 작동하지만, 이는 주로 클러스터 수준의 리소스(전체 노드)에 대한 권한을 정의한다.
즉, 클러스터 내 모든 namespace를 다 사용할 수 있는 권한이다.
ClusterRole은 ClusterRoleBinding을 통해서 사용자나 그룹에 클러스터 전체의 권한을 부여할 수 있다.
⚠️주의!
ClusterRoleBinding
은RoleBinding
보다 더 넓은 권한 부여 방법이므로, 클러스터 수준의 리소스(예: 노드) 뿐만 아니라 모든 네임스페이스의 네임스페이스 수준 리소스(예: 파드, 시크릿)에 대한 권한도 당연하게 부여할 수 있다.
당연히 NO❗
쿠버네티스의 RoleBinding은 ServiceAccount
뿐만 아니라 User
, Group
에 대해서도 설정할 수 있다.
ServiceAccount
에 대한 RoleBinding
User
에 대한 RoleBinding
Group
에 대한 RoleBinding
Group
에 대한 ClusterRoleBinding
특정 그룹에 대해서 클러스터 수준의 권한을 바인딩
namespace
에 상관 없으므로, namespace
를 지정하는 부분이 없다!
RoleBinding은 특정 네임스페이스 내에서 역할(Role)을 부여하는데 사용되며, ClusterRoleBinding은 주로 클러스터 전체에 대해 역할(ClusterRole)을 부여하는데 사용된다.
먼저 api 서비스에 부여되어 있는 인증 모드(authorization-mode)에는 어떤 것들이 있는지 살펴보자.
k describe -n kube-system po kube-apiserver-m-k8s | grep -i authorization-mode -F4
static pod인 api 서비스에는 총 2개의 인증 모드가 부여된 것을 확인할 수 있다.
Node 인증 모드
클러스터 내의 각 노드가 자신의 리소스를 접근/관리할 수 있도록 하는 인증 권한.
RBAC 인증 모드
사용자 및 그룹에 부여된 정해진 Role에 따른 리소스에 대한 접근/관리 권한.
Namespace를 2개 생성하고, 해당 Namespace내에 각각 ServiceAccount를 생성해 보도록 하자.
# dev1 namespace
apiVersion: v1
kind: Namespace
metadata:
name: dev1
---
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: dev1-hoon
namespace: dev1
---
# dev2 namespace
apiVersion: v1
kind: Namespace
metadata:
name: dev2
---
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: dev2-moon
namespace: dev2
k get ns
k get serviceaccounts -n dev1
k get serviceaccounts -n dev2
다음과 같이 파드와 디플로이먼트에 대해서 get
, list
권한을 가진 Role을 생성해 주자.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: dev1
name: role-get-dev1
rules:
- apiGroups: ["*"]
resources: ["pods", "deployments"]
verbs: ["get", "list"]
k get role -n dev1 -o yaml
다음과 같이 Role(role-get-dev1)과 연결되는 RoleBinding을 생성해 주도록 하자.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rolebinding-dev1
namespace: dev1
subjects:
- kind: ServiceAccount
name: dev1-hoon
apiGroup: ""
roleRef:
kind: Role
name: role-get-dev1
apiGroup: rbac.authorization.k8s.io
k get rolebindings.rbac.authorization.k8s.io -n dev1
기존 생성 하였던 Role(role-get-dev1)과 연결된 것을 확인할 수 있다.
이러한 Role을 새로운 context(클러스터) 단위로 묶은 뒤 실제로 Role이 잘 적용되는지 테스트 해보도록 하자.
컨텍스트는 클러스터, 사용자, 그리고 네임스페이스의 조합으로 정의되는 환경 설정이다.
이러한 컨텍스트는 특정 클러스터(EKS, GKE, AKE 등)에 접근하기 위한 "환경 설정"이므로, 이를 클러스터 단위라고 봐도 사실 얼추 맞다.
💡 SA의 크레덴셜(API토큰)을 추출하고 이를 새로운 Context에 할당한다.
#!/usr/bin/env bash
# 변수 설정: 스크립트는 NAMESPACE, SERVICEACCOUNT, SETCRED, SETCTXNAME라는 변수들을 설정합니다.
# 이들은 각각 네임스페이스, 서비스 어카운트 이름, 새로운 크레덴셜(자격 증명) 이름 그리고 새로운 컨텍스트 이름을 정의합니다.
NAMESPACE='dev1'
SERVICEACCOUNT='dev1-hoon'
SETCRED='dev1-set-hoon'
SETCTXNAME='ctx-dev1-hoon'
TOKENNAME=`kubectl -n $NAMESPACE get serviceaccount $SERVICEACCOUNT -o jsonpath={.secrets[0].name}`
# 토큰 이름 추출: kubectl 명령어를 사용하여 지정된 네임스페이스와 서비스 어카운트에 대한 토큰 이름을 가져옵니다.
echo "$SERVICEACCOUNT of $NAMESPACE Token: `kubectl -n $NAMESPACE get secret $TOKENNAME -o jsonpath={.data.token}| base64 --decode`"
# 자격 증명 설정: 새로운 크레덴셜을 생성하고, 이전 단계에서 가져온 토큰을 이 크레덴셜에 할당합니다.
kubectl config set-credentials $SETCRED --token=`kubectl -n $NAMESPACE get secret $TOKENNAME -o jsonpath={.data.token}| base64 --decode`
# 컨텍스트 설정: 마지막으로, 새로운 컨텍스트를 생성하고, 이를 위에서 생성한 크레덴셜과 연결합니다.
# 이 컨텍스트는 kubernetes 클러스터와 연결되어 있으며, 지정된 사용자(여기서는 새 크레덴셜)를 사용합니다.
kubectl config set-context $SETCTXNAME --cluster=kubernetes --user=$SETCRED
🔑크레덴셜이란?
시스템이나 리소스에 접근하기 위해서 사용되는 인증 정보로 사용자를 확인하고, 적절한 권한을 부여하는데 사용한다.
SA는 RBAC 권한과 연결된 크레덴셜(SA는 API 토큰형식의 크레덴셜을 씀)을 가지고 있다.
위는 이러한 크레덴셜(API 토큰)을 Context에 연결하는 과정의 쉘 스크립트 명령어이다.
일반적으로 한 Context는 하나의 사용자 또는 SA의 크레덴셜만을 참조하고, 이러한 SA의 크레덴셜에 따라서 수행할 수 있는 작업 권한이 제한된다.
# contexts 조회
k config get-contexts
# contexts 전환
k config use-context ctx-dev1-hoon
default 네임스페이스에서 pod, service, nodes를 조회해 보려고 하였는데, 모두 Forbidden
즉, 차단되어 있는 것을 확인할 수 있다.
dev1 네임스페이스에 대해서 get, list 권한은 있으므로 조회가 가능한 것을 확인할 수 있다.
물론 배포된 게 없으므로 나오는 리소스는 현재 없다.