Kubernetes 를 사용하다 보면 서로 분리된 환경에 설치된 여러 클러스터에 번갈아 접속해야 할 경우가 종종 발생한다. 예를 들어 한 쪽은 개발&테스트, 다른 한 쪽은 실제 서비스 클러스터 환경, 이런 식이다. 접속 터미널을 따로 띄워서 간편히 사용하는 경우가 많겠지만, 필요에 따라 하나의 kubectl 클라이언트로 서로 다른 클러스터에 접속할 수 있도록 설정하는 방법을 정리한다(K8s 1.6.x~1.8.x 기준).




클러스터 이름과 관리자 이름 변경


Kubernetes 를 구글 repo를 통해 기본 설치로 진행하면, kubectl을 통한 클러스터 접속용 설정 파일(yaml 형식)은 위의 캡처 이미지와 같은 모양으로 나타나게 된다(root 유저일 경우 KUBECONFIG 환경변수의 값은 '/root/.kube/config' 값을 가진다). 파일을 열어 보면, 클러스터명은 kubernetes, 사용자는 kubernetes-admin' 으로 자동 설정 되고, kubeadm을 통한 설치시에 만들어 진 보안 인증키 값들이 인코딩 되어 사용된다. Minikube 를 로컬 PC에 자체 설치하였어도 전체적인 설정파일의 구조는 동일하다고 볼 수 있다.


이와 같이, 유사한 방식으로 쿠버네티스를 여러 환경에 설치하더라도 해당 클러스터명과 사용자명이 동일하게 되지 않도록 구분을 지어 주어야만 context를 스위칭하면서 kubectl 에서 각각의 클러스터에 접속을 할 수 있게 된다.



캡처이미지에도 표시하였지만, 박스로 표시된 부분에 대해 각 이름의 일관성을 유지하면서 원하는 값으로 바꾸어 저장하도록 한다. 여기서는 클러스터 이름을 k8s-vbox로, 사용자(관리자) 이름을 k8s-vbox-admin 으로 변경한다.


<첫 번 째 클러스터 KUBECONFIG 파일 변경>

[root@kubemaster ~]# kubectl config get-contexts

CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE

*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin


[root@kubemaster ~]# vi $KUBECONFIG 

apiVersion: v1

clusters:

- cluster:

    certificate-authority-data: REDACTED

    server: https://10.255.10.170:6443

  name: k8s-vbox

contexts:

- context:

    cluster: k8s-vbox

    user: k8s-vbox-admin

  name: k8s-vbox-admin@k8s-vbox

current-context: k8s-vbox-admin@k8s-vbox

kind: Config

preferences: {}

users:

- name: help

  user:

    as-user-extra: {}

- name: k8s-vbox-admin

  user:

    client-certificate-data: REDACTED 

    client-key-data: REDACTED


[root@kubemaster ~]# systemctl daemon-reload

[root@kubemaster ~]# systemctl restart kubelet


[root@kubemaster ~]# kubectl config get-contexts

CURRENT   NAME                      CLUSTER    AUTHINFO         NAMESPACE

*         k8s-vbox-admin@k8s-vbox   k8s-vbox   k8s-vbox-admi



이번에는 또 다른 클러스터 이름을 k8s-vmw로, 사용자(관리자) 이름을 k8s-vmw-admin 으로 변경한다.


<두 번 째 클러스터 KUBECONFIG 파일 변경>

[root@kubemaster ~]# kubectl config get-contexts

CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE

*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin


[root@kubemaster ~]# cat $KUBECONFIG 

apiVersion: v1

clusters:

- cluster: 

    certificate-authority-data: REDACTED

    server: https://192.168.60.170:6443

  name: k8s-vmw

contexts:

- context:

    cluster: k8s-vmw

    user: k8s-vmw-admin

  name: k8s-vmw-admin@k8s-vmw

current-context: k8s-vmw-admin@k8s-vmw

kind: Config

preferences: {}

users:

- name: k8s-vmw-admin

  user:

    client-certificate-data: REDACTED

    client-key-data: REDACTED


[root@kubemaster ~]# systemctl daemon-reload 

[root@kubemaster ~]# systemctl restart kubelet

[root@kubemaster ~]# systemctl status kubelet

● kubelet.service - kubelet: The Kubernetes Node Agent

   Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)

  Drop-In: /etc/systemd/system/kubelet.service.d

           └─10-kubeadm.conf

   Active: active (running) since 화 2017-12-19 02:07:47 EST; 9s ago

...


[root@kubemaster ~]# kubectl config get-contexts

CURRENT   NAME                    CLUSTER   AUTHINFO        NAMESPACE

*         k8s-vmw-admin@k8s-vmw   k8s-vmw   k8s-vmw-admin



두 개 클러스터의 config 병합 & kubectl 접속


각 클러스터마다 config 를 수정하여 이름 부분이 잘 변경 되었다면, 양쪽 클러스터에 모두 접속할 수 있는 kubectl 클라이언트 계정의 config 파일에 또 다른 클러스터의 config 내용을 병합하여 아래와 같이 변경해 둔다. 내용을 잘 보면 두 개 클러스터의 config 파일 내용 중 'clusters' 영역과 'contexts' 영역 그리고 'users' 영역의 내용이 각각 병합되어 구성됨을 알 수 있을 것이다. 


[root@kubemaster ~]# cd ,kube

[root@kubemaster .kube]# cp config config.old

[root@kubemaster .kube]# vi config

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: REDACTED
    server: https://10.255.10.170:6443
  name: k8s-vbox
- cluster:
    certificate-authority-data: REDACTED
    server: https://192.168.60.170:6443
  name: k8s-vmw
contexts:
- context:
    cluster: k8s-vbox
    user: k8s-vbox-admin
  name: k8s-vbox-admin@k8s-vbox
- context:
    cluster: k8s-vmw
    user: k8s-vmw-admin
  name: k8s-vmw-admin@k8s-vmw
current-context: k8s-vbox-admin@k8s-vbox
kind: Config
preferences: {}
users:
- name: help
  user:
    as-user-extra: {}
- name: k8s-vbox-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: k8s-vmw-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED



이제 다음과 같이 두 개의 클러스터를 전환하면서 kubectl 명령을 사용할 수 있게 된다.


[root@kubemaster .kube]# kubectl config get-contexts 

CURRENT   NAME                      CLUSTER    AUTHINFO         NAMESPACE

*         k8s-vbox-admin@k8s-vbox   k8s-vbox   k8s-vbox-admin   

          k8s-vmw-admin@k8s-vmw     k8s-vmw    k8s-vmw-admin


[root@kubemaster ~]# kubectl get pods -nkube-system -l tier=control-plane -o wide

NAME                                 READY     STATUS    RESTARTS   AGE       IP              NODE

etcd-kubemaster                      1/1       Running   5          4d        10.255.10.170   kubemaster

kube-apiserver-kubemaster            1/1       Running   6          4d        10.255.10.170   kubemaster

kube-controller-manager-kubemaster   1/1       Running   5          4d        10.255.10.170   kubemaster

kube-scheduler-kubemaster            1/1       Running   5          4d        10.255.10.170   kubemaster

* 현재 접속된 클러스터의 pod 구성을 확인(control-plane 에 해당하는 pod 정보만 조회)


[root@kubemaster ~]# kubectl config use-context k8s-vmw-admin@k8s-vmw

Switched to context "k8s-vmw-admin@k8s-vmw".


[root@kubemaster ~]# kubectl get pods -nkube-system -l tier=control-plane -o wide

NAME                                 READY     STATUS    RESTARTS   AGE       IP               NODE

etcd-kubemaster                      1/1       Running   36         50d       192.168.60.170   kubemaster

kube-apiserver-kubemaster            1/1       Running   17         50d       192.168.60.170   kubemaster

kube-controller-manager-kubemaster   1/1       Running   45         50d       192.168.60.170   kubemaster

kube-scheduler-kubemaster            1/1       Running   43         50d       192.168.60.170   kubemaster

* 접속할 클러스터를 전환하여 pod 구성을 확인




- Barracuda -



블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


RBAC(Role Based Access Control). 우리 말로는 "역할 기반 접근 제어" 라고들 표현하지만 사실, '역할' 보다는 '권한' 이라고 이해하는 것이 더  뜻이 잘 통한다. Kubernetes 1.6 버전부터 kubeadm 을 통한 Bootstrap 방식의 설치가 도입되면서 RBAC의 기본 설정이 이루어지게 되어 있는대, 구글링을 통해 접해 본 예전 문서들에서는 curl 을 통해 쉽게 접근 되던 API 들이, 권한이 없다는 메시지를 뿌리며 실패되는 모습을 자주 보게 되면서, 이 부분에 대해 직접 실험하고 규명해 보고자 하는 생각이 들기 시작했다.






Kubeadm 의 bootstrapping 에 의해 설정된 기본 RBAC 확인


먼저 마스터에서 아래의 명령을 실행해 보자.


# APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")

# TOKEN="$(kubectl get secret $(kubectl get secrets | grep default | cut -f1 -d ' ') -o jsonpath='{$.data.token}' | base64 --decode)"

# curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1

HTTP/1.1 200 OK

Content-Type: application/json

Date: Tue, 05 Dec 2017 06:19:22 GMT

Transfer-Encoding: chunked


{

  "kind": "APIResourceList",

  "groupVersion": "v1",

  "resources": [

    {

...

...

...

      "verbs": [

        "get",

        "patch",

        "update"

      ]

    }

  ]

}

* APISERVER 변수에는 마스터에서 실행되고 있는 apiserver의 URL 값이 저장된다

* TOKEN 변수에는 default 네임스페이스의 default-token-xxxxx 토큰의 secret key 값이 decode 되어 저장된다

* 토큰 키를 header에 실어서 api 목록을 가져오는 curl 호출을 실행해 본다



위의 결과를 보면 API 가 잘 호출되고 모든 것이 순조로운 것처럼 보인다. 그렇다면  연이어서 아래 명령을 실행해 보자.


# curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1/pods

HTTP/1.1 403 Forbidden

Content-Type: application/json

X-Content-Type-Options: nosniff

Date: Tue, 05 Dec 2017 06:28:47 GMT

Content-Length: 292


{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {

    

  },

  "status": "Failure",

  "message": "pods is forbidden: User \"system:serviceaccount:default:default\" cannot list pods at the cluster scope",

  "reason": "Forbidden",

  "details": {

    "kind": "pods"

  },

  "code": 403

}

* Default 네임스페이스의 pod 리스트를 가져오는 API 호출을 실행한다

* Default 네임스페이스의 default 라는 사용자는 자신의 네임스페이스임에도 pod의 리스트를 볼 수 없다는 결과를 보여 준다



뭔가 이상하지 않은가? 첫 번 째 curl 실행과는 달리 pod들의 목록을 가져오는데 403 - 권한 없음 - 이라는 결과를 보여 준다. 그렇다면 특정 네임스페이스의 서비스 목록을 가져 오는 것 또한 불가능하지는 않을까?


# curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/kube-system/services

HTTP/1.1 403 Forbidden

Content-Type: application/json

X-Content-Type-Options: nosniff

Date: Tue, 05 Dec 2017 06:34:55 GMT

Content-Length: 316


{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {

    

  },

  "status": "Failure",

  "message": "services is forbidden: User \"system:serviceaccount:default:default\" cannot list services in the namespace \"kube-system\"",

  "reason": "Forbidden",

  "details": {

    "kind": "services"

  },

  "code": 403

}


맞다! Kube-system 네임스페이스의 서비스 목록을 가져오는 것도 역시 403의 결과를 보여 준다. 즉, RBAC 기본 설정대로라면 kubectl 을 통하지 않고 apiserver 에게 직접 API를 호출해서 클러스터의 상태를 보거나 설정 변경을 통한 관리, 운영 자체가 불가능한 상황이 되는 것이다. 우리는 앞으로 이 문제를 해결하는 방법을 찾아 보아야 한다.



그 전에, 우선 한 가지만 정리해 두고 넘어가자. 위의 명령들을 조합해서 RBAC 권한 설정에 대한 확인을 해 보려면  아래의 bash script 를 실행해 보면 된다.


# vi check-apiserver-access-by-default.sh

#!/bin/bash
# For v1.8.x default policy, this 'curl' results in '403 Forbidden'
APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
# Retrieve 'default' account's TOKEN in 'default' namespace
TOKEN="$(kubectl get secret $(kubectl get secrets | grep default | cut -f1 -d ' ') -o jsonpath='{$.data.token}' | base64 --decode)"
curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/default/services

# chmod a+x check-apiserver-access-by-default.sh



Kubernetes 는 여러 개의 ServiceAccount 를 기본으로 제공하는데, Default 네임스페이스의 default 계정(ServiiceAccount, k8s 방식의 표현은 'default:default') 이 아닌 다른 계정은 어떨까? 아래의 명령을 실행해 보자.


# APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")

# TOKEN="$(kubectl -nkube-system get secret $(kubectl get secrets -nkube-system | grep kube-dns | cut -f1 -d ' ') -o jsonpath='{$.data.token}' | base64 --decode)"

# curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/default/services

HTTP/1.1 200 OK

Content-Type: application/json

Date: Tue, 05 Dec 2017 06:57:21 GMT

Transfer-Encoding: chunked


{

  "kind": "ServiceList",

  "apiVersion": "v1",

...

...

      "status": {

        "loadBalancer": {

          

        }

      }

    }

  ]

}



앞의 시도와는 다르게, 이번에는 kubernetes의 control-plane 인 kube-system 네임스페이스의 kube-dns 계정(kube-system:kube-dns) 의 토큰 키 값을 읽어 와서 API 호출을 시도해 보니 정상적으로 동작한다.


# curl -D - --insecure --header "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/kube-system/services

HTTP/1.1 200 OK

Content-Type: application/json

Date: Tue, 05 Dec 2017 06:58:22 GMT

Transfer-Encoding: chunked


{

  "kind": "ServiceList",

  "apiVersion": "v1",

...

...

      "status": {

        "loadBalancer": {

          

        }

      }

    }

  ]

}


마찬가지로 kube-system 네임스페이스의 서비스 목록을 가져오는 것도 역시 가능하다. 그렇다면, API 호출을 통한 모든 행위(action)를 kube-system:kube-dns[각주:1] 계정으로 할 수 있는 것일까? 답은 "아니오" 이다. 맨 위의 그림이 그에 대한 설명을 보여 주고 있다. 다시 말하면 kube-system:kube-dns 계정(subject; 대상)에게는 전체 클러스터의 모든 서비스와 엔드포인트(cluster-wide, 즉 네임스페이스에 상관 없이) 들에 대해 'list', 'watch' 만 가능하도록 사전 설정 되어 있기 때문이다.



아래의 수행 결과는 현재 k8s 클러스터 내에서 위 그림의 파란 박스에 해당하는 system:kube-dns 라는 ClusterRole/ClusterRoleBinding 에 대한 설정 내용을 조회한 결과이다.


# kubectl describe clusterrole system:kube-dns

Name:         system:kube-dns

Labels:       kubernetes.io/bootstrapping=rbac-defaults

Annotations:  rbac.authorization.kubernetes.io/autoupdate=true

PolicyRule:

  Resources  Non-Resource URLs  Resource Names  Verbs

  ---------  -----------------  --------------  -----

  endpoints  []                 []              [list watch]

  services   []                 []              [list watch]


# kubectl describe clusterrolebinding system:kube-dns

Name:         system:kube-dns

Labels:       kubernetes.io/bootstrapping=rbac-defaults

Annotations:  rbac.authorization.kubernetes.io/autoupdate=true

Role:

  Kind:  ClusterRole

  Name:  system:kube-dns

Subjects:

  Kind            Name      Namespace

  ----            ----      ---------

  ServiceAccount  kube-dns  kube-system



기본 계정(ServiceAccount)에 클러스터 관리자 권한을 부여한다면?


Kubernetes 는 클러스터 전체를 관리할 수 있는 권한을 'cluster-admin' 이라는 'ClusterRole' 형태로 제공하고 있다. 다음의 yaml 파일을 적용해 보자.


#  vi 00-default-admin-access.yaml 

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: cluster-admin-clusterrolebinding-1
subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: cluster-admin-clusterrolebinding-2
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin

# kubectl apply -f 00-default-admin-access.yaml 

clusterrolebinding "cluster-admin-clusterrolebinding-1" created

clusterrolebinding "cluster-admin-clusterrolebinding-2" created

* 모든 네임스페이스에는 default 라는 계정이 반드시 하나 존재하게 되는데, 이들 계정에 cluster-admin 에 부여된 클러스터 관리자 권한을 매핑(ClusterRoleBinding)하여 적용한다



위와 같이 해 놓고, 앞서 확인용으로 만들어 놓은 check-apiserver-access-by-default.sh 를 실행하여 API 실행 권한을 확인해 보자.


# ./check-apiserver-access-by-default.sh 

HTTP/1.1 200 OK

Content-Type: application/json

Date: Tue, 05 Dec 2017 07:35:09 GMT

Transfer-Encoding: chunked


{

  "kind": "ServiceList",

  "apiVersion": "v1",

...

      "status": {

        "loadBalancer": {

          

        }

      }

    }

  ]

}



Default:default 계정으로 이전에는 동작하지 않던 default 네임스페이스의 서비스 목록 조회가 이번에는 정상적으로 동작한다(kube-system:default 계정으로도 마찬가지 결과를 확인할 수 있을 것이다).


그런데, 뭔가 석연치 않다. Kubernetes 의 기본 RBAC 설정을 망가뜨리고 있다는 생각이 들지 않는가? 바꿔 말해서 각 네임스페이스에 기본으로 존재하는 default 계정에 클러스터 전체를 관리할 수 있는 막강한 권한을 부여하는 것 자체가 보안성을 위협하는 심각한 장애 포인트가 될 수도 있다는 생각을 지울 수 없다. 일단 RBAC에 의한 권한 설정과 사용에 대한 감은 잡았으니, 깔끔하게 방금 설정한 내용을 지워 버리도록 하자..


# kubectl delete -f 00-default-admin-access.yaml 

clusterrolebinding "cluster-admin-clusterrolebinding-1" deleted

clusterrolebinding "cluster-admin-clusterrolebinding-2" deleted

* Yaml 파일 내용을 잘 보면, ClusterRoleBinding, 즉 권한 매핑을 지우는 것이지, default 계정들을 삭제하는 것은 아니므로 안심하자



클러스터 관리자 권한을 가지는 별도의 특별한 계정을 생성하고 사용


Kubernetes 클러스터 전체를 관리하는 유일하고 특별한 계정(kube-system:root-sa)를 따로 만들어서, 소수의 관리자 권한을 가진 사용자에게만 공개한다면 시스템 보안에 대한 위협은 훨씬 줄어들 것이다. 다음과 같이 yaml 파일을 작성하고 적용해 보자.


# vi 00-root-sa-admin-access.yaml 

kind: ServiceAccount
apiVersion: v1
metadata:
  name: root-sa
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: root-sa-kube-system-cluster-admin
subjects:
- kind: ServiceAccount
  name: root-sa
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin

# kubectl apply -f 00-root-sa-admin-access.yaml

clusterrolebinding "root-sa-kube-system-cluster-admin" created

* kube-system:root-sa 계정을 생성하고 cluster-admin 이라는 ClusterRole(권한 집합)과 매핑(ClusterRoleBinding)하여 클러스터 관리자 권한을 부여한다



참고로, 위의 yaml 로 정의된 root-sa 계정의 RBAC 설정은 다음 그림과 같이 이해하면 된다.




이제 앞서와 마찬가지로 방금 설정한 권한의 매핑 상태를 확인하는 bash script 를 하나 작성해 두자


# vi check-apiserver-access-by-root.sh

#!/bin/bash
# By modified RBAC policy, this 'curl' results in '200 OK'
APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
# Retrieve 'root' account's TOKEN in 'kube-system' namespace
ROOTTOKEN="$(kubectl get secret -nkube-system $(kubectl get secrets -nkube-system | grep root-sa | cut -f1 -d ' ') -o jsonpath='{$.data.token}' | base64 --decode)"
curl -D - --insecure --header "Authorization: Bearer $ROOTTOKEN" $APISERVER/api/v1/namespaces/default/services

# chmod a+x check-apiserver-access-by-root.sh

* Kube-system:root-sa 계정의 토큰 키값을 사용해서 API 호출을 수행하는 bash script



현재 설정된 root-sa 의 권한을 확인하기 위해 위의 스크립트를 실행해 보자


# ./check-apiserver-access-by-root.sh 

HTTP/1.1 200 OK

Content-Type: application/json

Date: Tue, 05 Dec 2017 08:12:38 GMT

Transfer-Encoding: chunked


{

  "kind": "ServiceList",

  "apiVersion": "v1",

  "metadata": {

    "selfLink": "/api/v1/namespaces/default/services",

...

    }

  ]

}

* root-sa 계정으로 default 네임스페이스의 서비스 목록을 성공적으로 불러 오고 있음을 확인할 수 있다.



특정 대상(subject)에 적용된 권한 매핑(ClusterRoleBinding)과 권한 집합(ClusterRole) 조회


[Bonus]


Kubectl 명령으로 ClusterRole/ClusterRoleBinding 목록을 확인하려면,


# kubectl get clusterrole

NAME                                                                   AGE

admin                                                                  19d

cluster-admin                                                          19d

edit                                                                   19d

...

view                                                                   19d

weave-net                                                              19d


# kubectl get clusterrolebinding

NAME                                            AGE

cluster-admin                                   19d

heapster                                        19d

...

system:node                                     19d

system:node-proxier                             19d

weave-net                                       19d


와 같이 명령을 실행하면 되지만, 역으로 특정 대상(ServiceAccount/User/Group)과 연관된 ClusterRole이나 ClusterRoleBinding의 목록을  확인하고 싶을 경우 다음의 bash script 를 작성해서 사용한다면 요긴하게 쓰일 것이니 참고하여 보도록 하자. 단, 스크립트 내에서 JSON 입력을 파싱하는 기능을 사용하기 위해 jq(JSON processor)를 사용하므로 yum install jq 와 같이 jq 패키지를 설치해 두어야 한다.


# vi check-clusterrole.sh

#!/bin/bash
# $1 is kind (User, Group, ServiceAccount)
# $2 is name ("system:nodes", etc)
# $3 is namespace (optional, only applies to kind=ServiceAccount)
function getRoles() {
    local kind="${1}"
    local name="${2}"
    local namespace="${3:-}"

    kubectl get clusterrolebinding -o json | jq -r "
      .items[]
      | 
      select(
        .subjects[]?
        | 
        select(
            .kind == \"${kind}\" 
            and
            .name == \"${name}\"
            and
            (if .namespace then .namespace else \"\" end) == \"${namespace}\"
        )
      )
      |
      (.metadata.name + \" \" + .roleRef.kind + \"/\" + .roleRef.name)
    "
}

if [ $# -lt 2 ]; then
    echo "Usage: $0 kind name {namespace}"
    exit -1
fi

echo "* Query: "
echo " - kind: $1"
echo " - name: $2"
echo " - namespace: $3"
echo "* Result: "
echo "[ClusterRolebinding] [Clusterrole.kind/Clusterrole.name]"
getRoles $1 $2 $3

# chmod a+x check-clusterrole.sh

* Kubernetes 에서 권한(Role)을 매핑 또는 부여(Binding)하는 대상(subject)는 ServiceAccount/User/Group 중 하나이다 

* ServiceAccount 는 네임스페이스에 종속적이므로 kind=ServiceAccount 일 때는 네임스페이스를 지정해야만 한다



사용법은 다음과 같다. 각각의 실행 결과를 직접 확인해 보면 kubernetes 에서 제공하는 RBAC 메커니즘에 에 대한 이해에 도움이 될 듯하다.


# ./check-clusterrole.sh 

Usage: ./check-clusterrole.sh kind name {namespace}


# ./check-clusterrole.sh ServiceAccount root-sa kube-system

* Query: 

 - kind: ServiceAccount

 - name: root-sa

 - namespace: kube-system

* Result: 

[ClusterRolebinding] [Clusterrole.kind/Clusterrole.name]

root-sa-kube-system-cluster-admin ClusterRole/cluster-admin


# ./check-clusterrole.sh Group system:unauthenticated

* Query: 

 - kind: Group

 - name: system:unauthenticated

 - namespace: 

* Result: 

[ClusterRolebinding] [Clusterrole.kind/Clusterrole.name]

system:basic-user ClusterRole/system:basic-user

system:discovery ClusterRole/system:discovery


# ./check-clusterrole.sh User system:kube-scheduler

* Query: 

 - kind: User

 - name: system:kube-scheduler

 - namespace: 

* Result: 

[ClusterRolebinding] [Clusterrole.kind/Clusterrole.name]

system:kube-scheduler ClusterRole/system:kube-scheduler



- Barracuda -



  1. kube-dns는 k8s 의 클러스터 내부에 존재하는 DNS로, 각 서비스나 엔드포인트들의 IP 주소를 내부 도메인명인 *.cluster.local 과 연결시켜 resolution을 수행한다 [본문으로]
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들