Kubernetes Authentication
회사에서 개발자 및 운영팀을 위한 격리된 환경을 만드는 것은 매우 유용하다. kubernetes를 활용할 때 개발자가 환경을 편안하게 사용할 수 있도록 해야 하며, 안전한 개발 공간(환경)을 제공하게 되면 해당 기술을 익히는 데 큰 도움이 된다.
kubernetes는 namespace와 RBAC(Role-Based Access Control)를 이용하여 격리된 환경을 제공할 수 있다. namespace가 격리된 공간이라고 한다면, RBAC는 격리된 공간(namespace)에 대한 제한된 접근을 관리하는 역할을 한다.
이 글에서는 namespace를 통해 kubernetes cluster에서 격리된 공간을 만들고 RBAC를 통해 해당 namespace에 대해 유일하게 접근이 가능한 service account를 만들면서 namespace와 RBAC에 대해 이해하고자 한다.
권한 관리
Kubernetes Cluster의 api에 접근하기 위해서는 우선 유효한 사용자 인증(authentication)을 거쳐야 한다. 인증이 됐으면 그 사용자가 접근하려고 하는 api에 권한이 있는지 확인이 된 다음에 api를 사용할 숭 있다. 하나의 클러스터를 여러 명의 사용자가 사용하는 경우에 api나 namespace별로 권한을 구분해서 권한이 있는 곳에만 접근을 가능하게 할 수 있다.
kubernetes에서 권한 관리를 위해 제공되는 방법으로는 두 가지가 있다. 하나는 ABAC (Attribute-based access control) 다른 하나는 RBAC (Role-based access control)이다. 둘 중 어떤 방법을 사용할지는 apiserver를 시작할 때 옵션에 --authorization-mode를 통해 지정할 수 있다.
ABAC은 속성(Attribute) 기반의 권한 관리로서 사용 가능한 속성으로는 일반적으로 user, group, request path, request verb 등 외에도 namespace, resource 등으로 설정할 수 있다. 이 경우에는 권한에 대한 내용을 파일로 관리하기 때문에 권한을 변경하려면 직접 마스터 서버에 들어가서 파일을 변경하고 apiserver를 재시작해주어야 한다.
RBAC은 역할(Role) 기반의 권한 간리로서 대부분의 권한 관리 시스템에서 많이 사용된다. user와 role을 별개로 선언한 다음에 그 두 가지를 binding 하여 사용자에게 권한을 부여해준다. RBAC는 관리하기 위해서 서버에 접근할 필요 없이 kubectl이나 api를 이용하여 관리하는 것이 가능하다.
1. Create Namespace.
1-1. Create Namespace using command
$ kubectl create namespace mynamespace
1-2. Create Namespace using yaml
apiVersion: v1
kind: Namespace
metadata:
name: mynamespace
$ kubectl apply -f <file_name>.yaml
2. Create Service Account with permissions
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mynamespace-user-full-access
namespace: mynamespace
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["batch"]
resources:
- jobs
- cronjobs
verbs: ["*"]
Role
롤(Role)은 특정 api나 리소스에 대한 권한들을 명시해둔 규칙들의 집합으로 role과 ClusterRole 두 가지 종류가 있다. Role은 해당 롤이 속한 namespace에만 적용되고, ClusterRole은 특정 namespace에 대한 권한이 아닌 클러스터 전체에 대한 권한을 관리한다. 또한, 추가로 namespace에 한정되지 않은 자원 및 api들에 대한 권한을 지정할 수 있다. 노드들에 대한 권한 외에도 "/healthz" 같은 엔드포인트에 대한 권한도 관리한다.
metadata : 해당 role이 속한 namespace를 명시한다.
rules
- 해당 롤이 가지는 권한에 대한 규칙들을 배열 형식으로 구체적인 값들을 나열한다.
- apiGroups : 해당 롤이 사용할 api 그룹들을 설정
- resources : 어떤 자원에 접근 가능한지를 명시한다. ( ex : pod, jobs, configmap, service, etc... )
- verb : 동사라는 의미로 어떤 동작이 가능한지를 설정하는 부분 ( ex : get, create, list, update, delete, proxy, etc... )
위의 yaml 파일을 살펴보면 metadata 부분에서 mynamespace-user-full-access라는 이름으로 role을 생성할 것이며 해당 role은 mynamespace라는 namespace에 적용될 것임을 명시하고 있다. 또한 rules를 살펴보면 해당 롤이 [ extensions , apps ] api group을 사용할 것이며 모든 리소스에 관해서 모든 동작을 허용할 것임을 알 수 있다.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mynamespace-cluster
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["*"]
aggregationRule:
clusterRoleSelectors:
- matchLabels:
kubernetes.io/bootstrapping: rbac-defaults
ClusterRole
ClusterRole은 Role과는 다르게 metadata 부분에 namespace가 없다. 이는 ClusterRole은 전체 namespace에 적용되기 때문이다. 그 부분을 제외하고는 모든 부분 Role과 동일하다.
ClusterRole은 aggregationRule을 이용해서 다른 ClusterRole들과 조합해서 사용할 수 있다. 위 yaml 파일을 보면 aggregationRule.clusterRoleSelector 항목이 있고 그 하위 항목으로 matchLabels 항목이 있다. 이때 matchLabels에서 설정한 kubernetes.io/bootstrapping: rbac-defaults에서 레이블에 맞는 다른 ClusterRole에서 필요한 rules를 가져오게 된다.
ClusterRole에서는 리소스에 대한 설정 외에도 URL 형식으로 rule을 설정하는 것이 가능하다. 이때는 rules.nonResourceURLs 항목을 통해 설정해주면 된다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: mynamespace-user
namespace: mynamespace
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mynamespace-user-view
namespace: mynamespace
subjects:
- kind: ServiceAccount
name: mynamespace-user
namespace: mynamespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: mynamespace-user-full-access
RoleBinding
RoleBinding은 Role과 User를 묶어주는 역할을 한다. 어떤 사용자 (ServiceAccount)가 무슨 롤을 사용하는지를 지정해 주는 것이다. 권한이 Role과 ClusterRole로 구분되어 있는 것처럼 RoleBinding 또한 기본적인 Role에 대한 Binding인 RoleBinding과 ClusterRole에 대한 Binding인 ClusterRoleBinding으로 구분되어 있다. 권한과 같은 RoleBinding은 특정 namespace에 적용되고 ClusterRoleBinding은 Cluster 전체에 대해 적용된다.
subjects 필드의 kind 하위 필드는 어떤 유형의 계정과 연결하려는지를 나타내고 name 하위 필드는 kind에서 명시한 계정의 이름을 명시하면 된다.
roleRef 필드는 subjects 필드에서 명시한 사용자에게 어떤 role을 할당할지를 표시한다. roleRef.kind에는 Role 혹은 ClusterRole이 올 수 있다. 이 때 ClusterRole을 설정하더라도 RoleBinding에 설정된 namespace에 한해서만 적용된다. roleRef.name에는 설정하려는 롤의 이름을 넣어준다.
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mynamespace-cluster-view
subjects:
- kind: ServiceAccount
name: mynamespace-user
namespace: mynamespace
apiGroup: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mynamespace-cluster-full-access
ClusterRoleBinding
RoleBinding과 대부분 비슷하지만 Role과 ClusterRole의 차이와 같이 metadata.namespace가 없다는 차이가 있다. 대신 subjects에 namespace가 있다. subjects.namespace는 ServiceAccount가 속해있는 namespace를 명시한다. subject.kind에는 User, Group, ServiceAccount가 올 수 있다.
< 참고 : https://arisu1000.tistory.com/27848 >