brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Jul 28. 2021

쿠버1탄-31. 쿠버네티스 - API 접근 제어


다음은 쿠버네티스 스터디 자료를 참고해  정리한 내용입니다.


<1> 테스트 환경 생성

<2> 인증과 인가 차이

<3> 인증 - kubectl 로  API 서버 사용하기 - X.509 Client 인증으로 해보자.

<4> 인증 방법2 Auth Proxy  로  사용

<5> 인가 - RBAC (Role Base Access Control)

<6> Service Account 와 API서버 인증 - Bearer token (ServiceAccount token)

<7> Role RoleBinding 를 이용하여 devteam 네임스페이스 내의 파드 조회 가능하게 설정!

<8> ClusterRole ClusterRoleBinding 를 이용하여 모든 네임스페이스 내의 권한 부여

<9> default 서비스 어카운트로 kubernetes 서비스를 통해 API 서버 사용

<10> 파드에 특정 서비스 어카운트 지정 후 kubernetes 서비스를 통해 API 서버 사용

<11> 삭제




<1> 테스트 환경 생성


1

AWS에 구축법

cloudformation으로  K8s 클러스터를  도쿄 리전에 만들어 보자.

https://brunch.co.kr/@topasvga/1681


또는

노트북에 로컬 구축법

https://brunch.co.kr/@topasvga/1682


2

여기서는 AWS에 구축하여 사용하는법으로 설명한다.


ec2 로그인

dig +short ns seo31.cndk.k8s  


3

ec2에 role 제공


4

REGION=ap-northeast-1

echo $REGION

aws s3 mb s3://seo-to31 --region $REGION

aws s3 ls

export NAME=seo31.cndk.k8s

export KOPS_STATE_STORE=s3://seo-to31

echo 'export NAME=seo31.cndk.k8s' >>~/.bashrc

echo 'export KOPS_STATE_STORE=s3://seo-to31' >>~/.bash


5

Kops로  로컬도메인으로 클러스터 생성에 20분 소요

kops create cluster --zones="$REGION"a --networking calico  --master-size t3.medium --node-size t3.medium --node-count=2  --ssh-public-key ~/.ssh/id_rsa.pub --dns private $NAME -y


클러스터 생성되었는지 10분마다 확인

kops validate cluster --wait 10m

  

7

API 서버에 터미널 2개  로그인하여 확인

scp -i ~/.ssh/id_rsa ~/.kube/config ubuntu@api.seo31.cndk.k8s:/tmp/config  

ssh -i ~/.ssh/id_rsa ubuntu@api.seo31.cndk.k8s  


모니터링 터미널

watch -d 'kubectl get ns,no,po,svc,deploy,rs,ing,ep -o wide'


8

alias k=kubectl

complete -F __start_kubectl k


k get ns,no,po,svc,deploy,rs,ing,ep


NAME                        STATUS   AGE

namespace/default           Active   2d13h

namespace/kube-node-lease   Active   2d13h

namespace/kube-public       Active   2d13h

namespace/kube-system       Active   2d13h


NAME                                                    STATUS   ROLES                  AGE     VERSION

node/ip-172-20-50-211.ap-northeast-1.compute.internal Ready control-plane,master 2d v1.20.8

node/ip-172-20-62-233.ap-northeast-1.compute.internal   Ready    node          2d13h   v1.20.8

node/ip-172-20-63-189.ap-northeast-1.compute.internal   Ready    node           2d13h   v1.20.8


NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE

service/kubernetes   ClusterIP   100.64.0.1   <none>        443/TCP   2d13h


NAME                   ENDPOINTS           AGE

endpoints/kubernetes   172.20.50.211:443   2d13h



9

Tool 설지

sudo su  -

git clone https://github.com/ahmetb/kubectx /opt/kubectx

ln -s /opt/kubectx/kubens /usr/local/bin/kubens

ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx

exit


10

# 네임스페이스 확인

kubens

default

kube-node-lease

kube-public

kube-system



11

# 네임스페이스 변경


cd /home/ubuntu/.kube/

root@ip-172-20-50-211:/home/ubuntu/.kube# chmod 755 config


kubens

default

kube-node-lease

kube-public

kube-system



12

kubectl get pod

NAME                                                                       READY   STATUS    RESTARTS   AGE

calico-kube-controllers-cc8b58cdf-6hhjc                                    1/1     Running   0          2d13h

calico-node-5n5r8                                                          1/1     Running   0          2d13h

calico-node-fgnx7                                                          1/1     Running   0          2d13h

calico-node-l24fw                                                          1/1     Running   0          2d13h

coredns-5489b75945-744w6                                                   1/1     Running   0          2d13h

coredns-5489b75945-qlp76                                                   1/1     Running   0          2d13h

       



13

유틸 설치 - 아마존 리눅스 기반 OS 용


# 디폴트 네임스페이스로 변경법 ?   kubens 다음 마이너스 - 

kubens -

Context "service-account-context" modified.

Active namespace is "default".


14

# 사용가능한 컨텍스트들 확인과 변경?


kubectx

service-account-context


# 컨텍스트 변경

kubectx <변경할 컨텍스트 명>




<2> 인증과 인가 차이


1

인증 ?

로그인, 인증서 등으로 로그인 하는것

X509 인증 등   = x 파이브 오 나인

kubectl 이 kube config 의 기본 설정파일을 참고해서 사용한다.



2

인가 ?

RBAC (role기반 권한 처리) 등으로 차단 된것 등을 허용하는것

Role Base Access Control

Role과 ClusterRole이 있으며 관리 범위가 틀리다.


Role은?

네임 스페이스 내에서만 동작한다.

Pod ,서비스 Svc 는 네임스페이스 내 소속된다. 권한 관리는 Role로 한다.

Role은 APIGroup, resource, verbs 3개로 구성된다.

Role을 ServiceAccount에 매핑한다. (Role 을 계정에 할당 하는것이다. Role 바인딩)


ClusterRole은 ?

네임스페이스 안에 속하지 않는것은 ClusterRole로 관리한다.

Node, PV , Namespace는 ClusterRole로 관리하다.

여러개 네임스페이스 등 인가도 가능하다.

서비스 아카운트에 클러스터 롤바인딩하는 것이다.



<3> 인증 - kubectl 로  API 서버 사용하기 - X.509 Client 인증으로 해보자.


다음은  KOPS로 구현한 AWS  환경에서 테스트 합니다.


1

kubectl로  API서버 사용 과정 확인


kubectl get node

NAME                                               STATUS   ROLES                  AGE     VERSION

ip-172-20-50-211.ap-northeast-1.compute.internal   Ready    control-plane,master   5m29s .20.8

ip-172-20-62-233.ap-northeast-1.compute.internal   Ready    node                   3m12s   v1.20.8

ip-172-20-63-189.ap-northeast-1.compute.internal   Ready    node                   3m58s   v1.20.8


2

X.509 Client 인증으로 해보자 ?


상세 디버그 정보 확인  -v7 , v9 

kubectl get node -v7

kubectl get node -v9


// 인증 정보가 있는곳.

/root/.kube/config


기본으로 /.kube/config 의 일을 로드 한다.

인증과 인가에 대한 정보가 있다.


AWS API호출이 https   443이다.

GET https://127.0.0.1/api/v1/nodes?limit=500

// API 서버 호출주소


I0725 13:27:22.334825   10473 loader.go:379] Config loaded from file:  /home/ubuntu/.kube/config

I0725 13:27:22.346220   10473 round_trippers.go:422] GET https://127.0.0.1/api/v1/nodes?limit=500

I0725 13:27:22.346244   10473 round_trippers.go:429] Request Headers:

:

NAME                                               STATUS   ROLES                  AGE     VERSION

ip-172-20-50-211.ap-northeast-1.compute.internal  Ready   control-plane,master 5m v1.20.8

ip-172-20-62-233.ap-northeast-1.compute.internal   Ready    node                   3m31s   v1.20.8

ip-172-20-63-189.ap-northeast-1.compute.internal   Ready    node                   4m17s   v1.20.8



3

인증서 정보(파일) 없이 api 서버 접속 테스트 해보자 ?

모두 안된다.

권한이 없으므로 


AWS는 포트 없이 도메인 주소가  나온다.

APIADDR=<API접속주소:포트>

APIADDR=127.0.0.1:443


curl -k https://$APIADDR/api/v1/nodes

curl -k https://$APIADDR/apis

curl -k https://$APIADDR/version

curl: (7) Failed to connect to 127.0.0.1 port 443: Connection refused


APIADDR=127.0.0.1:443


curl -k https://$APIADDR/api/v1/nodes


{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {


  },

  "status": "Failure",

  "message": "Unauthorized",

  "reason": "Unauthorized",

  "code": 401

}ubuntu@ip-172-20-50-211:~$



4

# kubeconfig 인증서 정보(파일)  3가지 확인 ?


CA crt(발급 기관 인증서, certificate-authority-data) 

Client crt(클라이언트 인증서, client-certificate-data) 

Client key(클라이언트 개인키, client-key-data)


KUBECONFIG=<kubeconfig파일위치>

KUBECONFIG=/home/ubuntu/.kube/config

cat $KUBECONFIG


3가지 내용이 나온다.

clusters:

contexts:

users:


contexts: = clusters: 와 users: 의 조합이다.



clusters:

- cluster:

    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lNRnF4YzRlVnAze

    server: https://127.0.0.1

  name: local


contexts:

- context:

    cluster: local

    user: kubecfg

  name: service-account-context

current-context: service-account-context

kind: Config


users:

- name: kubecfg

  user:

  client-certificate-data:

   client-key-data: 

// users: 에는 client-certificate-data: (클라이언트 인증서,Cleint crt) 와 client-key-data: (클라이언트 개인키 Client key , CA Key)가 있다.


6

클라이언트 인증서 =  client-certificate-data:

클라이언트 개인키 =    client-key-data: 


클라이언트 인증서 상세 정보 확인

grep 'client-certificate-data' $KUBECONFIG | head -n 1 | awk '{print $2}' | base64 -d

grep 'client-certificate-data' $KUBECONFIG | head -n 1 | awk '{print $2}' | base64 -d > client.crt

openssl x509 -in client.crt -noout -text


클라이언트 인증서를 파일로 만들어 보자~

grep 'client-certificate-data' $KUBECONFIG | head -n 1 | awk '{print $2}' | base64 -d > client.crt

-----BEGIN CERTIFICATE-----

MIIDITCCAgmgAwIBAgIRAI/QI18pn3wlPuM4tdUjCVwwDQYJKoZIhvcNAQELBQAw

FTETMBEGA1UEAxMKa3ViZXJuZXRlczAeFw0yMTEwMDcxMjM2MDJaFw0yMzAxMjAy


상세 정보 확인

openssl x509 -in client.crt -noout -text

// Subject: O = system:masters, CN = kubecfg   // 이미 admin 권한을 가지고 있다!!


$ openssl x509 -in client.crt -noout -text

Certificate:

    Data:

        Version: 3 (0x2)

        Serial Number:

            8f:d0:23:5f:29

        Signature Algorithm: sha256WithRSAEncryption

        Issuer: CN = kubernetes

        Validity

            Not Before: Oct  7 12:36:02 2021 GMT

            Not After : Jan 20 21:36:02 2023 GMT

        Subject: O = system:masters, CN = kubecfg   // 이미 admin 권한을 가지고 있다!!

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            :

         54:17:0e:68:3f:cf:e6:94:71:5d:66:1d:0b:db:2f:8c:21:de:

         a9:77:64:ad


8

사용자에 바인딩된 클러스터롤 확인 : Resources(오브젝트) , Verbs(동작) ?


kubectl describe clusterrolebindings cluster-admin

Name:         cluster-admin

Labels:       kubernetes.io/bootstrapping=rbac-defaults

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

Role:

  Kind:  ClusterRole

  Name:  cluster-admin

Subjects:

  Kind   Name            Namespace

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

  Group  system:masters


//  system:masters은 빌트인  클러스터 admin role이다.


9

cluster-admin 클러스터롤 확인 ?


kubectl describe clusterroles cluster-admin

Name:         cluster-admin

Labels:       kubernetes.io/bootstrapping=rbac-defaults

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

PolicyRule:

  Resources  Non-Resource URLs  Resource Names  Verbs

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

  *.*        []                 []              [*]

             [*]                []              [*]

// 모든 권한을 가지고 있다.


10

tree 설치?

sudo apt  install tree


11

K8S 기본 인증서 파일 확인 ?


tree /etc/kubernetes/   


여러가지 인증서와 키가 있다~~           

/etc/kubernetes/

├── cloud.config

├── kops-controller

│   ├── ca-key.pem

│   ├── ca.pem

│   ├── kops-controller.crt

│   └── kops-controller.key

├── kube-apiserver-healthcheck

│   └── secrets

│       ├── ca.crt

│       ├── client.crt

│       └── client.key



11

직접 인증서 지정하여 API 사용 ?


클라이언트 인증서,키 파일 추출 하자

해당 파일을 OS인증서 주입 후 웹 브라우저로 API서버 사용 가능!

grep 'client-certificate-data' $KUBECONFIG | head -n 1 | awk '{print $2}' | base64 -d > client.crt

grep 'client-key-data' $KUBECONFIG | head -n 1 | awk '{print $2}' | base64 -d > client.key


인증서와 개인 키를 파일로 만들었다


13

API 서버 사용 테스트 ?

APIADDR=127.0.0.1:443

curl -k --key ./client.key --cert ./client.crt https://$APIADDR/api/v1/nodes

curl -k --key ./client.key --cert ./client.crt https://$APIADDR/apis

curl -k --key ./client.key --cert ./client.crt https://$APIADDR/version

curl -k --key ./client.key --cert ./client.crt https://$APIADDR/

// 잘 된다 ~~


14

인증서 1년 만료기간이 있다.

만료 되기전에 인증서 갱신 해야 한다.

인증서 관리가 중요하다.

kubeadm 툴 설치후 확인

kubeadm certs check-expiration


15

클러스터 인증 관련 설정 정보 확인 ?

kubeadm K8S 환경만 가능

kubectl -n kube-system get cm kubeadm-config -o yaml


16

이제까지 htts로 인증서 값을 가지고 조회하는것을 하였다!



<4> 인증 방법2 - Auth Proxy  로  사용


인증서 정보 없이  Proxy 접속해 kubectl 을 사용해  API Server를 사용해보자

보안에 취약함.

간단하게 API 서버를 사용하고자 할때 사용한다.


1

master node ip 확인?

kubectl get nodes -owide


kubectl get node

NAME                                               STATUS   ROLES                  AGE   VERSION

ip-172-20-50-211.ap-northeast-1.compute.internal   Ready    control-plane,master     v1.20.8

ip-172-20-62-233.ap-northeast-1.compute.internal   Ready    node                   22m   v1.20.8

ip-172-20-63-189.ap-northeast-1.compute.internal   Ready    node                   23m   v1.20.8


dig +short ip-172-20-50-211.ap-northeast-1.compute.internal

172.20.50.211


3

Auth Proxy 실행

AuthPort=<Auth Proxy 사용할 포트 번호>

MasterIP=<마스터 노드 IP>


AuthPort=8000

MasterIP=172.20.32.214


4

(방법1) 터미널이 끊어져도 실행 가능하게 데몬 형태로 실행하기

nohup kubectl proxy --port=$AuthPort --address=$MasterIP --accept-hosts='^*$' >/dev/null 2>&1 &

# 프로세스 멈추기 : ss -tnlp ; kill -9 <pid>


5

(방법2) 터미널1개 띄워놓고 포그라운드에서 실행하기

kubectl proxy --port=$AuthPort --address=$MasterIP --accept-hosts='^*$'

# 프로세스 멈추기 : CTRL+C


6

# API 서버 사용 테스트

curl http://$MasterIP:$AuthPort/api/v1/nodes

curl http://$MasterIP:$AuthPort/apis

curl http://$MasterIP:$AuthPort/


or

자신의 PC 웹브라우저에서 접속 >> AWS EC2(Master Node)일 경우 'Inbound Security Group' 에 '0.0.0.0/0 TCP 8000' 포트 허용 설정 추가 필요




<5> 인가 - RBAC (Role Base Access Control)


인증후 권한을 부여하는것이 인가이다.



1

목적

Service Account 정보 확인하기


2

네임스페이스 생성 한다. 

기본적으로 자동으로 생기는 서비스 어카운트(SA)가 생성됨

서비스 어카운트가 가지는 디폴트 권한이 생긴다.


3

서비스어카운트 sa 확인 


kubectl get sa               

or

kubectl get serviceaccounts


NAME      SECRETS   AGE

default   1         2d13h


2

kubectl describe sa default

Name:                default

Namespace:           default

Labels:              <none>

Annotations:         <none>

Image pull secrets:  <none>

Mountable secrets:   default-token-zkk9j

Tokens:              default-token-zkk9j

Events:              <none>


3

kubectl get secrets 

NAME                  TYPE                                  DATA   AGE

default-token-zkk9j   kubernetes.io/service-account-token   3      2d13h


4

kubectl describe secrets

NAME                  TYPE                                  DATA   AGE

default-token-zkk9j   kubernetes.io/service-account-token   3      2d13h

ubuntu@ip-172-20-50-211:~$ kubectl describe secrets

Name:         default-token-zkk9j

Namespace:    default

Labels:       <none>

Annotations:  kubernetes.io/service-account.name: default

              kubernetes.io/service-account.uid: 7e8ba908-bbcd-4eb5-9adc-1a9706467c03

Type:  kubernetes.io/service-account-token

Data

====

ca.crt:     1082 bytes

namespace:  7 bytes

token:      eyJhbGciOiJSUzI1NiIzVycGJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZ

// 토

5

kubectl describe secrets  default-token-zkk9j


6

# 네임스페이스(NS) 신규 생성과  정보 확인


툴 설치

git clone https://github.com/ahmetb/kubectx /opt/kubectx

ln -s /opt/kubectx/kubens /usr/local/bin/kubens

ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx


7

kubens

default

devteam

kube-node-lease

kube-public

kube-system


8

chmod 755 config 해야 한다.


9

kubectl create ns devteam


kubens devteam

Context "service-account-context" modified.

Active namespace is "devteam".


kubectl describe sa

Name:                default

Namespace:           devteam

Labels:              <none>

Annotations:         <none>

Image pull secrets:  <none>

Mountable secrets:   default-token-gtl6g

Tokens:              default-token-gtl6g

Events:              <none>


kubectl describe secrets

Name:         default-token-gtl6g

Namespace:    devteam

Labels:       <none>

Annotations:  kubernetes.io/service-account.name: default

              kubernetes.io/service-account.uid: b978c213-cded-45a4-9674-b31e2a9b113e

Type:  kubernetes.io/service-account-token

Data

====

ca.crt:     1082 bytes

namespace:  7 bytes

token:      eyJhbGciOiJSUzI1NiIsImtpZCI6Ind



7

watch -d 'kubectl get ns,no,po,svc,deploy,rs,ing,ep -o wide'

NAME                        STATUS   AGE

namespace/default           Active   2d14h

namespace/devteam           Active   56m

namespace/kube-node-lease   Active   2d14h

namespace/kube-public       Active   2d14h

namespace/kube-system       Active   2d14h


NAME                                                    STATUS   ROLES                  AGE     VERSION   INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME

node/ip-172-20-50-211.ap-northeast-1.compute.internal   Ready    control-plane,master   2d14h   v1.20.8   172.20.50.211   18.179.205.221   Ubuntu 20.04.2 LTS   5.4.0-1047-aws   containerd://1.4.4


ssh -i ~/.ssh/id_rsa ubuntu@api.seo31.cndk.k8s

alias k=kubectl

complete -F __start_kubectl k

k get ns,no,po,svc,deploy,rs,ing,ep


8

devteam NS에 파드 생성

cat <<EOF | kubectl create -f -

apiVersion: v1

kind: Pod

metadata:

  name: pod-1

  labels:

    app: pod

spec:

  containers:

  - name: netshoot-pod

    image: nicolaka/netshoot

    command: ["tail"]

    args: ["-f", "/dev/null"]

  terminationGracePeriodSeconds: 0

EOF


9

k get pods




<6> Service Account 와 API서버 인증 - Bearer token (ServiceAccount token)


1

NS 생성 시 자동 생성되는 SA(서비스 어카운트)의 토큰(token) 정보 추출

kubens devteam

//kube  ns는 네임스페이스를 변경하는 유틸


kubectl get secrets $(kubectl get sa -o jsonpath="{.items[0].secrets[0].name}") -o jsonpath="{.data.token}" | base64 -d

출력값이 나옴


// 출력값을 token 이라는 변수에 입력

TOKEN=`kubectl get secrets $(kubectl get sa -o jsonpath="{.items[0].secrets[0].name}") -o jsonpath="{.data.token}" | base64 -d`


echo $TOKEN


2

kubectl get node -v7

I0728 04:08:34.190463 2597686 loader.go:379] Config loaded from file:  /home/ubuntu/.kube/config

I0728 04:08:34.198210 2597686 round_trippers.go:422] GET https://127.0.0.1/api/v1/nodes?limit=500

I0728 04:08:34.198231 2597686 round_trippers.go:429] Request Headers:

I0728 04:08:34.198241 2597686 round_trippers.go:433]     Accept: 


3

# Bearer token (ServiceAccount token) 인증을 통한 API서버 접속

APIADDR=<API접속주소:포트>

APIADDR=127.0.0.1:443


curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/

{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {


  },

  "status": "Failure",

  "message": "forbidden: User \"system:serviceaccount:devteam:default\" cannot get path \"/\"",

  "reason": "Forbidden",

  "details": {


  },

  "code": 403


잘됨 3가지

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/apis

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/version

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1


안됨

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/pods/


3

 NS 생성 시 자동 생성되는 default SA는 일부 권한이 바인딩되어 있어서 기본 pod 정보 확인은 실패!

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/pods/


{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {


  },

  "status": "Failure",

  "message": "pods is forbidden: User \"system:serviceaccount:devteam:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"devteam\"",

  "reason": "Forbidden",

  "details": {

    "kind": "pods"

  },

  "code": 403





<7> Role RoleBinding 를 이용하여 devteam 네임스페이스 내의 파드 조회 가능하게 설정!


1

Role 생성하고 RoleBinding하자.


Role 형식?

네임 스페이스가 존재한다.

rules가 있다.


apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  namespace: default

  name: service-reader

rules:

- apiGroups: [""]                 # 1. 대상이 될 오브젝트의 API 그룹

  resources: ["services"]         # 2. 대상이 될 오브젝트의 이름. 현재 디폴트 값

  verbs: ["get", "list"]          # 3. 어떠한 동작을 허용할 것인지 명시



2

# API Resource 정보 확인

kubectl api-resources | head -1 ; kubectl api-resources | grep rbac

NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND

clusterrolebindings     rbac.authorization.k8s.io/v1           false        ClusterRoleBinding

clusterroles                   rbac.authorization.k8s.io/v1           false        ClusterRole

rolebindings                 rbac.authorization.k8s.io/v1           true         RoleBinding

roles                               rbac.authorization.k8s.io/v1           true         Role


// clusterrolebindings , clusterroles 은 네임스페이스 밖에 존재.

//rolebindings, roles은 네임스페이스 안에 존재.



3

kubectl api-resources -owide

각각의 object에서 할수 있는 부분이 나온다.

create , delete 등이 사용 할수 있는 옵션을 보여준다.



4

role을 생성해  pod 조회 권한을 부여해보자 ?


# devteam NS 에 Role 생성

kubens devteam

Context "service-account-context" modified.

Active namespace is "devteam".


5

role 만들자.

종류 role

role 은 namespace가 있다. namespace안에서 존재하니까

클러스터 role은 네임스페이스가 없다. namespace 밖에 있으니까

rules = 권한이 있다.


cat <<EOF | kubectl create -f -

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  name: dev-role1

  namespace: devteam

rules:

- apiGroups: [""]

  resources: ["pods"]

  verbs: ["get", "list"]

EOF


// pods 가 core api 그룹으로 ""  안쓴다.



4

# Role 확인(NS 내 적용 동작)

kubectl get roles

NAME        CREATED AT

dev-role1   2021-07-28T04:14:42Z



5

kubectl describe roles dev-role1

Name:         dev-role1

Labels:       <none>

Annotations:  <none>

PolicyRule:

  Resources  Non-Resource URLs  Resource Names  Verbs

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

  pods       []                 []              [get list]

// pod에 대해 get과 list를 할수 있다.


6

# RoleBinding 생성 ?

default 서비스 어카운트와 Role 바인딩 한다.

계정과 role 을 연결


종류 RoleBinding

namespace 있다.


cat <<EOF | kubectl create -f -

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

  name: dev-rolebind1

  namespace: devteam

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: Role

  name: dev-role1

subjects:

- kind: ServiceAccount

  name: default

  namespace: devteam

EOF


// role과 서비스 어카운트를 바인딩 한다.



7

 확인

kubectl get rolebindings

NAME            ROLE             AGE

dev-rolebind1   Role/dev-role1   37s



8

kubectl describe rolebindings dev-rolebind1


Name:         dev-rolebind1

Labels:       <none>

Annotations:  <none>

Role:

  Kind:  Role

  Name:  dev-role1

Subjects:

  Kind            Name     Namespace

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

  ServiceAccount  default  devteam

// role과 서비스 어카운트가 연결 되어 있다.


9

#  확인을 위해서 서비스 생성 ?


kubens devteam

Context "service-account-context" modified.

Active namespace is "devteam".



10

cat <<EOF | kubectl create -f -

apiVersion: v1

kind: Service

metadata:

  name: svc-1

spec:

  selector:

    app: pod

  ports:

  - port: 8080

    targetPort: 80

EOF



11

# 확인

kubectl get svc

NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

svc-1   ClusterIP   100.67.127.140   <none>        8080/TCP   17s


12

kubectl get ep

NAME    ENDPOINTS        AGE

svc-1   100.98.83.1:80   45s


13

kubectl get all,ep

NAME        READY   STATUS    RESTARTS   AGE

pod/pod-1   1/1     Running   0          42m


NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

service/svc-1   ClusterIP   100.67.127.140   <none>        8080/TCP   56s


NAME              ENDPOINTS        AGE

endpoints/svc-1   100.98.83.1:80   56s


14

# Bearer token (ServiceAccount token) 인증을 통한 API서버 접속 - Role Rolebinding 설정된 상태!

APIADDR=<API접속주소:포트>

APIADDR=127.0.0.1:443


# 아래 조회 중 되는것 안되는것 이 있다! 왜그럴까?

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/pods/

잘 됨!



서비스 조회는 안됨.

권한이 없어서.

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/services/

{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {


  },

  "status": "Failure",

  "message": "services is forbidden: User \"system:serviceaccount:devteam:default\" cannot list resource \"services\" in API group \"\" in the namespace \"devteam\"",

  "reason": "Forbidden",

  "details": {

    "kind": "services"

  },

  "code": 403



15

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/nodes

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/





<8> ClusterRole ClusterRoleBinding 를 이용하여 모든 네임스페이스 내의 권한 부여


네임스페이스를 별도로 만든다.

별도의 서비스 어카운트를 만든다.

다른 네임스페이스에 있는 dev 네임스페이스를 조회 한다.  dev에 있는것 pod,svc 조회해 보자.

클러스터 Role은 모든 네임스페이스 안에 있는 오브젝트를 사용할수 있는 권한 제공 가능. 

클러스터 Role은 네임스페이스 에 있는 오브젝트를 사용할수 있는 권한 제공 가능. 



1

# 인프라 네임스페이스(NS) 신규 생성 및 정보 확인 하자


kubectl create ns infrateam

namespace/infrateam created


2

kubens infrateam

Context "service-account-context" modified.

Active namespace is "infrateam".


3

kubectl describe sa && kubectl describe secrets

Name:                default

Namespace:           infrateam

Labels:              <none>

Annotations:         <none>

Image pull secrets:  <none>

Mountable secrets:   default-token-jsz4c

Tokens:              default-token-jsz4c

Events:              <none>

Name:         default-token-jsz4c

Namespace:    infrateam

Labels:       <none>

Annotations:  kubernetes.io/service-account.name: default

              kubernetes.io/service-account.uid: 98bc5e94-13a6-4647-9c72-d2df875fefb4


Type:  kubernetes.io/service-account-token


Data

====

ca.crt:     1082 bytes

namespace:  9 bytes

token:      eyJhbGciOiJSUzI1


4

# 서비스 어카운트 생성 - infrateam 네임스페이스에 소속됨

본인 이름으로 서비스 어카운트를 만들어 테스트 하자.


NICK=<편한 닉네임, 소문자로>

NICK=masterseo


kubectl create sa $NICK

serviceaccount/masterseo created


5

# 확인

kubectl get sa

NAME        SECRETS   AGE

default     1         92s

masterseo   1         17s



6

토큰이 있다~

디폴트 권한만 있다.

kubectl get secrets

NAME                    TYPE                                  DATA   AGE

default-token-jsz4c     kubernetes.io/service-account-token   3      108s

masterseo-token-dwpn4   kubernetes.io/service-account-token   3      33s



7

# 클러스터롤과 롤바인딩 생성 ?


모든 리소스에 모든 권한을 가진 role 을 만든다 !!

- apiGroups: ["*"]

  verbs: ["*"]

  resources: ["*"]


바인딩하고, nick name에 권한까지 준다.


cat <<EOF | kubectl create -f -

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

  name: cluster-role-01

rules:

- apiGroups: ["*"]

  verbs: ["*"]

  resources: ["*"]

---

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding

metadata:

  name: cluster-rolebind-01

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: ClusterRole

  name: cluster-role-01

subjects:

- kind: ServiceAccount

  name: $NICK

  namespace: infrateam

EOF


clusterrole.rbac.authorization.k8s.io/cluster-role-01 created

clusterrolebinding.rbac.authorization.k8s.io/cluster-rolebind-01 created



8

kubectl describe clusterroles cluster-role-01

Name:         cluster-role-01

Labels:       <none>

Annotations:  <none>

PolicyRule:

  Resources  Non-Resource URLs  Resource Names  Verbs

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

  *.*        []                 []              [*]



9

kubectl get clusterrolebindings cluster-rolebind-01

NAME                  ROLE                          AGE

cluster-rolebind-01   ClusterRole/cluster-role-01   81s


10

kubectl describe clusterrolebindings cluster-rolebind-01

Name:         cluster-rolebind-01

Labels:       <none>

Annotations:  <none>

Role:

  Kind:  ClusterRole

  Name:  cluster-role-01

Subjects:

  Kind            Name       Namespace

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

  ServiceAccount  masterseo  infrateam




12

# <닉네임> SA(서비스 어카운트)의 토큰(token) 정보 추출


TOKEN=`kubectl get secrets $(kubectl get sa $NICK -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 -d`

echo $TOKEN

eyJhbGciOiJSUzI1NiIsImtpZCI6IndXdlJocVFkREhyZHQzck9UNEx0MktwTFlqOTJScURVZC1mQzVy



13

# 다른 네임스페이스 오브젝트에 대해서 API서버 조회 ?

Bearer token (ServiceAccount token)


dev팀의 pod가 조회 가능하다~

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/pods/


다른 네임스페이스의 Pod 조회가 가능하다 !!


{

  "kind": "PodList",

  "apiVersion": "v1",

  "metadata": {

    "resourceVersion": "544437"

  },

  "items": [

    {

      "metadata": {

        "name": "pod-1",

        "namespace": "devteam",

        "uid": "cc279997-35b2-47cd-8cb3-03abe10f55e8",

        "resourceVersion": "537118",

        "creationTimestamp": "2021-07-28T03:38:01Z",

        "labels": {

          "app": "pod"

        },


14

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/namespaces/devteam/services/


노드의 정보도 조회 된다. = 클러스터 레벨의 권한이 있다.

curl -k -H "Authorization: Bearer $TOKEN" https://$APIADDR/api/v1/nodes




<9> default 서비스 어카운트로 kubernetes 서비스를 통해 API 서버 사용


1

# devteam NS 로 변경

kubens devteam

Context "service-account-context" modified.

Active namespace is "devteam".


2

# 이전 실습에서 생성해둔 pod-1 의 Mounts 와 ConfigMap 정보 확인

kubectl describe pod pod-1 | egrep '(Mounts|ConfigMapName)' -A1

    Mounts:

      /var/run/secrets/kubernetes.io/serviceaccount from default-token-gtl6g (ro)


3

kubectl get configmaps -o yaml

apiVersion: v1

items:

- apiVersion: v1

  data:

    ca.crt: |

      -----BEGIN CERTIFICATE-----

      MIIC8jCCAdqgAwIBAgIMFpULGp3W2XRcR+LMMA0GCSqGSIb3DQEBCwUAMBUxEzAR

     



4

(옵션) 파드(pod-1) 생성된 노드에서 컨테이너 상세 정보 확인

clear

docker inspect ec6c4d010772 | grep Mounts -A8

"Mounts": [

            {

                "Type": "bind",

                "Source": "/var/lib/kubelet/pods/2b9f016c-b43a-4f1c-83d4-bc2ca276af1d/volumes/kubernetes.io~projected/kube-api-access-xc7vf",

                "Destination": "/var/run/secrets/kubernetes.io/serviceaccount",

                "Mode": "ro",

                "RW": false,

                "Propagation": "rprivate"

            },

...



5

# 파드에 기본 적용되는 서비스 어카운트(토큰)

kubectl exec -it pod-1 -- ls /run/secrets/kubernetes.io/serviceaccount

ca.crt     namespace  token



kubectl exec -it pod-1 -- cat /run/secrets/kubernetes.io/serviceaccount/token

eyJhbGciOiJSUzI1NiIsImtpZCI6IndXdlJocVFkREhyZHQzck9UNEx0MktwTFlqOTJScURVZC1mQzVycGxzR28ifQ.eyJp


kubectl exec -it pod-1 -- cat /run/secrets/kubernetes.io/serviceaccount/namespace

devteam



kubectl exec -it pod-1 -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt

-----BEGIN CERTIFICATE-----

MIIC8jCCAdqgAwIBAgIMFpULGp3W2XRcR+LMMA0GCSqGSIb3DQEBCwUAMBUxEzAR

BgNVBAMTCmt1YmVybmV0ZXMwHhcNMjEwNzIzMTMxNzMwWhcNMzEwNzIzMTMxNzMw




6

# API서버 정보 확인

kubectl get svc -A

NAMESPACE     NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE

default       kubernetes   ClusterIP   100.64.0.1       <none>        443/TCP                  2d15h

devteam       svc-1        ClusterIP   100.67.127.140   <none>        8080/TCP                 17m

kube-system   kube-dns     ClusterIP   100.64.0.10      <none>        53/UDP,53/TCP,9153/TCP 



7

kubectl describe svc kubernetes -n default

Name:              kubernetes

Namespace:         default

Labels:            component=apiserver

                   provider=kubernetes

Annotations:       <none>

Selector:          <none>

Type:              ClusterIP

IP Families:       <none>

IP:                100.64.0.1

IPs:               100.64.0.1

Port:              https  443/TCP

TargetPort:        443/TCP

Endpoints:         172.20.50.211:443

Session Affinity:  None

Events:            <none>



8

# 파드 Shell 실행

kubectl exec -it pod-1 -- zsh

Welcome to Netshoot! (github.com/nicolaka/netshoot)



9

# API 서버 DNS 쿼리 정보 확인

# 아래 쿼리 중 어떤건 안되는 것이 있다. 왜그럴까?

cat /etc/resolv.conf

nslookup kubernetes

nslookup kubernetes.default

nslookup kubernetes.default.

nslookup kubernetes.default.svc

nslookup kubernetes.default.svc.

nslookup kubernetes.default.svc.cluster.local

nslookup -type=A kubernetes -debug | grep QUESTIONS -A1

nslookup -type=A kubernetes.default -debug | grep QUESTIONS -A1


# API 서버 접근 - 여기도 확인 !

curl https://kubernetes -k

curl https://kubernetes.default -k


10

# 파드 내에서 어떻게든 API 서버 접근을 해보자!

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

echo $TOKEN


curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/version

eyJhbGciOiJSUzI1NiIsImtpZCI6IndXdlJocVFkREhyZHQzck9UNEx0MktwTFlqOTJScURVZC1mQzVycy5pb

{

  "major": "1",

  "minor": "20",

  "gitVersion": "v1.20.8",

  "gitCommit": "5575935422cc1cf5169dfc8847cb587aa47bac5a",

  "gitTreeState": "clean",

  "buildDate": "2021-06-16T12:53:07Z",

  "goVersion": "go1.15.13",

  "compiler": "gc",

  "platform": "linux/amd64"

}#                                                                                                                                                                             

11

curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/apis

{

  "kind": "APIGroupList",

  "apiVersion": "v1",

  "groups": [

    {

      "name": "apiregistration.k8s.io",

      "versions": [

        {

          "groupVersion": "apiregistration.k8s.io/v1",

          "version": "v1"

        },

        {

          "groupVersion": "apiregistration.k8s.io/v1beta1",

          "version": "v1beta1"

        }

      ],

curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/api/v1/nodes

exit



12

curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/api/v1/nodes

{

  "kind": "Status",

  "apiVersion": "v1",

  "metadata": {


  },

  "status": "Failure",

  "message": "nodes is forbidden: User \"system:serviceaccount:devteam:default\" cannot list resource \"nodes\" in API group \"\" at the cluster scope",

  "reason": "Forbidden",

  "details": {

    "kind": "nodes"

  },

  "code": 403

}

#




<10> 파드에 특정 서비스 어카운트 지정 후 kubernetes 서비스를 통해 API 서버 사용


1

# infrateam NS 로 변경

kubens infrateam


1

# 이전 실습에서 생성한 서비스 어카운트 정보 확인

kubectl get sa ; kubectl get secret ; kubectl describe clusterrolebindings cluster-rolebind-01


3

# 닉네임 변수 지정(혹은 확인)

NICK=<닉네임>

NICK=masterseo


4

# 파드 생성 시 특정 서비스 어카운트의 시크릿을 마운트 하기

# infrateam NS에 파드 생성


cat <<EOF | kubectl create -f -

apiVersion: v1

kind: Pod

metadata:

  name: pod-1

  labels:

    app: pod

spec:

  serviceAccountName: $NICK

  containers:

  - name: netshoot-pod

    image: nicolaka/netshoot

    command: ["tail"]

    args: ["-f", "/dev/null"]

  terminationGracePeriodSeconds: 0

EOF


//  serviceAccountName: $NICK

Pod 생성할때  서비스 어카운트 매핑이 가능하다.




5

# 파드 Shell 실행

kubectl exec -it pod-1 -- zsh

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

# API 서버 접속 확인

nslookup kubernetes.default


TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

echo $TOKEN


몇가지 조회가 된다.

curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/api/v1/nodes


curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/api/v1/namespaces/devteam/pods/ 


curl --header "Authorization: Bearer $TOKEN" -k https://kubernetes.default/api/v1/namespaces/devteam/services/


curl https://kubernetes.default/ -k

exit



<11> 삭제


1

kubens default

Context "service-account-context" modified.

Active namespace is "default".


2

kubectl delete ns devteam infrateam

namespace "devteam" deleted

namespace "infrateam" deleted


3

clusterrolebindings ?


kubectl delete clusterrolebindings cluster-rolebind-01 && kubectl delete clusterroles cluster-role-01

clusterrolebinding.rbac.authorization.k8s.io "cluster-rolebind-01" deleted

clusterrole.rbac.authorization.k8s.io "cluster-role-01" deleted




다음 보기

https://brunch.co.kr/@topasvga/1745



https://brunch.co.kr/@topasvga/1656


감사합니다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari