JUST WRITE

여기만 사용해! - 특정 Namespace 전용 User 생성 본문

MLOps/Kubernetes

여기만 사용해! - 특정 Namespace 전용 User 생성

천재보단범재 2024. 2. 15. 16:51

특정 Namespace 전용 User 생성

여기만 사용해!

Github Action을 통해서 자동 배포 Workflow을 구성해보려고 합니다.

아래 step들로 workflow를 구성하려 합니다.

  1. 특정 조건일 때 Github Action Workflow 시작
  2. docker image build
  3. Container Repository에 push
  4. 특정 Namespace에 Deployment에 새로운 build 한 image로 교체/재시작

사내에 구축된 Kubernetes Cluster에 배포까지 자동화 Workflow을 구성해보려고 합니다.

구성하기 앞서 특정 Namespace에 접근할 수 있는 ServiceAccount 생성이 필요하였습니다.

보통 Kubernetes Cluster 구축 시 생성한 관리자용 config로 접근을 합니다.

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

관리자용 config로 접근 시 모든 권한과 모든 Namespace에 접근이 가능합니다. 

Github action 설정 시 해당 admin config로 진행해도 상관은 없지만,

Github 역시 Kubernetes Cluster 외부이기 때문에 주의가 필요합니다.

이번 Workflow에 필요한 권한과 특정 Namespace에만 접근 가능한 ServiceAccount를 생성해서,

Kubernetes Cluster 다른 부분에는 영향이 가지 않도록 하는 것이 중요합니다.

이번 포스팅에서는 특정 Namespace에만 접근 가능한 ServiceAccount 생성에 대해서 정리해 보겠습니다.

kubectl config

사용자가 Kubernetes Cluster에 접근하려면 kube-apiserver를 통해서 접근합니다.

kubectl 명령어도 결국 kube-apiserver를 통해서 kuberenetes에 접근하는 것입니다.

kube-apiserver는 기본 Port 6443이고 TLS 인증이 적용되어 있습니다.

config 파일에 TLS 인증 정보가 설정되어 있습니다.

$ cat ~/.kube/config

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0....
    ...
    ...
    server: https://{master node ip}:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
users:
- name: kubernetes-admin
  user:
    client-certificate-data:
    ...
    client-key-data:
    ...

설정이 크게 3가지로 나눠집니다.

첫 번째는 접근할 kubernetes cluster에 대한 설정입니다.

  • cluster.certificate-authority-data -> cluster 인증에 필요한 hash값
  • cluster.server -> kube-apiserver endpoint
  • cluster.name -> cluster 명칭

두 번째는 context 설정으로 접근할 사용자나 Namepsace를 연결하는 설정입니다.

  • context.cluster -> 접근할 cluster
  • context.user -> 접근할 user, 세 번째 파트에 user에 설정에 기반
  • context.name -> context 명칭

context를 여러 개 설정할 수 있으며 아래 명령어로 context를 변경하며 해당 context로 접근 가능합니다.

$ kubectl config set-context ${context명}

세 번째는 Cluster를 사용할 user에 대한 설정입니다.

  • name -> User명
  • user.client-certificate-data -> client 인증에 필요한 hash값
  • user.client-key-data -> client key의 hash값, TLS 기반 hash값

이렇게 config에 TLS 인증에 대한 정보가 담겨 있기 때문에 문제없이 Kubernetes Cluster에 접근 가능합니다.

ServiceAccount를 통한 config 생성

위 설정은 kubeadm으로 kubernetes cluster 구축 시 세팅한 admin config값입니다.

TLS 인증 정보를 기반으로 설정이 되어 있습니다.

이번 포스팅에서는 필요한 Role만 가진 ServiceAccount를 사용하도록 설정해 보겠습니다.

아래 yaml를 통해서 ServiceAccount를 생성합니다.

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: user-test
  name: user-test-account

ServiceAccount를 생성하면 non-expired sercret token이 자동으로 생성됩니다.

kubernetes 1.24 이전 버전에서만 자동으로 생성합니다.

1.24 이후 버전에서는 따로 생성해서 mapping이 필요합니다.

참고로 제가 진행한 Kubernetes Cluster 버전은 1.22.2입니다.

# yaml로 확인
$ kubectl get serviceaccount -n user-test user-test-account -o yaml
apiVersion: v1
kind: ServiceAccount
...
...
...
secrets:
- name: ${secret name}

# jsonpath로 바로 secret name get
$ kubectl get serviceaccount -n user-test user-test-account -o jsonpath='{$.secrets[].name}'

ServiceAccount에 mapping 된 secret의 token을 알아내야 합니다.

ServiceAccount가 생성된 같은 Namespace에 Secret이 있는 것을 확인할 수 있습니다.

$ kubectl get secret -n user-test ${secret명} -o yaml

apiVersion: v1
data:
  ca.crt: ...
  namespace: ...
  token: ...
kind: Secret
metadata:
...
...
...
type: kubernetes.io/service-account.token

핝줄 명령어로 필요한 sercret의 token을 확인할 수 있습니다.

$ kubectl get secret -n user-test ${secret명} -o jsonpath='{$.data.token}' | base64 --decode

 

위 config를 가져와서 TLS 인증 설정대신 ServiceAccount의 token 값을 설정합니다.

$ cp ~/.kube/config kubeconfig-token.yaml
$ vi kubeconfig-token.yaml

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0....
    ...
    ...
    server: https://{master node ip}:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: special-user
  name: special-user@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
users:
- name: special-user
  user:
    token: ${token}

TLS 설정인 client-certificate-data, client-key-data 필드 대신 token 필드를 넣어줍니다.

설정한 config값을 통해 kubectl로 kubernetes cluster에 접근 아래 2가지 방법으로 가능합니다.

# 1. kubeconfig 옵션을 통해 접근
$ kubectl --kubeconfig kubeconfig-token.yaml get pods

# 2. ~/.kube/config로 설정
$ mkdir -p ~/.kube
$ cp kubeconfig-token.yaml ~/.kube/config
$ kubectl get pods

# error 발생
Error from server (Forbidden): pods is forbidden: User "system.serviceaccount:user-test-account" cannot list resource "pods" in API group "" in the namespace "default"

하지만 접근할 수 없다는 메시지를 받게 될 것입니다.

ServiceAccount에 권한설정이 필요하기 때문입니다.

Role, RoleBinding

kube-apiserver 접근 시 사용자 인증도 필요하지만 해당 사용자의 권한 인증도 필요합니다.

Kubernetes Cluster에서는 크게 2가지 방식으로 권한 관리를 합니다.

  • ABAC(Attribute-based access Control)
  • RBAC(Role-based access Control)

ABAC

ABAC(Attribute-based access Control)는 속성 기반 권한 관리입니다.

속성은 아래와 같습니다.

  • user
  • group
  • request path
  • request verb

권한 설정 내용을 파일로 관리하므로 권한을 변경하려면 kube-apiserver를 재시작해야 합니다.

RBAC

RBAC(Role-based access Control)는 역할 기반 권한 관리입니다.

User와 Role을 별개로 관리하고 2가지를 조합해서 사용합니다.

ABAC처럼 Master에 접근할 필요 없이 kubectl이나 APIf를 이용해 관리할 수 있습니다.

Role

Role은 특정 API나 자원 사용 권한들을 명시해둔 규칙의 집합입니다.

Role과 ClusterRole 2가지 있으며, Role은 Role이 속한 Namespace에 적용됩니다.

ClusterRole은 특정 Namespace가 아닌 Kubernetes Cluster 전반에 적용됩니다.

Role 역시 다른 object와 마찬가지로 yaml로 정의 가능합니다.

$ kubectl apply -f role.yaml -n user-test

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: 
  namespace: user-test
  name: user-test-role
rules:
- apiGroups:
  - ""
  - "extensions"
  - "apps"
  - "batch"
  - "autoscaling"
  resources:
  - "pods"
  - "pods/log"
  - "deployments"
  - "replicasets"
  - "services"
  - "daemonsets"
  - "configmaps"
  - "replicationcontrollers"
  - "horizontalpodautoscalers"
  - "cronjobs"
  - "jobs"
  verbs:
  - "get"
  - "list"
  - "watch"
  - "create"
  - "update"
  - "patch"
  - "delete"
  • apiGroups -> Role 사용할 apigroup
  • resources -> 접근할 자원
  • verbs -> 사용할 동작(get, list 등)

apiGroups, resources, verbs에 어떤 것을 넣느냐에 따라 해당 Role이 어디까지 권한이 주어질지 설정됩니다.

RoleBinding

RoleBinding은 Role과 User를 묶는 역할입니다.

User가 어떤 Role를 사용할지 설정합니다.

RoleBinding도 RoleBinding과 ClusterRoleBinding으로 나뉩니다.

$ kubectl apply -f rolebinding.yaml -n user-test

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: user-test
  name: user-test-rolebinding
subjects:
  - kind: ServiceAccount
    name: user-test-account
    namespace: user-test
roleRef:
  kind: Role
  name: user-test-role
  apiGroup: rbac.authorization.k8s.io
  • subjets -> Role를 사용할 User
  • roleRef -> 할당할 Role

이렇게 Role과 RoleBinding으로 설정을 하고 나면 위에서 생성한 ServiceAccount에 권한이 주어집니다.

# 기본 namespace(default) pod 확인 -> Error 발생
$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system.serviceaccount:user-test-account" cannot list resource "pods" in API group "" in the namespace "default"
...
...
...
Error from server (Forbidden): job.batch is forbidden: User "system.serviceaccount:user-test-account" cannot list resource "jobs" in API group "" in the namespace "default"

# 특정 namspace pod 확인
$ kubectl get pods -n user-test
NAME              READY    STATUS     RESTARTS AGE
...
...
...

# context의 기본 namespace 변경
$ kubectl config set-context special-user@kubernetes --namepspace=user-test

# 기본 namespace(user-test) pod 확인
$ kubectl get pods
NAME              READY    STATUS     RESTARTS AGE
...
...
...

이제 정상적으로 특정 Namespace에 접근이 가능한 것을 알 수 있습니다.

정리

이번 포스팅에서는 특정 Namespace에만 접근 가능한 User 설정을 해보았습니다.

Kubernetes Cluster에 접근하려면 TLS 인증이 필요하다는 것을 알 수 있었습니다.

User 인증 뿐만 아니라 권한 인증을 통해 Kubernetes Cluster 권한 관리 이뤄진다는 것을 알 수 있었습니다.

다음 포스팅에서는 이번 포스팅에서 생성한 config를 통해 Github Action Workflow를 구성해보겠습니다.

[참고사이트]

 

728x90
반응형
Comments