[CKS] 1-15. Cluster Roles and Role Bindings

쿠버네티스 클러스터 역할과 바인딩은 클러스터 범위 리소스의 접근 제어를 통해 전체 시스템의 안정적 운영과 보안을 지원합니다.

개요

클러스터 역할과 클러스터 역할 바인딩을 알아보겠습니다.

특정 네임스페이스(또는 아무것도 지정되지 않은 경우 기본 네임스페이스) 내에서 권한을 부여하는 네임스페이스 역할과 달리, 클러스터 역할은 클러스터 범위 리소스에 대한 액세스를 제어하는 데 사용됩니다.

k8s 리소스 분류

쿠버네티스는 구조적으로 2가지 그룹으로 분류할 수 있습니다.

1. Namespace Scope Resource

2. Cluster Scope Resource

다음 명령어를 통해 확인해볼 수 있습니다. 결론적으로 네임스페이스 리소스에는 역할과 역할 바인딩이 사용. 클러스터 전체 리소스에 대한 권한을 부여해야 하는 경우에는 클러스터 역할과 클러스터 역할 바인딩을 사용할 수 있도록 구성해야합니다.

kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false

Cluster Role

Node를 관리하기 위한 Cluster admin을 예시로 들어보겠습니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-administrator
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["list", "get", "create", "delete"]

Cluster Role Binding

역할을 생성하고 binding하는 것은 동일합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-admin-role-binding
subjects:
- kind: User
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-administrator
  apiGroup: rbac.authorization.k8s.io

PV / PVC

PVC의 경우 사용자가 스토리지 자원을 요청하는 명세입니다. 특정 네임스페이스 내에서 생성되고 관리하므로 Namespace scope을 가지지만, PV에 경우 관리자가 프로비저닝한 스토리지의 한 부분으로, 클러스터 전체 리소스입니다.

Hands-on

한 사용자에게 2개의 역할을 한 번에 할당할 수 없습니다.

두번에 YAML 작성을 요구합니다.

# 바인딩 1: user-A에게 pod-reader 권한 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: user-a-pod-reader-binding
subjects:
- kind: User
  name: user-A
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
---
# 바인딩 2: user-A에게 configmap-editor 권한 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: user-a-configmap-editor-binding
subjects:
- kind: User
  name: user-A
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: configmap-editor
  apiGroup: rbac.authorization.k8s.io

Hands-on(ABAC)

{"apiVersion": "abac.authorization.k8s.io/v1beta1", "kind": "Policy", "spec": {"user": "alice", "namespace": "project-a", "resource": "pods", "readonly": true}}
controlplane /etc/kubernetes/abac ➜  crictl logs 58d9851ac1171
W0608 07:05:55.110611       1 registry.go:256] calling componentGlobalsRegistry.AddFlags more than once, the registry will be set by the latest flags
I0608 07:05:55.111188       1 options.go:238] external host was not specified, using 192.168.58.153
I0608 07:05:55.113408       1 server.go:143] Version: v1.32.0
I0608 07:05:55.113436       1 server.go:145] "Golang settings" GOGC="" GOMAXPROCS="" GOTRACEBACK=""
E0608 07:05:55.487303       1 run.go:72] "command failed" err="invalid authorization config: open /etc/kubernetes/abac/abac-policy.jsonl: no such file or directory"

controlplane /etc/kubernetes/abac ➜  ls
abac-policy.jsonl

컨테이너와 호스트(물리 서버)의 파일 시스템이 분리되어 있기 때문에 Volume 마운트가 필요합니다.

spec:
  containers:
  - command:
    - kube-apiserver
        # ...
    - --authorization-mode=Node,RBAC,ABAC  # ABAC 모드가 활성화되어 있는지 확인
    - --authorization-policy-file=/etc/kubernetes/abac/abac-policy.jsonl
    ...
    volumeMounts:
    - name: abac-policy-volume          # 아래 volumes에 정의할 이름과 일치해야 합니다.
      mountPath: /etc/kubernetes/abac  # 컨테이너 내부에서 접근할 경로
      readOnly: true                   # 정책 파일이므로 읽기 전용이 안전합니다.
  ...
  volumes:
  - name: abac-policy-volume      # 위 volumeMounts의 이름과 일치해야 합니다.
    hostPath:
      path: /etc/kubernetes/abac # 호스트(물리 서버)의 실제 파일 경로
      type: DirectoryOrCreate
cat /var/log/containers/kube-apiserver
k create sa john
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: build-robot-secret
  annotations:
    kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
kubectl config set-credentials john --token=$(cat john-secret.txt)
k config set-context john-context --cluster kubernetes --user john --namespace=default

k config use-context john-context