권한을 찾아서: GitHub Team을 이용하여 Kubernetes 계정 인증하기 (3)

유희철
Banksalad Tech
Published in
9 min readSep 10, 2018

바로 이전 포스트에서는 Guard를 이용해서 Authn 시스템을 구축했습니다. 즉 접속하는 유저가 누구이고 어떤 팀에 속해있는지 구별할 수 있게 되었고요. 이번에는 Role-based access control, 즉 RBAC를 이용해서 각각의 유저 혹은 그룹 마다 다른 권한을 부여하는 즉 Authz를 구성해보도록 하겠습니다.

k8s 1.8 버전 부터 RBAC 기능이 GA 로 승격되고 특별히 옵션을 끄지 않는 이상 기본으로 적용되어 있습니다.

RBAC 에 대해서는 공식 문서에 자세히 설명이 되어있으니 참고해 주시고, 여기서는 Github 팀 권한 인증을 위해 필요한 최소한의 개념만을 다루도록 하겠습니다. 일단 RBAC 에 관련된 리소스 중 Role/ClusterRole, RoleBinding/ClusterRoleBinding 에 대해서 알아야 합니다.

Role은 API/리소스 별로 권한을 설정하는 리소스입니다.

# Role의 간단한 예제
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 는 Core API 를 의미합니다.
resources: ["pods"]
verbs: ["get", "watch", "list"]

위의 예제는 pod-reader 라는 이름의 default 네임스페이스에서만 유효한 Role입니다. rules: 를 보시면 apiGroups, resources, verbs 등을 지정하여 특정 리소스에 대한 접근권한을 제어합니다. $ kubectl get role --all-namespaces 라고 입력하면 모든 네임스페이스에 있는 Role을 리스트업 할 수 있고 $ kubectl get role my-role -n my-namespace -o=yaml 을 통해서 각각의 Role 이 어떻게 설정되어있는지 살펴보실 수 있습니다.

ClusterRole과 다른 점은 이 Role이 적용되는 범위가 특정 네임스페이스인지 모든 네임스페이스(cluster-wide) 인지, 그 범위만 다릅니다.

위와 같은 Role을 실제로 적용하기 위해서는 RoleBinding 오브젝트를 만들어 등록해야 합니다.

# jane 이라는 유저에게 pod-reader 라는 역할을 바인딩시키는 RoleBinding read-pods 라는 이름의 오브젝트 입니다.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane # 이름은 대소문자를 구별합니다.
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # Role 또는 ClusterRole을 지정할 수 있습니다.
name: pod-reader # 실제 존재하는 역할과 매치되어야 합니다.
apiGroup: rbac.authorization.k8s.io

이렇게 역할의 정의와 바인딩을 분리함으로써 하나의 역할을 다수의 RoleBinding과 ClusterRoleBinding에 적용할 수 있습니다.

자 그럼 지금까지 습득한 내용을 기반으로 실제 여러분의 Github 팀과 Role을 묶어Binding 보도록 하겠습니다.

먼저 “나”에게는 k8s 내에 모든 걸 할 수 있는 cluster-admin 권한을 할당 해보도록 하겠습니다.

https://github.com/orgs/{my-org}/new-team 에 접속하여 새로운 팀을 만들어줍니다. 여기서는 admin-k8s 라는 이름으로 만들겠습니다.

우리가 적용하고자 하는clusterrole/cluster-admin 은 이미 존재하니 — $ kubectl get clusterrole cluster-admin — 건너뛰고 ClusterRoleBinding을 아래와 같이 작성합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-k8s-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group # Group 이라고 지정함으로써 Github Team을 가르켰습니다.
name: admin-k8s # 대소문자를 구별함으로 주의해주세요

admin-k8s-team-rb.yml 등의 이름으로 파일을 생성하여 $ kubectl create -f admin-k8s-team-rb.yml 와 같은 명령어로 ClusterRoleBinding을 등록해 줍니다.

그리고 ~/.kube/config 파일을 열어서 아래 내용을 users: 에 추가해주시구요

users:
- name: my-github-token
user:
token: tttttt26ooooo275kkkkkk2f27eeeee51cnnnnnn

위의 token 항목 에는 2편에서 발급 받은 Github 토큰 값을 넣으시면 됩니다.

context 항목도 아래와 같이 수정하여 기존 kops 발급된 어드민용 인증 정보 대신 Github credential 을 사용하도록 변경합니다.

- context:
cluster: my.cluster.k8s.local
user: my-github-token

이제 $ kubectl get nodes 라고 입력했을 때 클러스터의 노드 리스트를 볼 수 있다면 드디어 Github Team + Guard + RBAC 를 이용한 인증에 성공했다고 보면 됩니다! 🎉

이러한 인증방식은 Github와 연동 되는 부분이 있기 때문에 처음에는 인증하는데에 몇 분 정도 시간이 필요할 수 있습니다. 이런 경우에는 몇 분 정도 기다렸다가 다시 시도해보세요.

조금 더 확실하게 연동이 잘 되었는지를 테스트 하고 싶으시다면 ~/.kube/config 파일을 잘 백업해두신 후에 기존에 kops가 만들어준 어드민 user 항목을 삭제하시고 kubectl의 기능이 잘 동작하는지 확인해 볼 수 있습니다.

자 이번에는 k8s admin이 아닌 백엔드 팀에게 권한을 부여해보도록 하겠습니다.

여러분이 직접 하실 때는 각 팀에게 꼭 필요한 권한만을 가지고 있는 Role/ClusterRole 을 만들어서 사용하시길 권장합니다. 이번 예제에서는 클러스터 구성 시 생성되는 clusterrole/edit을 사용하도록 하겠습니다.( $ kubectl get clusterrole edit -o=yaml )

그러면 ClusterRole이 준비되었으니 아래와 같이 RoleBinding을 작성합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding # 이번에는 ClusterRolebinding이 아님을 주의하세요
metadata:
name: backend-team
namespace: development # RoleBinding의 경우는 네임스페이스를 지정합니다
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: edit
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group # Group이라고 지정함으로써 Github Team을 가르켰습니다.
name: backend # 대소문자를 구별함으로 주의해주세요

위의 RoleBinding 을 k8s 클러스터에 등록하면 ($ kubectl apply -f my-role.yaml) 이제 Github 의 backend 팀으로 등록된 멤버들은 clusterrole/edit에 부여된 권한을 갖게 되었습니다.

이제 다음으로 해당 팀원들이 k8s 클러스터에 접근 할 수 있도록 알려줘야 합니다.

사실 위에서 이미 ~/.kube/config 파일을 수정한 것에서 몇가지 작업만 더하면 됩니다.

  1. user 항목의 name: admin인 유저를 찾아서 지워주시고요. 특히 client-key-data 를 가지고 있는 유저는 꼭 지워야 합니다.
  2. 본인의 Github 토큰을 공유하고 싶지 않을테니 해당 토큰을 포함한 유저도 지우거나 토큰을 의미 없는 값으로 변경하신 후 저장하면 이제 모든 팀원에게 공유할 수 있는 형태의 템플릿이 되었다고 볼 수 있습니다.
  3. 권한이 필요한 팀원에게 해당 파일과 Github 토큰을 발급 받는 방법(2편 참조)을 공유해주시고, config 파일을 제 위치(~/.kube/config)에 옮겨주세요. 그리고 실제로 k8s 클러스터에 접속 후 기능 이용에 문제가 없는지 확인해주시면 됩니다.

Webhook token auth + Guard 덕분에 자칫 복잡할 수 있는 Auth 문제를 생각보다 간편하게 해결 할 수 있었습니다.

이렇게 함께 총 3편의 글을 통해 직접 Auth 문제를 해결해 보았는데 어떠셨나요? 제 예상으로는 앞으로 1년 내에 AWS 서울 리전에도 EKS가 상륙할 것으로 보이고 그 때가 되면 AWS의 IAM을 통해서 훨씬 더 간편하게 Auth 문제를 해결할 수 있겠지만 지금 당장에도 이런식으로나마 보안과 계정 관리 문제의 두마리 토끼를 잡을 수 있었습니다.

그리고 저 개인적으로는 이번 작업을 진행한 덕분에 실제로 k8s의 Auth 작동방식에 대해서 더 자세히 이해할 수 있었고, 또 레이니스트의 기술 블로그에 처음으로 기고해보는 계기가 되었네요.

그러면 비슷한 고민을 하셨을 분들께 흥미로운 사례가 되었길 바라며 글을 마칩니다. Happy DevOpsing! 👍 🕺

--

--