RBAC 소개
쿠버네티스에서는 ABAC(특성 기반 접근 제어), RBAC(역할 기반 접근 제어), Webhook, Node, AlwaysDeny(항상 거부) 및 AlwaysAllow(항상 허용)의 6가지 모드로 인증이 구현됩니다.
1.6 버전부터 쿠버네티스는 기본적으로 RBAC 접근 제어 정책을 활성화합니다. 1.8 버전부터 RBAC은 안정적인 기능으로 자리 잡았습니다. –authorization-mode=RBAC 옵션을 설정하여 RBAC을 활성화할 수 있습니다.
RBAC API에서 인증은 다음 단계로 진행됩니다:
- 역할 정의: 역할을 정의할 때 해당 역할이 리소스에 대한 접근 제어 규칙을 지정합니다.
- 역할 바인딩: 주체(주로 사용자)와 역할을 바인딩하여 사용자에게 접근 권한을 부여합니다.
역할과 클러스터 역할
RBAC API에서 역할은 권한 집합을 나타내는 규칙을 포함합니다. 여기서는 권한이 부여되는 방식만 있으며 거부되는 설정은 없습니다. 쿠버네티스에는 일반 역할과 클러스터 역할의 두 가지 유형이 있습니다.
Role을 사용하여 특정 네임스페이스 내에서 역할을 정의하거나, ClusterRole을 사용하여 클러스터 전체 범위의 역할을 정의할 수 있습니다. 하나의 역할은 단일 네임스페이스의 리소스에 대한 접근 권한만 부여할 수 있습니다.
클러스터 역할(ClusterRole)은 다음과 같은 리소스에 대한 권한을 부여받을 수 있습니다:
- 클러스터 범위 리소스 (예: Node)
- 비 리소스 엔드포인트 (예: "/healthz")
- 클러스터의 모든 네임스페이스에 있는 리소스 (예: Pod)
역할 바인딩과 클러스터 역할 바인딩
역할 바인딩은 하나 이상의 사용자와 역할을 바인딩하여 사용자에게 권한을 부여하는 데 사용됩니다. 주체는 사용자, 그룹 또는 서비스 계정으로 구분됩니다. 역할 바인딩도 일반 역할 바인딩과 클러스터 역할 바인딩으로 나뉩니다. 역할 바인딩은 동일한 네임스페이스에 있는 역할만 참조할 수 있습니다.
역할 바인딩은 클러스터 역할을 참조하여 접근 권한을 부여할 수도 있습니다. 이 경우 주체가 리소스에 대한 접근이 현재 네임스페이스로 제한됩니다. 이를 통해 관리자는 클러스터 전체의 공통 역할 집합을 정의한 후 여러 네임스페이스에서 재사용할 수 있습니다.
클러스터 역할은 클러스터 수준 및 전체 네임스페이스에서 권한 부여에 사용될 수 있습니다.
리소스
쿠버네티스의 주요 리소스에는 Pods, Nodes, Services, Deployment, Replicasets, Statefulsets, Namespace, Persistents, Secrets 및 ConfigMaps 등이 포함됩니다. 또한 일부 리소스에는 하위 리소스가 존재하며, 예를 들어 Pod에는 log 하위 리소스가 있습니다.
주체
RBAC 인증의 주체는 그룹, 사용자 또는 서비스 계정일 수 있습니다. 사용자는 "alice", "bob@example.com" 등 문자열로 표시되며, 구체적인 형식은 관리자가 인증 모듈에서 구성한 사용자 이름에 따라 다릅니다. system:은 쿠버네티스 시스템 사용을 위해 예약되어 있으므로 사용자 접두사로 사용할 수 없습니다. 그룹도 인증 모듈에서 제공되며 사용자와 유사한 형식을 가집니다.
기본 예제
1. RoleBinding을 사용하여 사용자를 Role에 바인딩하기
명령어 도움말 및 형식 확인
[root@k8s-master01 ~]# kubectl create role -h # role 생성 명령어 도움말 및 간단한 예제 확인
[root@k8s-master01 RBAC]# kubectl create role pod-reader --verb=get,list,watch --resource=pods --dry-run -o yaml # -o 매개변수로 yaml 형식 내보내기
[root@k8s-master01 RBAC]# cat role-demo.yaml # 완성된 yaml 파일
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: default # 네임스페이스 이름
rules:
- apiGroups: # 포함할 API 그룹, 비작성 시 모든 그룹 포함
- ""
resources: # 포함할 리소스
- pods
verbs: # 위 리소스에 허용할 작업
- get
- list
- watch
role 생성
[root@k8s-master01 RBAC]# kubectl apply -f role-demo.yaml
role.rbac.authorization.k8s.io "pod-reader" created
[root@k8s-master01 RBAC]# kubectl get role # role 정보 확인
NAME AGE
pod-reader 8s
[root@k8s-master01 RBAC]# kubectl describe role pod-reader # pod-reader 상세 정보 확인
Name: pod-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pod-reader","namespace":"default"},"rules":[{"apiGroup...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch]
RoleBinding 생성하여 사용자 testuser(이전 장서비스 계정에서 생성된 사용자)를 pod-reader 역할에 바인딩
[root@k8s-master01 ~]# kubectl create rolebinding -h # 명령어 도움말 확인
kubectl create rolebinding testuser-read-pods --role=pod-reader --user=testuser --dry-run -o yaml # testuser-read-pods라는 이름의 rolebinding 생성
[root@k8s-master01 RBAC]# cat rolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: testuser-read-pods
roleRef: # role 참조, 어떤 role을 참조할지 지정
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
subjects: # 작업을 실행하는 주체
- apiGroup: rbac.authorization.k8s.io
kind: User
name: testuser
[root@k8s-master01 RBAC]# kubectl describe rolebinding testuser-read-pods
Name: testuser-read-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"name":"testuser-read-pods","namespace":"default"},"ro...
Role:
Kind: Role
Name: pod-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User testuser
작업 확인
[root@k8s-master01 RBAC]# kubectl config use-context testuser@kubernetes # testuser 사용자로 컨텍스트 전환
Switched to context "testuser@kubernetes".
[root@k8s-master01 RBAC]# kubectl get pods # 현재 네임스페이스의 pod 정보 확인
NAME READY STATUS RESTARTS AGE
myapp-deploy-5cfd895984-262kz 1/1 Running 0 3d
myapp-deploy-5cfd895984-7whdn 1/1 Running 0 3d
myapp-deploy-5cfd895984-lg8sh 1/1 Running 0 3d
myapp-deploy-5cfd895984-m7h5j 1/1 Running 0 3d
myapp-deploy-5cfd895984-zd9cm 1/1 Running 0 3d
[root@k8s-master01 RBAC]# kubectl get pods -n kube-system # 다른 네임스페이스 pod 정보 확인 시 권한 없음 확인
Error from server (Forbidden): pods is forbidden: User "testuser" cannot list pods in the namespace "kube-system"
2. ClusterRoleBinding을 사용하여 사용자를 ClusterRole에 바인딩하기
ClusterRole 생성
[root@k8s-master01 RBAC]# kubectl config use-context kubernetes-admin@kubernetes # 컨텍스트 전환
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master01 RBAC]# kubectl create clusterrole -h
[root@k8s-master01 RBAC]# kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods -o yaml --dry-run
[root@k8s-master01 RBAC]# cat clusterrole-cluster.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-reader # ClusterRole은 클러스터 수준이므로 namespace 정의 불가
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master01 RBAC]# kubectl apply -f clusterrole-cluster.yaml
[root@k8s-master01 RBAC]# useradd admin
[root@k8s-master01 RBAC]# cp -rp ~/.kube/ /home/admin
[root@k8s-master01 RBAC]# chown -R admin:admin /home/admin
[root@k8s-master01 RBAC]# su - admin
[admin@k8s-master01 ~]$ kubectl config use-context testuser@kubernetes
[admin@k8s-master01 ~]$ kubectl config view
ClusterRoleBinding 생성하여 사용자 testuser를 cluster-reader ClusterRole에 바인딩
[root@k8s-master01 RBAC]# kubectl delete rolebinding testuser-read-pods # root 사용자
[admin@k8s-master01 ~]$ kubectl get pods # admin 사용자로 확인
Error from server (Forbidden): pods is forbidden: User "testuser" cannot list pods in the namespace "default"
[root@k8s-master01 RBAC]# kubectl create clusterrolebinding -h
[root@k8s-master01 RBAC]# kubectl create clusterrolebinding testuser-read-all-pods --clusterrole=cluster-reader --user=testuser --dry-run -o yaml # testuser-read-all-pods라는 clusterrolebinding 생성
[root@k8s-master01 RBAC]# cat clusterrolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: testuser-read-all-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: testuser
[root@k8s-master01 RBAC]# kubectl apply -f clusterrolebinding-demo.yaml
[root@k8s-master01 RBAC]# kubectl describe clusterrolebinding testuser-read-all-pods
확인
# admin 사용자 터미널에서
[admin@k8s-master01 ~]$ kubectl get pods # 현재 네임스페이스 pod 정보 확인 가능
NAME READY STATUS RESTARTS AGE
myapp-deploy-5cfd895984-262kz 1/1 Running 0 3d
myapp-deploy-5cfd895984-7whdn 1/1 Running 0 3d
myapp-deploy-5cfd895984-lg8sh 1/1 Running 0 3d
myapp-deploy-5cfd895984-m7h5j 1/1 Running 0 3d
myapp-deploy-5cfd895984-zd9cm 1/1 Running 0 3d
[admin@k8s-master01 ~]$ kubectl get pods -n ingress-nginx # 다른 네임스페이스 pod 정보 확인 가능
NAME READY STATUS RESTARTS AGE
default-http-backend-66c4fbf5b4-m8d6j 1/1 Running 0 24d
nginx-ingress-controller-64bcff8657-6j4tq 1/1 Running 0 24d
[admin@k8s-master01 ~]$ kubectl delete pod myapp-deploy-5cfd895984-262kz # pod 삭제 불가
Error from server (Forbidden): pods "myapp-deploy-5cfd895984-262kz" is forbidden: User "testuser" cannot delete pods in the namespace "default"
3. RoleBinding을 사용하여 ClusterRole 바인딩
RoleBinding(ClusterRole 사용 및 존재) 생성하여 사용자를 ClusterRole에 바인딩
[root@k8s-master01 RBAC]# kubectl delete clusterrolebinding testuser-read-all-pods # 충돌 방지를 위해 이전 clusterrolebinding 삭제
clusterrolebinding.rbac.authorization.k8s.io "testuser-read-all-pods" deleted
[root@k8s-master01 RBAC]# kubectl create rolebinding testuser-read-pods --clusterrole=cluster-reader --user=testuser --dry-run -o yaml
[root@k8s-master01 RBAC]# cat rolebinding-cluster-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: testuser-read-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: testuser
[root@k8s-master01 RBAC]# kubectl apply -f rolebinding-cluster-demo.yaml
rolebinding.rbac.authorization.k8s.io "testuser-read-pods" created
[root@k8s-master01 RBAC]# kubectl describe rolebinding testuser-read-pods
확인:
# admin 사용자 터미널에서
[admin@k8s-master01 ~]$ kubectl get pods # 현재 네임스페이스 pod 정보 확인 가능
NAME READY STATUS RESTARTS AGE
myapp-deploy-5cfd895984-262kz 1/1 Running 0 3d
myapp-deploy-5cfd895984-7whdn 1/1 Running 0 3d
myapp-deploy-5cfd895984-lg8sh 1/1 Running 0 3d
myapp-deploy-5cfd895984-m7h5j 1/1 Running 0 3d
myapp-deploy-5cfd895984-zd9cm 1/1 Running 0 3d
[admin@k8s-master01 ~]$ kubectl get pods -n ingress-nginx # 다른 네임스페이스 정보 확인 불가
Error from server (Forbidden): pods is forbidden: User "testuser" cannot list pods in the namespace "ingress-nginx"
4. RoleBinding을 사용하여 시스템 기본 ClusterRole 바인딩
[root@k8s-master01 RBAC]# kubectl get clusterrole # 현재 클러스터의 clusterrole 확인
[root@k8s-master01 RBAC]# kubectl create rolebinding default-ns-admin --clusterrole=admin --user=testuser --dry-run -o yaml # admin clusterrole에 testuser 사용자 바인딩
[root@k8s-master01 RBAC]# cat rolebinding-cluster-admin-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: default-ns-admin
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: testuser
[root@k8s-master01 RBAC]# kubectl apply -f rolebinding-cluster-admin-demo.yaml
[root@k8s-master01 RBAC]# kubectl describe rolebinding default-ns-admin
확인
# admin 사용자 터미널에서
[admin@k8s-master01 ~]$ kubectl get pods # 현재 네임스페이스 pod 정보 확인 가능
NAME READY STATUS RESTARTS AGE
myapp-deploy-5cfd895984-262kz 1/1 Running 0 3d
myapp-deploy-5cfd895984-7whdn 1/1 Running 0 3d
myapp-deploy-5cfd895984-lg8sh 1/1 Running 0 3d
myapp-deploy-5cfd895984-m7h5j 1/1 Running 0 3d
myapp-deploy-5cfd895984-zd9cm 1/1 Running 0 3d
......
[admin@k8s-master01 ~]$ kubectl delete pod myapp-deploy-5cfd895984-262kz # 현재 네임스페이스 pod 삭제 가능
pod "myapp-deploy-5cfd895984-262kz" deleted
[admin@k8s-master01 ~]$ kubectl get deploy # 네임스페이스의 다른 리소스 확인 가능
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deploy 5 5 5 5 3d
[admin@k8s-master01 ~]$ kubectl delete deployment nginx-deploy # 현재 네임스페이스의 다른 리소스 삭제 가능
deployment.extensions "nginx-deploy" deleted
[admin@k8s-master01 ~]$ kubectl get pods -n kube-system # 다른 네임스페이스에는 권한 없음
Error from server (Forbidden): pods is forbidden: User "testuser" cannot list pods in the namespace "kube-system"
Role, ClusterRole, RoleBinding, ClusterRoleBinding의 시스템 관계
[root@k8s-master01 RBAC]# kubectl get clusterrolebinding # 클러스터의 clusterrolebinding 확인
NAME AGE
cluster-admin 31d
......
[root@k8s-master01 RBAC]# kubectl get clusterrolebinding cluster-admin -o yaml # cluster-admin clusterrolebinding 정보 확인
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: 2018-10-30T02:32:22Z
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "103"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/cluster-admin
uid: 07b1d436-dbec-11e8-8969-5254001b07db
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group # 타입은 그룹
name: system:masters # 이 그룹에는 kubernetes-admin 사용자가 포함되어 있으며, 이는 기본 현재 사용자
[root@k8s-master01 RBAC]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://172.16.150.212:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin # 기본 현재 사용자
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: testuser
name: testuser@kubernetes
current-context: kubernetes-admin@kubernetes # 현재 사용하는 sa
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: testuser
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
[root@k8s-master01 RBAC]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# openssl x509 -in ./apiserver-kubelet-client.crt -text -noout # 인서트 내용 확인
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3187679453637891293 (0x2c3ce992f3e5d4dd)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Oct 30 02:32:03 2018 GMT
Not After : Oct 30 02:32:03 2019 GMT
Subject: O=system:masters, CN=kube-apiserver-kubelet-client # kubernetes-admin 사용자가 system:master 그룹에 속한 이유는 인서트에 정의되어 있음, O는 그룹을 의미
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
.....
RoleBinding 또는 ClusterRoleBinding의 객체가 서비스 계정인 경우, pod(spec.serviceAccountName에 정의)가 이 서비스 계정 이름으로 시작되면 해당 pod의 애플리케이션도 해당 서비스 계정의 권한을 가집니다. 즉, 해당 서비스 계정에 바인딩된 Role 또는 ClusterRole의 권한을 갖게 됩니다. 시스템의 특수 pod는 이러한 설정이 필요할 수 있습니다. 예를 들어, 클러스터 생성 시 사용된 flannel 네트워크 플러그인을 예로 설명합니다.
flannel 구성 확인
[root@k8s-master01 kubernetes]# cat kube-flannel.yml # flannel 구성 파일
---
kind: ClusterRole # ClusterRole 정의
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: flannel
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding # ClusterRoleBinding 정의
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount # ServiceAccount 정의
metadata:
name: flannel
namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
---
......(이하 생략)
flannel 생성 pod 정보 확인
[root@k8s-master01 kubernetes]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
etcd-k8s-master01 1/1 Running 0 32d
kube-apiserver-k8s-master01 1/1 Running 0 32d
kube-controller-manager-k8s-master01 1/1 Running 0 7d
kube-dns-86f4d74b45-72kdh 3/3 Running 0 32d
kube-flannel-ds-amd64-847wt 1/1 Running 0 32d
kube-flannel-ds-amd64-9v9t6 1/1 Running 0 32d
kube-flannel-ds-amd64-k4blq 1/1 Running 0 32d
kube-proxy-8l9tf 1/1 Running 0 32d
kube-proxy-m6pqm 1/1 Running 0 32d
kube-proxy-scj8n 1/1 Running 0 32d
kube-scheduler-k8s-master01 1/1 Running 0 32d
[root@k8s-master01 kubernetes]# kubectl get pod kube-flannel-ds-amd64-847wt -n kube-system -o yaml
......(생략)
serviceAccount: flannel
serviceAccountName: flannel # 현재 pod가 시작될 때 컨테이너 프로세스는 API서버와 통신할 때 serviceAccountName의 계정으로 연결되어 해당 서비스 계정의 권한을 얻음
.....(생략)
다음은 사용자가 다른 Role 및 Binding에 바인딩될 때 가지는 권한 경계를 나타내는 표입니다
| 사용자 | 바인딩 타입 | 역할 타입 | 권한 범위 |
|---|---|---|---|
| RoleBinding | Role | 네임스페이스 | |
| ClusterRoleBinding | ClusterRole | 클러스터 | |
| RoleBinding | ClusterRole | 네임스페이스 |