본문 바로가기

Computer Science/Kubernetes(CKA) 자격증 준비

Kubernetes 정리 165: Service Accounts

Kubernetes에는 사용자 계정과 서비스 계정이라는 두 가지 유형의 계정이 있습니다. 이미 알고 계시겠지만 사용자 계정은 사람이 사용하고 서비스 계정은 기계가 사용합니다.

사용자 계정은 관리 작업을 수행하기 위해 클러스터에 액세스하는 관리자 또는 애플리케이션을 배포하기 위해 클러스터에 액세스하는 개발자 등을 위한 것입니다. 서비스 계정은 Kubernetes 클러스터와 상호 작용하기 위해 애플리케이션에서 사용하는 계정입니다. 예를 들어 Prometheus와 같은 모니터링 애플리케이션은 서비스 계정을 사용하여 성능 메트릭을 위해 Kubernetes API를 가져옵니다. Jenkins와 같은 자동화된 빌드 tool은 서비스 계정을 사용하여 Kubernetes 클러스터에 애플리케이션을 배포합니다. 
예를 들어 보겠습니다. 저는 "My Kubernetes Dashboard"라는 간단한 Kubernetes 대시보드 애플리케이션을 구축했습니다. Python으로 구축된 간단한 애플리케이션이며 배포 시 Kubernetes API에 요청을 전송하여 Kubernetes 클러스터의 파드 목록을 검색하고 웹페이지에 표시하는 것이 전부입니다. 내 애플리케이션이 Kubernetes API를 쿼리하려면 인증을 받아야 합니다. 이를 위해 서비스 계정을 사용합니다.

서비스 계정을 생성하려면 kubectl create serviceaccount 커맨드를 실행한 다음 계정 이름(이 경우에는 dashboard-sa)을 입력합니다. kubectl에서 서비스 계정을 보려면 kubectl get serviceaccount 커맨드를 사용하세요. 그러면 모든 서비스 계정이 조회됩니다. 

서비스 계정이 생성되면 토큰도 자동으로 생성됩니다. 서비스 계정 토큰은 Kubernetes API에 인증하는 동안 외부 애플리케이션에서 사용해야 하는 것입니다. 그러나 토큰은 secret 오브젝트로 저장됩니다. 지금은 dashboard-sa-token-kbbdm이라는 이름입니다. 
따라서 서비스 계정을 만들 때 먼저 서비스 계정 오브젝트를 만든 다음, 서비스 계정에 대한 토큰을 생성합니다. 그런 다음 secret 오브젝트를 만들고 secret 오브젝트 내부에 해당 토큰을 저장합니다. 그리고 secret 오브젝트가 서비스 계정에 연결됩니다. 토큰을 보려면 kubectl describe secret 커맨드를 실행하여 secret 오브젝트를 봅니다.

예를 들어 curl을 사용하는 이 간단한 예에서 Kubernetes API에 대한 risk call을 수행하는 동안 bearer token을 인증 헤더로 제공할 수 있습니다.  애플리케이션의 경우엔 토큰을 복사하여 토큰 필드에 붙여넣어 대시보드 애플리케이션을 인증합니다. 
이렇게 해서 새로운 서비스 계정을 생성하고 사용합니다. 서비스 계정을 생성하고, 롤 기반 액세스 제어 메커니즘을 사용하여 올바른 권한을 할당할 수 있지만, 이는 이 과정의 범위를 벗어납니다. 서비스 계정 토큰을 내보내고 이를 사용하여 Kubernetes API에 인증하도록 타사 애플리케이션을 구성할 수도 있습니다. 
하지만 타사 애플리케이션이 Kubernetes 클러스터 자체에서 호스팅된다면 어떨까요? 예를 들어 Kubernetes 클러스터 자체에 배포된 My Kubernetes Dashboard 애플리케이션 또는 Prometheus 애플리케이션을 가질 수 있습니다. 이 경우 서비스 계정 토큰을 내보내고 이를 사용하도록 타사 애플리케이션을 구성하는 이 전체 프로세스는, 서비스 토큰 암호를 타사 애플리케이션을 호스팅하는 파드 내부의 볼륨으로 자동 마운트하여 간단하게 만들 수 있습니다. 

이렇게 하면 Kubernetes API에 액세스하기 위한 토큰이 이미 파드 내부에 배치되어 애플리케이션에서 쉽게 읽을 수 있습니다. 수동으로 제공할 필요가 없습니다. 
돌아가서 서비스 계정 목록을 보면 이미 존재하는 default 서비스 계정이 있음을 알 수 있습니다. Kubernetes의 모든 네임스페이스에 대해 default라는 서비스 계정이 자동으로 생성됩니다. 각 네임스페이스에는 고유한 default 서비스 계정이 있습니다. 파드가 생성될 때마다 default 서비스 계정과 해당 토큰이 볼륨 마운트로 해당 파드에 자동으로 마운트됩니다. 예를 들어 my-kubernetes-dashboard 이미지를 사용하여 파드를 생성하는 간단한 파드 definition 파일이 있습니다.

 definition 파일에 secret 또는 볼륨 마운트를 지정하지 않았습니다. 그러나 파드가 생성되고, kubectl describe pod 커맨드를 실행하여 파드의 세부 정보를 보면 default 토큰이라는 시크릿에서 자동으로 볼륨이 생성되는 것을 볼 수 있습니다. 
secret 토큰은 var/run/secrets/kubernetes.io/serviceaccount 위치에 마운트됩니다. 따라서 Pod 내부에서 ls 커맨드를 실행하여 디렉토리의 콘텐츠를 조회하면 secret이 세 개의 개별 파일로 마운트된 것을 볼 수 있습니다. 

 

실제 토큰이 있는 파일은 token이라는 파일입니다. 해당 파일의 내용을 보면 Kubernetes API에 액세스하는 데 사용되는 토큰이 표시됩니다. 
이제 default 서비스 계정은 매우 제한적이라는 점을 기억하세요. default Kubernetes API 쿼리를 실행할 수 있는 권한만 있습니다. 방금 만든 것과 같은 다른 서비스 계정을 사용하려면 서비스 계정을 포함하도록 파드 definition 파일을 수정하고 새 서비스 계정의 이름을 지정합니다. 기존 파드의 서비스 계정은 편집할 수 없습니다. 파드를 삭제하고 다시 생성해야 합니다. 그러나 deployment의 경우 파드 definition 파일을 변경하면 배포에 대한 새 롤아웃이 자동으로 트리거되므로 서비스 계정을 사용할 수 있습니다. 따라서 배포는 올바른 서비스 계정으로 새 파드를 삭제하고 다시 생성하는 작업을 처리합니다. 

명시적으로 지정하지 않은 경우 Kubernetes는 자동으로 default 서비스 계정을 마운트합니다. pod의 spec섹션에서 자동 마운트 서비스 계정 토큰 필드를 false로 설정하여 서비스 계정을 자동으로 마운트하지 않도록 선택할 수 있습니다. 

 

이제 릴리스 버전 1.22와 1.24에서 변경된 서비스 계정, 암호 및 토큰의 작동 방식의 몇 가지 사항에 대해 설명하겠습니다. 이전에 설명한 것처럼 모든 네임스페이스에는 default 서비스 계정이 있고 해당 서비스 계정에는 연결된 토큰이 있는 secret 오브젝트가 있습니다. 파드가 생성되면 자동으로 서비스 계정을 파드에 연결하고 토큰을 파드 내의 잘 알려진 위치에 마운트합니다. 이 경우 var/run/secrets/kubernetes.io/serviceaccount 아래에 있습니다. 이렇게 하면 파드 내에서 실행되고 해당 프로세스가 Kubernetes API를 쿼리할 수 있도록 하는 프로세스에 토큰에 액세스할 수 있습니다.