[쿠버네티스 쉽게 이해하기 14] 인증Authentication과 알백RBAC 방식의 인가Authorization
14. 인증Authentication과 알백RBAC 방식의 인가Authorization
접근하는 사용자를 인증하고 권한을 부여하는 인가는 안전한 쿠버네티스 운영을 위해 매우 중요 합니다.
먼저 쿠버네티스가 인증과 인가를 처리하는 원리에 대해서 살펴 보겠습니다.
두번째로 알백 방식으로 권한을 부여하는 방법에 대해 알아 보겠습니다.
다음으로 인증 방법 중 서비스 어카운트 인증, X.509 인증서 기반 인증, WebHook 연동 인증을 실습하도록 하겠습니다.
14.1 인증과 인가 방법 이해
사용자, 그룹, 서비스 어카운트의 요청이 쿠버네티스에서 처리되기 위해서는 인증 ⇒ 인가 ⇒ 진입 제어의 세 단계를 통과해야 합니다.
예를 들어 여러분들이 ‘k get po -A’라는 명령으로 모든 네임스페이스의 파드 리스트를 확인하는 경우를 생각해 봅시다.
먼저 명령을 내린 머신에 있는 kubernetes config파일(기본적으로 $HOME/.kube/config파일)에서 현재 사용자가 누구인지를 찾습니다.
‘k config view’라는 명령으로 보면 현재 컨텍스트의 현재 유저를 볼 수 있습니다.
그 유저를 기본인증, X.509 인증서 기반 인증, OAuth 연동 인증, WebHook 연동 인증, 프락시 서버 연동 인증 중 하나의 방법으로 인증 합니다.
인증이 성공하면 유저가 ‘k get po -A’라는 명령을 수행할 권한이 있는지 클러스터 롤 바인딩과 롤 바인딩을 검사 합니다.
인증과 인가까지 통과한 요청은 어드미션 컨트롤러의 뮤테이팅Mutating 어드미션Admission과 밸리데이팅Validating 어드미션Admission 과정까지 통과해야 합니다.
뮤테이팅 어드미션은 요청을 정책에 맞게 변형하는 과정이고 밸리데이팅 어드미션은 최종적으로 요청을 수락할 지 판단하는 과정입니다.
예를 들어 뮤테이팅 어드미션에서 무조건 현재 네임스페이스의 파드 리스트만 리턴 하도록 요청을 변형 하였다면 전체 네임스페이스의 파드를 볼 수 있는 권한이 있더라도 현재 네임스페이스의 파드 리스트만 리턴 됩니다.
밸리데이팅 어드미션에서 ‘Guest’그룹의 사용자는 파드 리스트를 못 보게 정의 하였고 현재 사용자가 ‘Guest’그룹에 속한다면 최종적으로 요청은 거부 됩니다.
쿠버네티스에 대한 요청이 처리되는 전체 과정을 요약하면 아래와 같습니다.
인증의 방법에는 기본인증, X.509 인증서 기반 인증, OAuth 연동 인증, WebHook 연동 인증, 프락시 서버 연동 인증이 있다고 했는데 어떤 방법으로 인증하는게 좋을까요 ?
각 인증 방법의 장단점을 비교하면 아래와 같습니다.
인증방법 | 설명 | 장점 | 단점 |
기본인증 (일반유저) |
ID와 암호 또는 인증 토큰을 이용 | 계정관리 편리: 외부 시스템 연동 없이 자체 계정 정보 파일만 있으면 됨 | 평문 또는 base64인코딩된 암호 사용으로 보안 위험 존재 |
기본인증 (서비스어카운트) |
JWT 이용 | 계정관리 편리: 외부 시스템 연동 없이 JWT로만 인증함 | JWT 탈취 시 보안 위험 발생하므로 정기적으로 서비스 어카운트의 프라이빗 키 교체 필요 |
X.509 인증서 기반 인증 | X.509 인증서의 프라이빗키/퍼블릭키 비교 방식 이용 | 계정관리 편리: 외부 시스템 연동 없이 X.509인증서로만 인증함 | 클라이언트 인증서 탈취 시 보안 위험 발생하므로 정기적으로 클라이언트 인증서와 프라이빗 키 교체 필요 |
OAuth 연동 인증 | OAuth 서비스 프로바이더와 연동하여 인증 | 계정 관리 편의성과 보안 보장: 기존 OAuth 서비스 프로바이더 ID/암호 사용할 수 있고 OAuth방식으로 안전한 인증 보장 | OAuth 연동을 위한 개발 필요 |
WebHook 연동 인증 | WebHook으로 인증 시스템과 연동하여 인증 | 계정 관리 편의성과 보안 보장: 기존 인증시스템 ID/암호 사용할 수 있고 WebHook 통한 안전한 인증 보장 | WebHook 개발 필요 |
프락시 서버 연동 인증 | 프락시 서버로 인증 시스템과 연동하고 X.509인증서 기반 인증을 조합하여 인증 | 계정관리 편의성, 보안 보장, 쿠버네티스 API Server 노출 안됨 | 프락시 서버 개발 필요와 프락시 서버의 X.509인증서 정기적 교체 필요 |
모든 상황에서 권장되는 인증 방식은 없습니다.
쿠버네티스에서 서비스되는 업무의 성격에 따라 계정관리의 편의성과 보안성을 고려하여 적절한 인증 방식을 선택하여야 합니다.
어드미션 컨트롤은 쿠버네티스 1.25부터 파드 시큐리티 폴리시(PSP: Pod Security Policy)를 완벽히 대체할 예정입니다.
어드미션 컨트롤은 개발자나 CI/CD팀의 실수로 부터 쿠버네티스의 안전을 방어할 수 있는 최후의 보루라고 할 수 있습니다.
어드미션 컨트롤은 쿠버네티스 운영자의 역할이기 때문에 이 책에서는 더 이상 깊게 다루지 않습니다.
관심 있는 분들은 아래 블로그 글을 참고하시기 바랍니다.
https://coffeewhale.com/kubernetes/admission-control/2021/04/28/opa1/
14.2 알백 권한 관리 방법
알백으로 권한을 정의하기 위해서 여러분들은 롤과 클러스터롤을 정의하는 방법을 알아야 합니다.
그리고 정의한 클러스터롤/롤을 사용자/그룹/서비스어카운트에 연결하기 위한 클러스터 롤 바인딩과 롤 바인딩을 어떻게 하는지도 알아야 합니다.
또한 지금 접근하는 유저가 특정 수행을 할 수 있는지 체크하는 방법까지 알면 더 좋습니다.
이와 같은 방법을 학습하고 마지막에는 이후의 실습을 위한 사전 작업을 수행하겠습니다.
1) 클러스터롤/롤 정의하기
클러스터롤은 모든 네임스페이스에 대한 권한을 정의하는 것이고 롤은 특정 네임스페이스에 대한 권한만을 정의하는 것입니다.
정의하는 문법은 롤은 네임스페이스를 지정해야 한다는 것 외에는 동일 합니다.
❶ ‘API Group/API Version’ 형식으로 apiVersion을 지정하고 ‘kind’에 리소스의 종류를 ‘ClusterRole’ 또는 ‘Role’로 합니다.
❷ 클러스터 롤은 ‘name’만 지정하면 되고 롤은 ‘name’과 ‘namespace’를 지정 합니다.
❸ ‘rules’는 권한을 부여할 오브젝트의 API Group, 리소스명, CRUD 권한의 세 부분으로 구성 됩니다.
정의를 할 때 아래와 같은 순서로 작업 하시면 됩니다.
- 어떤 리소스에 대해 권한을 정의할 지 결정
- 그 리소스의 API Group을 ‘k api-resources | grep {리소스명}’로 찾음. 찾은 결과에서 API Group과 정확한 리소스명을 ‘apiGroups’와 ‘resources’에 추가함.
- 어떤 CRUD 권한을 부여할 지 정의함. CRUD별 권한명은 아래와 같음
권한구분 | verbs |
CREATE | create |
READ | get, list, watch |
UPDATE | update, patch |
DELETE | delete |
2) 클러스터롤 바인딩/롤 바인딩 하기
클러스터롤 바인딩은 모든 네임스페이스에 적용되는 클러스터롤과 바인딩하는 것이고 롤 바인딩은 특정 네임스페이스에만 적용되는 롤과 바인딩하는 것입니다.
❶ 클러스터롤 바인딩과 롤 바인딩 정의의 차이는 롤 바인딩은 네임스페이스까지 정의한다는 것입니다.
❷ 바인딩할 롤을 정의하는 ‘roleRef’에서 ‘kind’는 바인딩할 롤이 클러스터롤이면 ‘ClusterRole’이라고 하고 롤이면 ‘Role’이라고 정의하면 됩니다.
❸ 바인딩할 대상을 정의하는 ‘subjects’에서 ‘kind’는 대상의 유형에 따라 ‘User’, ‘Group’, ‘ServiceAccount’로 지정할 수 있습니다.
클러스터롤 바인딩과 롤 바인딩은 ‘kubectl’명령으로 생성할 수도 있습니다.
kubectl create {바인딩 오브젝트 유형: clusterrolebinding OR rolebinding} \
{바인딩 오브젝트 이름} \
{바인딩 클러스터롤 OR 롤: --clusterrole={클러스터롤 이름} OR --role={롤 이름} \
{바인딩 대상: --user={유저명} OR --group={그룹명} OR --serviceaccount={네임스페이스}:{서비스어카운트명}}
예1) kubectl create clusterrolebinding crb_kube-admin --clusterrole=admin --user=kube-admin,ou=users,dc=myldap,dc=io
예2) kubectl create rolebinding rb_ott_ott-admin --clusterrole=admin --user=ott-admin -n ott
예3) kubectl create rolebinding rb_ott_sa-edit --clusterrole=edit --serviceaccount=ott:sa-edit -n ott
3) 수행 권한 체크 방법
쿠버네티스는 KubeConfig에 정의된 정보를 바탕으로 현재 사용자가 특정 수행을 할 수 있는지 체크하는 방법을 제공 합니다.
‘kubectl auth can-i’라는 명령을 사용하면 됩니다.
kubectl auth can-i VERB [TYPE | TYPE/NAME | NONRESOURCEURL] [options]
사용법과 예제는 ‘kubectl auth can-i --help’로 도움말을 참조하면 됩니다.
[root@osboxes ~]# kubectl auth can-i create pods --namespace ott yes |
4) 인증/인가 실습을 위한 사전 작업
이후 실습을 위해 클러스터 롤 ‘crole-cicd’와 롤 ‘role-cicd’를 만들겠습니다.
클러스터롤과 롤을 만들기 위한 야믈 파일을 다운로드하여 생성 하십시오.
[root@osboxes]# cd ~/k8s/yaml [root@osboxes yaml]# wget https://hiondal.github.io/k8s-yaml/3.14/role.yaml |
‘crole-cicd’는 노드, 네임스페이스, 스토리지클래스, 퍼시스턴트볼륨의 READ권한만을 정의한 클러스터롤입니다.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: crole-cicd rules: - apiGroups: [ "", "storage.k8s.io" ] resources: [ "nodes", "namespaces", "storageclasses", "persistentvolumes" ] verbs: [ "get", "list", "watch" ] |
‘role-cicd’는 아래와 같이 CI/CD를 위한 CRUD권한과 서비스어카운트에 대한 READ권한을 정의한 롤입니다.
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: role-cicd namespace: ott rules: - apiGroups: [ "", "apps" ] resources: [ "ingresses", "services", "configmaps", "persistentvolumeclaims", "deployments", "statefulsets", "pods", "replicasets" ] verbs: [ "create", "get", "list", "watch", "update", "patch", "delete" ] - apiGroups: [ "" ] resources: [ "serviceaccounts" ] verbs: [ "get", "list" ] |
‘role.yaml’파일을 이용하여 클러스터롤과 롤을 생성 합니다.
[root@osboxes yaml]# k apply -f role.yaml role.rbac.authorization.k8s.io/role-cicd created clusterrole.rbac.authorization.k8s.io/crole-cicd created |
또한 이후의 실습을 위해 아래 작업을 먼저 해 주십시오.
공통으로 사용할 환경 변수를 생성 합니다.
- API_FQDN: 쿠버네티스 API 서버의 주소입니다. 여러분의 쿠버네티스 컨트롤 플레인의 퍼블릭 IP로 바꾸십시오.
- CLUSTER: 클러스터 이름입니다. 저는 ‘happycloud’로 했고 바꾸셔도 됩니다.
- CERTDIR: 쿠버네티스 인증서들을 다운로드 받을 디렉토리 입니다. 역시 바꾸셔도 됩니다.
[root@osboxes yaml]# API_FQDN=https://169.56.70.197:6443 [root@osboxes yaml]# CLUSTER=happycloud [root@osboxes yaml]# CERTDIR=/etc/kubernetes/pki |
쿠버네티스 인증서 디렉토리를 만들고 루트CA 인증서인 ‘ca.crt’와 루트CA의 프라이빗 키인 ‘ca.key’를 다운로드 합니다.
[root@osboxes yaml]# mkdir -p ${CERTDIR} [root@osboxes yaml]# scp m:${CERTDIR}/ca.key ${CERTDIR}/ca.key [root@osboxes yaml]# scp m:${CERTDIR}/ca.crt ${CERTDIR}/ca.crt |
‘cluster-admin’권한을 가진 유저 ‘kubernetes-admin’이 정의된 KubeConfig파일을 다운로드 하고 그 파일을 사용하여 ‘kubectl’명령이 수행되도록 합니다. ‘KUBECONFIG’라는 환경 변수에 KubeConfig파일의 경로를 지정하면 됩니다.
[root@osboxes yaml]# scp m:/etc/kubernetes/admin.conf ~/.kube/admin.conf [root@osboxes yaml]# export KUBECONFIG=~/.kube/admin.conf |
‘kubectl config view’ 명령으로 현재 컨텍스트, 네임스페이스 , 유저의 인증서 정보를 확인해 보십시오.
[root@osboxes yaml]# k config view |
현재 컨텍스트는 ‘kubernetes-admin@kubernetes’이고 현재 유저는 ‘kubernetes-admin’이며 이 유저의 인증서와 프라이빗키가 파일 안에 정의되어 있습니다.
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1…Cg== server: https://169.56.70.197:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: LS0tLS…g== client-key-data: LS0tLS1CRUdJTiB… |
지금까지 우리는 이 파일을 배천 노드의 ‘~/.kube/config’에 다운로드하여 사용하였습니다.
환경변수 ‘KUBECONFIG’값이 비어 있으면 ‘~/.kube/config’ 파일을 이용하여 쿠버네티스를 접근하게 됩니다.
즉, 우리는 지금까지 클러스터 관리자의 권한으로 쿠버네티스를 접근하였던 것입니다.
14.3 서비스 어카운트 인증 실습
클라이언트인 사용자 PC나 프로그램에서 서비스 어카운트의 JWT(JSON Web Token)를 이용하여 인증하는 방식입니다.
서비스 어카운트의 JWT는 서비스 어카운트 생성 시 컨트롤 매니저에 의해 시크릿 오브젝트로 자동으로 만들어집니다.
서비스 어카운트 ‘sa-cicd’를 만들고 자동으로 만들어진 시크릿 오브젝트로 부터 JWT를 구하여 그 내용을 보겠습니다.
그리고 KubeConfig파일에 서비스 어카운트를 위한 클러스터, 컨텍스트, 유저 정보를 구성하겠습니다.
그 다음 서비스 어카운트 ‘sa-cicd’에 클러스터롤 ‘crole-cicd’와 롤 ‘role-cicd’를 바인딩하여 권한을 부여 하고 인증/인가를 테스트 하겠습니다.
1) 서비스 어카운트 생성 및 JWT 내용 확인
서비스 어카운트 인증/인가를 위해 필요한 환경변수를 생성 합니다.
- KUBECFG: 새로 만들 쿠버네티스 컨피그 파일의 경로
- CONTEXT: 쿠버네티스를 접근하는 유저, 클러스터, 네임스페이스를 정의한 컨텍스트 이름
- NS: CRUD권한을 부여할 네임스페이스 이름
- SA: 서비스어카운트 이름
- ROLE: 서비스어카운트에 바인딩할 롤 이름
- CLUSTER_ROLE: 서비스어카운트에 바인딩할 클러스터 롤 이름
[root@osboxes yaml]# KUBECFG=~/.kube/config-sa [root@osboxes yaml]# CONTEXT=sa@ott [root@osboxes yaml]# NS=ott [root@osboxes yaml]# SA=sa-cicd [root@osboxes yaml]# ROLE=role-cicd [root@osboxes yaml]# CLUSTER_ROLE=crole-cicd |
서비스 어카운트 ‘sa-cicd’를 만듭니다. ‘2>/dev/null’은 에러가 났을 때 (결과값이 ‘2’ 일때) 표시하지 않게(/dev/null로 결과를 보냄)하는 옵션 입니다.
[root@osboxes yaml]# k create sa ${SA} -n ${NS} 2>/dev/null serviceaccount/sa-cicd created |
자동으로 만든 시크릿 오브젝트에서 JWT값을 구합니다.
{변수}=`{명령}`과 같은 형태로 명령의 결과를 변수로 받을 수 있습니다. 이때 {명령}을 감싼 특수 기호는 작은 따옴표가 아니라 키보드에서 숫자 1 왼쪽에 있는 물결표시입니다. 영문 상태에서 그 키를 누르면 작은 따옴표 비슷하게 나옵니다.
[root@osboxes yaml]# secret=`k get secret -n ${NS} | grep ${SA} | awk '{print $1}'` [root@osboxes yaml]# jwt=`k describe secret ${secret} -n ${NS} | grep token: | awk '{print $2}'` [root@osboxes yaml]# echo $jwt |
웹브라우저에서 ‘https://jwt.io’를 접근하고 왼쪽 박스에 위에서 구한 JWT의 값을 붙여넣어 보십시오.
JWT는 오른쪽에 디코딩된 값과 같이 HEADER, PAYLOAD, SIGNATURE의 세 파트로 구성되어 있습니다. 각 파트의 값을 BASE64로 인코딩하고 ‘.’으로 연결 합니다. 실제 데이터가 들어가는 곳은 PAYLOAD부분이고 아래 예와 같이 네임스페이스, 서비스어카운트명 등이 정의되어 있습니다.
이 JWT가 쿠버네티스 API Server로 전달 되면 API Server는 JWT SIGNATURE파트에 있는 값을 서비스 어카운트 용 퍼블릭 키(/etc/kubernetes/pki/sa.pub)로 검증을 하여 인증을 합니다.
API 서버가 하는 검증 작업을 실제로 한번 해 보겠습니다.
위 JWT는 왼쪽 하단에 보시면 ‘Invalid Signature’라고 나옵니다. 검증할 퍼블릭 키가 없기 때문입니다.
아래 명령으로 컨트롤 플레인의 ‘/etc/kubernetes/pki/sa.pub’의 값을 복사하여 오른쪽 SIGNATURE파트의 첫번째 박스에 붙여 넣어 보십시오.
[root@osboxes yaml]# ssh m cat /etc/kubernetes/pki/sa.pub -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxBmNMhP0UvydhugsL2Qi VSPdZbJJJ3fb4b93gfMxjZZy58Ji3eMIhpLl9CJGsPUlOhTyb8urfjQ3vS9Snick bOSKMbz1sNwmabJcxyKjjI0bII0y60yo+nUJpzKyiwj1OFYe1gKkZwVmIbhmQZhw u/KwAChdi07jX5XaWgbhUrujAIJXppnHGWEWWJQn9O0zGQ/fbDRk+MARI6XQGzcN +ODoucvrLcd2G3gm6yPvzoxanDRMeTBGbT4kicrnvgoTv0f4893BsE43CtmXYnXc Rhn5Cop60yWfLOQWCB+pu8YN6PLd74rL01DL4SatAzV3pJRnUD3p1MCN+vdVFqPY mQIDAQAB -----END PUBLIC KEY----- |
아래와 같이 정상적인 JWT값으로 검증이 됩니다.
2) KubeConfig 파일 구성
쿠버네티스 클러스터를 접근하는 머신에 KubeConfig파일이 있으면 그 파일의 정보를 이용하여 클러스터를 접근 합니다.
KubeConfig파일의 위치는 ‘{사용자 홈 디렉토리}/.kube/config’ 또는 ‘KUBECONFIG’라는 환경변수에 등록한 경로 입니다.
쿠버네티스 관리자는 클러스터를 접근하는 팀별로 서비스 어카운트를 만들고 그 팀에서 공용으로 사용할 KubeConfig파일을 제공하는 방식으로 운영할 수 있습니다.
그리고 보안을 위해 주기적으로 서비스 어카운트를 재생성하여 JWT값이 바뀌도록 하여야 합니다.
KubeConfig파일은 아래와 같이 Clusters, Contexts, Users로 구성되어 있습니다.
KubeConfig 파일은 직접 파일을 편집하여 만들어도 되고 ‘kubectl config’명령으로 만들 수도 있습니다.
우리는 ‘kubectl config’명령을 이용하여 만들도록 하겠습니다.
이미 위에서 했지만 확실하게 다시 한번 KUBECONFIG 환경변수를 셋팅 합니다.
‘admin.conf’를 KubeConfig파일로 사용하게 함으로써 이후의 수행은 ‘cluster-admin’권한으로 수행하게 합니다.
[root@osboxes yaml]# export KUBECONFIG=~/.kube/admin.conf |
‘kubectl config set-cluster’명령을 이용하여 새 KubeConfig파일에 클러스터를 만듭니다.
[root@osboxes yaml]# k config set-cluster ${CLUSTER} \ --kubeconfig=${KUBECFG} \ --server=${API_FQDN} \ --certificate-authority=${CERTDIR}/ca.crt \ --embed-certs=true [root@osboxes ~]# cat ${KUBECFG} |
KubeConfig파일인 ‘~/.kube/config-sa’파일의 내용을 보면 아래와 같이 클러스터가 추가되어 있을 겁니다
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS…Cg== server: https://169.56.70.197:6443 name: happycloud contexts: null current-context: "" kind: Config preferences: {} users: null |
‘kubectl config set-context’명령을 이용하여 컨텍스트를 추가 합니다.
[root@osboxes ~]# k config set-context ${CONTEXT} \ --kubeconfig=${KUBECFG} \ --cluster=${CLUSTER} \ --namespace=${NS} \ --user=${SA} Context "sa@ott" created. [root@osboxes ~]# cat ${KUBECFG} |
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS…Cg== server: https://169.56.70.197:6443 name: happycloud contexts: - context: cluster: happycloud namespace: ott user: sa-cicd name: sa@ott current-context: "" kind: Config preferences: {} users: null |
‘kubectl config set-credentials’명령을 이용하여 서비스 어카운트 정보를 ‘Users’에 추가 합니다.
[root@osboxes ~]# k config set-credentials ${SA} \ --kubeconfig=${KUBECFG} \ --token=${jwt} [root@osboxes ~]# cat ${KUBECFG} |
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1…0tCg== server: https://169.56.70.197:6443 name: happycloud contexts: - context: cluster: happycloud namespace: ott user: sa-cicd name: sa@ott current-context: "" kind: Config preferences: {} users: - name: sa-cicd user: token: eyJhb…JBQ |
위와 같이 클러스터, 컨텍스트, 유저가 KubeConfig 파일 ‘~/.kube/config-sa’에 잘 등록되었습니다.
3) 권한 부여 및 테스트
이제 새로 만든 KubeConfig파일을 이용하여 쿠버네티스 클러스터를 접근해 보겠습니다.
아래와 같이 KUBECONFIG 환경변수를 새로운 KubeConfig파일로 셋팅하고 파드리스트를 확인해 보면 API Server로 연결이 안된다는 에러가 납니다.
[root@osboxes ~]# export KUBECONFIG=${KUBECFG} [root@osboxes ~]# k get po The connection to the server localhost:8080 was refused - did you specify the right host or port? |
이유는 현재 컨텍스트가 비어 있기 때문입니다.
아래 명령으로 현재 컨텍스트를 ‘sa@ott’로 변경 하시고 다시 시도 해 보십시오.
이번에는 API Server까지는 연결이 되지만 파드 리스트를 볼 권한이 없어 에러가 납니다.
[root@osboxes ~]# k config use-context ${CONTEXT} Switched to context "sa@ott". [root@osboxes ~]# k get po Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:ott:sa-cicd" cannot list resource "pods" in API group "" in the namespace "ott" |
서비스 어카운트 ‘sa-cicd’에게 클러스터롤 ‘crole-cicd’와 롤 ‘role-cicd’를 바인딩 하십시오.
현재 sa-cicd의 권한으로 수행되므로 맨 끝에 ‘--kubeconfig’옵션을 붙여 수행하는 사용자를 ‘kubernetes-admin’으로 임시로 바꿔 수행 합니다.
서비스 어카운트는 항상 ‘{네임스페이스}:{서비스 어카운트 이름}’의 형식으로 지정해야 합니다.
[root@osboxes ~]# k create clusterrolebinding crb_${NS}_${SA} --clusterrole=${CLUSTER_ROLE} --serviceaccount=${NS}:${SA} --kubeconfig=$HOME/.kube/admin.conf [root@osboxes ~]# k create rolebinding rb_${NS}_${SA} --role=${ROLE} --serviceaccount=${NS}:${SA} -n ${NS} --kubeconfig=$HOME/.kube/admin.conf |
이제 다시 파드 리스트를 확인해 보면 정상적으로 표시 됩니다.
[root@osboxes ~]# k get po NAME READY STATUS RESTARTS AGE member-59d75b86ff-9xbl5 1/1 Running 0 3d recommend-67445ccb4f-4vt5m 1/1 Running 0 3d |
4) 쿠버네티스 OpenAPI 연결 테스트
프로그램으로 쿠버네티스 클러스터를 접근할 때 쿠버네티스 OpenAPI를 이용할 수 있습니다.
쿠버네티스 1.23부터 지원되는 OpenAPI V3는 아직 알파 버전이기 때문에 OpenAPI V2로 테스트 하겠습니다.
쿠버네티스 OpenAPI는 아래 글을 참고 하십시오.
https://kubernetes.io/ko/docs/concepts/overview/kubernetes-api/
API호출 시 HTTP Header ‘Authorization’의 값을 ‘Bearer {인증토큰}’으로 하면 됩니다.
인증 토큰은 서비스 어카운트 생성 시 자동으로 만들어진 시크릿 오브젝트로 부터 구하면 됩니다.
[root@osboxes yaml]# secret=`k get secret -n ${NS} | grep ${SA} | awk '{print $1}'` [root@osboxes yaml]# jwt=`k describe secret ${secret} -n ${NS} | grep token: | awk '{print $2}'` [root@osboxes yaml]# echo $jwt |
‘curl’을 이용하여 간단하게 테스트 해 보겠습니다.
모든 쿠버네티스 OpenAPI 정보를 보려면 아래와 같이 하면 됩니다.
[root@osboxes yaml]# curl -k -H "Authorization: Bearer ${jwt}" ${API_FQDN}/openapi/v2 |
‘-k’는 쿠버네티스 API 서버를 루트CA 인증서 검사 없이 접근하는 옵션입니다. 실제 프로그램에서는 아래와 같이 루트 CA인증서를 ‘--cacert’파라미터로 넘겨야 합니다.
[root@osboxes yaml]# curl --cacert ${CERTDIR}/ca.crt -H "Authorization: Bearer ${jwt}" ${API_FQDN}/openapi/v2 |
위 결과값을 JSON Viewer(예: http://jsonviewer.stack.hu)로 보면 각 오브젝트를 처리할 수 있는 API 주소를 알 수 있습니다.
예를 들어 현재 네임스페이스의 파드 리스트를 보려면 아래와 같이 하면 됩니다.
[root@osboxes yaml]# curl -k -H "Authorization: Bearer ${jwt}" ${API_FQDN}/api/v1/namespaces/${NS}/pods |
14.4 X.509 인증서 기반 인증 실습
이번에는 X.509 인증서를 이용한 인증을 실습해 보겠습니다.
JWT는 서비스 어카운트를 인증할 때만 사용할 수 있기 때문에 일반 사용자를 안전하게 인증하기 위한 다른 방법이 필요 합니다. 그 방법중의 하나가 X.509 인증서를 이용하는 것입니다.
인증할 사용자의 인증서와 프라이빗 키를 먼저 만들어야 합니다. 이때 사용자 인증서를 쿠버네티스의 루트CA와 루트 CA 프라이빗키로 디지털 서명 합니다.
그리고 KubeConfig파일에 클러스터, 컨텍스트, 유저를 추가 합니다.
마지막으로 사용자에게 클러스터롤/롤을 바인딩하여 권한을 부여하고 인증/인가를 테스트 합니다.
1) 사용자 인증서와 프라이빗 키 생성
필요한 환경변수를 먼저 생성 합니다.
- KUBECFG: KubeConfig파일 경로
- CONTEXT: 쿠버네티스를 접근하는 유저, 클러스터, 네임스페이스를 정의한 컨텍스트 이름
- NS: CRUD권한을 부여할 네임스페이스 이름
- USER, ORG_UNIT, ORG: 유저를 구별하는 전체 이름으로 CN={USER}/OU={ORG_UNIT}/O={ORG}형식임
- CLUSTER_ROLE: 유저에게 부여할 클러스터롤 이름
- EXPIREDAYS: 유저 인증서의 유효일로서 보안을 위해 정기적으로 교체하는 것이 좋으므로 짧게 잡는것이 좋음
[root@osboxes ~]# KUBECFG=~/.kube/config-x509 [root@osboxes ~]# CONTEXT=admin@ott [root@osboxes ~]# NS=ott [root@osboxes ~]# USER=ott-admin [root@osboxes ~]# ORG_UNIT=ott [root@osboxes ~]# ORG=happycloud [root@osboxes ~]# CLUSTER_ROLE=admin [root@osboxes ~]# EXPIREDAYS=90 |
사용자의 인증서를 만들기 위해서는 프라이빗키 생성 ⇒ 인증 요청서(CSR-Certificate Signing Request) 생성 ⇒ 인증서 생성의 단계를 거쳐야 합니다.
먼저 프라이빗키를 생성 합니다. 맨 끝에 ‘4096’는 암호화에 사용할 바이트 수 입니다.
[root@osboxes ~]# openssl genrsa -out ${CERTDIR}/${USER}.key 4096 |
프라이빗키로 인증서를 만들 유저를 위한 인증서 생성 요청서 파일을 만듭니다.
이때 인증서 소유자의 풀 네임을 ‘-subj’파라미터로 지정 합니다.
[root@osboxes ~]# openssl req -new \ -key ${CERTDIR}/${USER}.key \ -out ${CERTDIR}/${USER}.csr \ -subj "/CN=${USER}/OU=${ORG_UNIT}/O=${ORG}" |
유저 인증서 파일을 만듭니다. 이때 쿠버네티스 루트CA와 루트CA 프라이빗키로 디지털 서명을 합니다.
[root@osboxes ~]# openssl x509 -req -CAcreateserial \ -days ${EXPIREDAYS} \ -in ${CERTDIR}/${USER}.csr \ -CA ${CERTDIR}/ca.crt \ -CAkey ${CERTDIR}/ca.key \ -out ${CERTDIR}/${USER}.crt Signature ok subject=CN = ott-admin, OU = ott, O = happycloud Getting CA Private Key |
‘/etc/kubernetes/pki’디렉토리에 인증서인 ott-admin.csr, 프라이빗키인 ott-admin.key, CSR인 ott-admin.csr파일이 생성 되었는지 확인 합니다.
[root@osboxes ~]# ll ${CERTDIR} total 32 … -rw-r--r--. 1 root root 1387 Feb 9 06:39 ott-admin.crt -rw-r--r--. 1 root root 1630 Feb 9 06:38 ott-admin.csr -rw-------. 1 root root 3243 Feb 9 06:38 ott-admin.key |
2) KubeConfig 파일 구성
KubeConfig파일인 ‘~/.kube/config-x509’파일에 클러스터와 컨텍스트 정보를 등록 합니다.
먼저 KubeConfig파일을 ‘admin.conf’로 변경한 후 수행 하십시오.
[root@osboxes ~]# export KUBECONFIG=~/.kube/admin.conf [root@osboxes ~]# k config set-cluster ${CLUSTER} \ --kubeconfig=${KUBECFG} \ --server=${API_FQDN} \ --certificate-authority=${CERTDIR}/ca.crt \ --embed-certs=true [root@osboxes ~]# k config set-context ${CONTEXT} \ --kubeconfig=${KUBECFG} \ --cluster=${CLUSTER} \ --namespace=${NS} \ --user=${USER} |
X.509 기반 유저 정보를 등록할 때는 유저 인증서와 유저 프라이빗 키를 파라미터로 넘기면서 ‘--embed-certs’파라미터를 ‘true’로 하여 KubeConfig파일 내에 데이터를 임베드 합니다.
‘--embed-certs’파라미터를 생략하거나 ‘false’로 하면 인증서 경로가 KubeConfig파일에 등록 됩니다.
[root@osboxes ~]# k config set-credentials ${USER} \ --kubeconfig=${KUBECFG} \ --client-certificate=${CERTDIR}/${USER}.crt \ --client-key=${CERTDIR}/${USER}.key \ --embed-certs=true |
현재 컨텍스트를 셋팅 합니다.
[root@osboxes ~]# k config use-context ${CONTEXT} --kubeconfig=${KUBECFG} |
등록된 KubeConfig 파일의 내용을 확인 합니다.
[root@osboxes ~]# cat ${KUBECFG} |
아래와 같이 유저 ‘ott-admin’의 인증서 데이터와 프라이빗 키 데이터가 등록이 됩니다.
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tL…Cg== server: https://169.56.70.197:6443 name: happycloud contexts: - context: cluster: happycloud namespace: ott user: ott-admin name: admin@ott current-context: admin@ott kind: Config preferences: {} users: - name: ott-admin user: client-certificate-data: LS0tLS1CR…RS0tLS0tCg== client-key-data: LS0tLS…LS0K |
3) 권한 부여 및 테스트
KubeConfig파일을 생성한 ‘~/.kube/config-x509’로 변경 합니다.
[root@osboxes ~]# export KUBECONFIG=${KUBECFG} [root@osboxes ~]# k get po The connection to the server localhost:8080 was refused - did you specify the right host or port? |
유저 ‘ott-admin’에게 클로스터롤 ‘admin’과 롤 바인딩 합니다.
[root@osboxes ~]# k create rolebinding rb_${NS}_${USER} --clusterrole=${CLUSTER_ROLE} --user=${USER} -n ${NS} --kubeconfig=$HOME/.kube/admin.conf |
유저 ‘ott-admin’은 네임 스페이스 ‘ott’에 대해 ‘admin’권한을 갖게 되었으므로 이제 파드 리스트가 정상적으로 리턴 됩니다.
[root@osboxes ~]# k get po NAME READY STATUS RESTARTS AGE member-59d75b86ff-9xbl5 1/1 Running 0 3d6h recommend-67445ccb4f-4vt5m 1/1 Running 0 3d6h |
4) 쿠버네티스 OpenAPI 연결 테스트
X.509 인증서 기반으로 쿠버네티스를 OpenAPI로 접근할 때도 KubeConfig와 동일하게 유저의 인증서와 프라이빗키를 넘기면 됩니다.
[root@osboxes yaml]# curl -k \ --cert ${CERTDIR}/ott-admin.crt \ --key ${CERTDIR}/ott-admin.key \ ${API_FQDN}/api/v1/namespaces/${NS}/pods |
14.5 WebHook 연동 인증 실습
쿠버네티스를 접근하는 클라이언트의 인증을 위해 서비스 어카운트나 X.509인증서를 사용하는 것은 별도의 외부 시스템과 연동하지 않아 단순하고 편하기는 하나 주기적으로 인증 데이터를 갱신해야 하는 불편함이 있습니다.
WebHook으로 외부 인증 시스템을 연동하면 보안을 보장하면서 이러한 불편함을 해결할 수 있습니다.
물론 WebHook프로그램을 개발하고 외부 인증 시스템을 별도로 구축해야 하는 작업은 필요 합니다.
WebHook 연동 실습은 아래와 같은 순서로 진행 됩니다.
1) 환경변수 생성
이후 실습에서 사용할 환경변수를 생성 합니다.
- KUBECFG: KubeConfig 파일 경로
- CONTEXT: KubeConfig 파일에 등록할 컨텍스트 이름
- CLUSTER: KubeConfig 파일에 등록할 클러스터 이름
- NS: 네임 스페이스
- USER: 유저명
- LDAP: LDAP서버 주소. IP는 본인의 워커노드 IP로 반드시 변경 필요
- DN: LDAP에 등록된 사용자의 구별된 이름(Distinguished Name)
- PW: LDAP에 등록된 사용자 암호
- ROLE: 권한 부여를 위해 바인딩할 롤 이름
- CLUSTER_ROLE: 권한 부여를 위해 바인딩할 클러스터롤 이름
[root@osboxes ~]# KUBECFG=$HOME/.kube/config-webhook [root@osboxes ~]# CONTEXT=user@ott [root@osboxes ~]# CLUSTER=happycloud [root@osboxes ~]# NS=ott [root@osboxes ~]# USER=user1 [root@osboxes ~]# LDAP=ldap://169.56.70.201:389 [root@osboxes ~]# DN=cn=user1,ou=users,dc=myldap,dc=io [root@osboxes ~]# PW=passw0rd [root@osboxes ~]# ROLE=role-cicd [root@osboxes ~]# CLUSTER_ROLE=crole-cicd |
2) KubeConfig 파일 구성
KubeConfig파일인 ‘~/.kube/config-webhook’파일에 클러스터와 컨텍스트 정보를 등록 합니다.
이번에는 클러스터 등록 시 인증서를 KubeConfig파일에 임베드 하지 않겠습니다.
생성된 KubeConfig파일의 클러스터 정보가 어떻게 다른지 확인해 보십시오.
먼저 KubeConfig파일을 ‘admin.conf’로 변경한 후 수행 하십시오.
[root@osboxes ~]# export KUBECONFIG=~/.kube/admin.conf [root@osboxes ~]# k config set-cluster ${CLUSTER} \ --kubeconfig=${KUBECFG} \ --server=${API_FQDN} \ --certificate-authority=${CERTDIR}/ca.crt [root@osboxes ~]# k config set-context ${CONTEXT} \ --kubeconfig=${KUBECFG} \ --cluster=${CLUSTER} \ --namespace=${NS} \ --user=${USER} |
유저 등록 시 쿠버네티스에 전달할 인증토큰 정보를 만들어야 합니다.
WebHook을 직접 개발할 것이므로 인증토큰의 구조는 개발에 맞춰 마음대로 만드셔도 됩니다.
제가 제공할 예제에서는 JSON형식으로 ldap주소, 유저이름, 암호로 구성되어 있고 BASE64로 암호화 되어 있어야 합니다.
이 인증토큰은 쿠버네티스 API 서버가 WebHook에 인증 요청을 하면서 전달됩니다.
WebHook은 인증 토큰을 BASE64 디코딩하여 LDAP서버를 연결하고 전달 받은 ID와 암호로 로그인을 시도하여 그 결과를 리턴 합니다.
인증 토큰을 아래와 같이 만듭니다. JSON문자열의 키와 값은 반드시 큰따옴표로 감싸야 합니다.
“tr -d ‘\n’” 명령은 새로운 줄을 없애는 명령입니다.
[root@osboxes ~]# tokenstr="{ \"ldap\": \"${LDAP}\", \"user\": \"${DN}\", \"pw\": \"${PW}\" }" [root@osboxes ~]# token=`echo ${tokenstr} | base64 | tr -d '\n'` |
KubeConfig에 인증토큰과 같이 유저를 등록합니다.
[root@osboxes ~]# k config set-credentials ${USER} \ --kubeconfig=${KUBECFG} \ --token=${token} |
현재 컨텍스트를 셋팅 합니다.
[root@osboxes ~]# k config use-context ${CONTEXT} --kubeconfig=${KUBECFG} |
등록된 KubeConfig 파일의 내용을 확인 합니다.
[root@osboxes ~]# cat ${KUBECFG} |
3) 권한 부여
이번에는 KubeConfig를 새로 만든 파일로 전환하기 전에 권한 부터 부여하겠습니다.
현재 유저가 ‘kubernetes-admin’이므로 권한 부여 시 ‘--kubeconfig’옵션을 붙일 필요가 없습니다.
‘--user’ 파라미터의 값은 ‘${USER}’가 아니라 ‘${DN}’입니다. LDAP에 등록한 사용자의 전체 이름을 지정하여야 합니다.
[root@osboxes ~]# k create rolebinding rb_${NS}_${USER} --role=${ROLE} --user=${DN} -n ${NS} [root@osboxes ~]# k create clusterrolebinding crb_${NS}_${USER} --clusterrole=${CLUSTER_ROLE} --user=${DN} |
권한까지 부여했어도 여전히 인증이 안될겁니다.
전달된 인증 토큰을 읽어 인증을 수행할 WebHook이 없기 때문입니다.
[root@osboxes .kube]# k get po error: You must be logged in to the server (Unauthorized) |
4) WebHook 개발 위한 파이썬 설치
WebHook은 파이썬으로 개발 합니다. 물론 다른 언어로 개발하셔도 됩니다.
개발과 실행을 위해 파이썬을 먼저 설치해야 합니다.
WebHook은 NFS서버에 설치하도록 하겠습니다.
NFS서버를 로그인하고 아래 순서로 파이썬을 설치하여 주십시오.
[root@osboxes .kube]# ssh nfs Last login: Wed Feb 9 18:51:46 2022 from 223.62.219.190 [root@nfs ~]# mkdir -p ~/install && cd ~/install |
파이썬 설치에 필요한 라이브러리들을 먼저 설치 합니다.
[root@nfs install]# dnf install -y gcc openssl-devel bzip2-devel libffi-devel [root@nfs install]# dnf update -y |
설치 파일들을 다운로드 합니다. 여기서는 파이썬 3.9.9를 설치 하겠습니다.
‘https://www.python.org/ftp/python’ 에서 최신 버전을 확인하여 다운로드 하십시오.
[root@nfs install]# PYTHON_VER=3.9.9 [root@nfs install]# PYTHON_CMD=python3.9 [root@nfs install]# PIP_CMD=pip3.9 [root@nfs install]# wget https://www.python.org/ftp/python/${PYTHON_VER}/Python-${PYTHON_VER}.tgz [root@nfs install]# tar xvf Python-${PYTHON_VER}.tgz |
성능 최적화를 위한 작업을 수행 합니다. 파이썬 패키지 설치 관리자인 ‘pip’도 같이 설치 합니다.
[root@nfs install]# cd Python-${PYTHON_VER} [root@nfs Python-3.9.9]# ./configure --enable-optimizations --with-ensurepip=install |
파이썬을 설치 합니다. ‘/usr/bin’에 실행 파일이 설치 됩니다. 이 작업은 몇십분 이상 걸립니다.
[root@nfs Python-3.9.9]# make altinstall |
실행 파일들을 PATH에 추가 합니다.
[root@nfs Python-3.9.9]# install $(which ${PYTHON_CMD}) /usr/local/bin/python [root@nfs Python-3.9.9]# install $(which ${PIP_CMD}) /usr/local/bin/pip |
파이썬 버전을 확인 합니다.
[root@nfs Python-3.9.9]# python --version Python 3.9.9 |
파이썬 설치 관리자인 ‘PIP’를 업그레이드 하고 버전을 확인 합니다.
[root@nfs Python-3.9.9]# python -m pip install --upgrade pip [root@nfs Python-3.9.9]# pip --version pip 22.0.3 from /usr/local/lib/python3.9/site-packages/pip (python 3.9) |
파이썬을 모두 설치 한 후 WebHook에서 사용할 라이브러리인 ‘flask’, ‘requests’, ‘python-ldap’을 설치 합니다.
[root@nfs Python-3.9.9]# pip install flask [root@nfs Python-3.9.9]# pip install requests |
‘python-ldap’은 사전에 여러 라이브러리들을 먼저 설치해야 합니다.
‘openldap-devel’과 ‘python-devel’은 ‘dnf list’ 명령으로 정확한 라이브러리명을 확인하고 설치 하십시오.
[root@nfs Python-3.9.9]# dnf groupinstall -y "Development Tools" [root@nfs Python-3.9.9]# dnf list openldap-devel* [root@nfs Python-3.9.9]# dnf install -y openldap-devel.x86_64 [root@nfs Python-3.9.9]# dnf list python-devel* [root@nfs Python-3.9.9]# dnf install -y python-devel.x86_64 [root@nfs Python-3.9.9]# pip install python-ldap |
5) LDAP 서버 설치
LDAP서버를 워커노드에 컨테이너로 설치 합니다.
실무에서 LDAP을 파드로 설치하고 싶으면 아래 글을 참고 하십시오.
https://happycloud-lee.tistory.com/117
워커노드로 로그인 하고 LDAP을 위한 디렉토리를 만듭니다.
[root@osboxes ~]# ssh w1 … [root@worker1 ~]# mkdir -p /var/lib/ldap/data [root@worker1 ~]# mkdir -p /var/lib/ldap/conf |
LDAP을 ‘podman’을 이용하여 설치 합니다. ‘podman’은 CRI-O의 CLI툴 입니다.
[root@worker1 ~]# podman run -d -e DOMAIN=myldap.io \ -e PASSWORD=happy@cloud \ --name=myldap \ -p 389:389 \ -p 9580:9580 \ -v /var/lib/ldap/data:/var/ldap \ -v /var/lib/ldap/conf:/etc/ldap/slapd.d \ docker.io/siji/openldap:2.4.42 [root@worker1 ~]# podman ps |
작업하는 PC의 hosts에 워커노드의 퍼블릭 IP로 ‘myldap.io’를 등록 합니다.
이 작업은 LDAP 클라이언트를 웹브라우저에서 접근할 때 ‘myldap.io’를 사용하기 위한 작업이므로 굳이 안해도 됩니다.
웹브라우저를 열고 hosts에 등록을 했으면 ‘http://myldap.io:9580/phpldapadmin’으로 접근하고, 안 했으면 ‘http://{워커노드 퍼블릭 IP}:9580/phpldapadmin’으로 접근 하십시오.
좌측에서 ‘login’을 누르십시오. ‘Login DN’은 자동으로 ‘admin’계정 정보가 나옵니다. 암호를 ‘happy@cloud’로 입력하고 로그인 하십시오. 이 암호는 컨테이너 실행 시 ‘PASSWORD’ 파라미터로 지정 하였습니다.
로그인 후 OU ‘ou=users’와 유저 ‘cn=user1,ou=users,dc=myldap,dc=io’를 등록하여 주십시오.
아래 글을 참고하시면 됩니다.
https://happycloud-lee.tistory.com/172
6) WebHook 개발 및 실행
NFS 서버로 로그인하여 작업 디렉토리를 만들고 WebHook소스를 다운로드 하십시오.
[root@osboxes ~]# ssh nfs … [root@nfs ~]# mkdir -p ~/work && cd ~/work [root@nfs work]# wget https://hiondal.github.io/k8s-yaml/3.14/webhook-ldap.py |
WebHook 소스의 핵심 부분은 ‘external_auth_LDAP’함수 입니다.
아래와 같이 전달 받은 인증 토큰을 디코딩하여 LDAP주소, 유저명, 암호를 읽어 LDAP서버에 인증이 되는지 확인하여 그 결과를 리턴 합니다.
# Authentication system: LDAP def external_auth_LDAP(tokenReview): try: # Get userid and password: token is base64 encoded JSON format contains 'ldap,user,pw'. encoded_token = tokenReview['spec']['token'] base64_bytes = encoded_token.encode("ascii") string_bytes = base64.b64decode(base64_bytes) token = string_bytes.decode("ascii") # ex) '{ \"ldap\": \"ldap://169.56.70.201:389\", \"user\": \"cn=ondal,ou=users,dc=myldap,dc=io\", \"pw\": \"passw0rd\" }' print(f"TOKEN: {token}") jsonobj = json.loads(token) ldap_fqdn = jsonobj["ldap"] user = jsonobj["user"] pw = jsonobj["pw"] # Connect LDAP ldap_address = ldap_fqdn ldap_object = initialize_ldap(ldap_address) # Authenticate user ldap_result = authenticate(ldap_object, ldap_address, user, pw) print('result: %s'%(ldap_result)) |
WebHook을 실행 합니다. 중단할때는 CTRL-C를 누르면 됩니다.
[root@nfs work]# python webhook-ldap.py * Serving Flask app 'webhook-ldap' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on all addresses. WARNING: This is a development server. Do not use it in a production deployment. * Running on http://10.178.189.25:6000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 106-900-190 |
‘Running on ‘ 뒤에 나오는 WebHook 주소를 복사해 놓으십시오.
위와 같이 포그라운드ForeGround로 실행하면 터미널을 빠져나가면 실행이 중단 됩니다.
‘screen’이라는 가상 터미널 프로그램을 이용하여 백그라운드로 실행 하십시오.
‘screen’ 설치와 사용법은 아래 글을 참고 하십시오.
https://happycloud-lee.tistory.com/119
[root@nfs work]# dnf install -y screen [root@nfs work]# screen -S webhook-ldap [root@nfs ~]# cd work [root@nfs work]# python webhook-ldap.py * Serving Flask app 'webhook-ldap' (lazy loading) … |
가상 터미널에서 WebHook실행 후 ‘CTRL-ad’를 눌러 가상 터미널을 빠져 나갑니다.
… [detached from 13453.webhook-ldap] [root@nfs work]# |
7) API 서버에 WebHook 등록
API서버가 WebHook을 호출할 수 있도록 API 서버 설정에 추가 합니다.
이를 위해서는 WebHook정보를 담은 야믈 파일을 먼저 만들어야 합니다.
컨트롤 플레인에 로그인하고 ‘/etc/kubernetes/pki’디렉토리로 이동하여 WebHook 정의 야믈 파일을 다운로드 하십시오.
[root@nfs work]# exit [root@osboxes ~]# ssh m … [root@master ~]# cd /etc/kubernetes/pki [root@master pki]# wget https://hiondal.github.io/k8s-yaml/3.14/webhook.yaml |
파일을 열고 ‘clusters.cluster.server’의 값을 위 WebHook 실행 했을때 결과 화면에 나온 WebHook 주소로 바꾸 십시오.
apiVersion: v1 kind: Config clusters: - name: flask-auth cluster: server: http://10.178.189.25:6000/ # https://<ADDR>:<PORT> 형식 insecure-skip-tls-verify: true # tls 설정 disable users: - name: kube-apiserver contexts: - context: cluster: flask-auth user: kube-apiserver name: auth current-context: auth |
쿠버네티스 API 서버의 설정 파일인 ‘/etc/kubernetes/manifests/kube-apiserver.yaml’을 열고 아래와 같이 WebHook 옵션을 추가 하십시오.
[root@master pki]# cd /etc/pki/manifests [root@master manifests]# vim kube-apiserver.yaml |
… spec: containers: - command: - kube-apiserver - --advertise-address=169.56.70.197 … - --authentication-token-webhook-config-file=/etc/kubernetes/pki/webhook.yaml … |
8) 인증/인가 테스트
이제 KubeConfig 파일을 바꾸고 다시 테스트 하면 정상적으로 파드 리스트가 나올 겁니다.
[root@master manifests]# exit [root@osboxes ~]# export KUBECONFIG=~/.kube/config-webhook [root@osboxes ~]# k get po NAME READY STATUS RESTARTS AGE member-59d75b86ff-9xbl5 1/1 Running 0 3d19h recommend-67445ccb4f-4vt5m 1/1 Running 0 3d19h |
쿠버네티스 OpenAPI로도 테스트 해 보겠습니다.
서비스 어카운트와 마찬가지로 요청 HTTP 헤더 ‘Authorization’에 ‘Bearer {인증토큰}’을 넘기면 됩니다.
인증토큰은 위에서 만든 ‘token’변수를 이용하면 됩니다.
[root@osboxes ~]# curl -k -H "Authorization: Bearer ${token}" ${API_FQDN}/api/v1/namespaces/${NS}/pods |
지금까지 만든 KubeConfig파일을 아래와 같이 환경변수 KUBECONFIG에 정의하여 사용할 수 있습니다.
[root@osboxes ~]# export KUBECONFIG=~/.kube/config-sa:~/.kube/config-x509:~/.kube/config-webhook [root@osboxes ~]# k config view |
아래와 같이 KubeConfig파일에 설정된 값이 합쳐져서 사용할 수 있게 됩니다.
apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://169.56.70.197:6443 name: happycloud contexts: - context: cluster: happycloud namespace: ott user: ott-admin name: admin@ott - context: cluster: happycloud namespace: ott user: sa-cicd name: sa@ott - context: cluster: happycloud namespace: ott user: user2 name: user@ott current-context: sa@ott kind: Config preferences: {} users: - name: ott-admin user: client-certificate-data: REDACTED client-key-data: REDACTED - name: sa-cicd user: token: REDACTED - name: user1 user: token: REDACTED - name: user2 user: token: REDACTED |
특정 컨텍스트로 바꾸시려면 ‘kubectl config use-context’명령을 사용합니다.
[root@osboxes ~]# k config use-context sa@ott |
현재 컨텍스트에서 클러스터, 유저, 네임스페이스를 바꾸려면 아래와 같이 하면 됩니다.
[root@osboxes ~]# k config set-context --current --cluster=happycloud Context "sa@ott" modified. [root@osboxes ~]# k config set-context --current --user=sa-cicd Context "sa@ott" modified. [root@osboxes ~]# k config set-context --current --namespace=ott Context "sa@ott" modified. |
더 자세한 사용법은 ‘kubectl config --help’명령으로 도움말을 참고 하십시오.
쿠버네티스 쉽게 이해하기 시리즈 목차
[쿠버네티스 쉽게 이해하기 1] 쿠버네티스 설치하기
[쿠버네티스 쉽게 이해하기 2] 쿠버네티스 아키텍처
[쿠버네티스 쉽게 이해하기 3] 한장으로 이해하는 쿠버네티스 리소스
[쿠버네티스 쉽게 이해하기 4] 쿠버네티스 개발에서 배포까지 실습
[쿠버네티스 쉽게 이해하기 5] 쿠버네티스 오브젝트 정의 파일 쉽게 만들기
[쿠버네티스 쉽게 이해하기 6] 꼭 알아야 할 쿠버네티스 주요 명령어
[쿠버네티스 쉽게 이해하기 7] 파드 실행 및 통제를 위한 워크로드 컨트롤러
[쿠버네티스 쉽게 이해하기 8] 파드 로드 밸런서 서비스
[쿠버네티스 쉽게 이해하기 9] 서비스 로드 밸런서 인그레스
[쿠버네티스 쉽게 이해하기 10] 환경변수 컨피그맵과 시크릿
[쿠버네티스 쉽게 이해하기 11] 데이터 저장소 사용을 위한 PV/PVC
[쿠버네티스 쉽게 이해하기 12] 헬스 체크를 위한 스타트업 프로브, 라이브니스 프로브, 레디니스 프로브
[쿠버네티스 쉽게 이해하기 13] 통합 로깅을 위한 EFK 스택
[쿠버네티스 쉽게 이해하기 14] 인증Authentication과 알백RBAC 방식의 인가Authorization
[쿠버네티스 쉽게 이해하기 15] 더 알면 좋을 주제들: 무중단 배포, 모니터링, HPA