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

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

[CKS] 1-15. Cluster Roles and Role Bindings
Photo by Aldebaran S / Unsplash

개요

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

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

k8s 리소스 분류

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

1. Namespace Scope Resource

  • Pod, Replicas, jobs, deployments, service, PVC, secrets.. 등이 대표적입니다
  • Namespace를 지정하지 않으면 default namespace를 사용합니다.

2. Cluster Scope Resource

  • Nodes, PV, certificatesigningrequests, namespace..가 대표적입니다.
  • Namespace를 지정하지 않고 생성합니다.
  • 반드시 Cluster Scope에 대해서만 만들 수 있는 것은 아닙니다.
    • Cluster Role로 Namesapce Scope Resource를 지정하게 된다면 Namespace 관련없이 허락된 모든 Namespace 리소스에 대해서 접근이 가능합니다.

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

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)

  • 쿠버네티스에서 ABAC 정책을 정의하는 데 사용되는 파일 구성 형식은 무엇인가요?
    • 쿠버네티스의 ABAC(속성 기반 접근 제어) 정책은 한 줄에 하나의 JSON 객체가 들어가는 파일 형식을 사용하여 정의됩니다. 이 형식은 흔히 JSON Lines(.jsonl)라고 불립니다.
    • 파일의 각 줄은 단일 정책을 나타냅니다. API 서버는 --authorization-policy-file=파일_경로 플래그와 함께 시작될 때 이 파일을 읽어 권한을 결정합니다.
{"apiVersion": "abac.authorization.k8s.io/v1beta1", "kind": "Policy", "spec": {"user": "alice", "namespace": "project-a", "resource": "pods", "readonly": true}}
  • ABAC 설정하기
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
  • Service Account Token 없이 생성
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
  • Config 등록
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
  • ABAC 권한 업데이트
    • ABAC을 위한 JSONL 파일을 업데이트하면 재시작이 필요합니다.
    • API 서버를 재시작하려면 /etc/kubernetes/manifests/kube-apiserver.yaml 파일을 수정하면 됩니다. 실제 설정 변경 없이 재시작을 유발하기 위해 아무 값이나 업데이트했다가 나중에 다시 원래대로 되돌리는 방법을 사용할 수 있습니다.