Service Account
Service Account
개념
- 이전까지는 사람이 클러스터에 접근할 때, 인증서 등의 방법으로 접근하는 방식을 다루었다.
ServiceAccount는 사람 외의 리소스(예: 봇, 애플리케이션)이 쿠버네티스 API와 통신할 때 사용하는 리소스이다.- 예:
Prometheus: 클러스터 성능 지표를 수집하기 위해 API 서버와 통신Jenkins: 애플리케이션 배포를 위해 클러스터에 접근할 때 API 서버와 통신
팁
User(쿠버네티스 리소스는 아님)와 ServiceAccount는 각각 'Authentication(인증)' 방식은 인증서 vs 토큰으로 다르지만, 'Authorization(인가)' 단계에서는 똑같이 Role/ClusterRole - RoleBinding/ClusterRoleBinding 방식의 RBAC를 사용한다.
인증 방식 (토큰)
- User의 경우 인증서, Static Token File 과 같은 방식으로 인증하였다.
- 하지만,
ServiceAccount는 Token을 통해 인증한다.- 여기서의 Token은 JWT 기반 토큰으로, Static Token File과는 다르다.
ServiceAccount는 API 서버와 통신시 HTTP 헤더에Bearer Token으로 포함하여 전송한다.
기본 동작
- 쿠버네티스 클러스터가 생성되면 기본적으로 모든 네임스페이스에
default라는 이름의ServiceAccount가 생성된다. (제한적인 권한)
- 자동 할당
Pod가 생성될 때, 별도의ServiceAccount를 지정하지 않는다면,defaultServiceAccount가 할당된다.default는 권한이 제한적이므로 특정 권한이 필요한 경우 별도의 서비스 어카운트를 생성해서 관련 권한에 바인딩해야한다.
- 토큰 마운트
- 쿠버네티스는 자동으로 토큰을 생성하여
Pod내부의Projected Volume에 마운트한다.Projected Volume은Secret,ConfigMap,serviceAccountToken등의 리소스를 동일한 디렉토리에 보관하는 'Pod내부 볼륨'이라고 생각하면 된다.- 경로:
/var/run/secrets/kubernetes.io/serviceaccount/token
- 쿠버네티스는 자동으로 토큰을 생성하여
팁
- 토큰은 유효기간이 있는데, 이건 누가 자동갱신하나요?
kubelet이ServiceAccount를 감시하며, 토큰이 만료되기 전에 갱신한다.
생성
Service Account
Imperative
kubectl create serviceaccount dashboard-sa
- yaml 로 생성할 수도 있지만, 넣을 리소스가 많지 않기 때문에 그냥 위처럼 imperative하게 생성하는 것이 빠르다.
Declarative(YAML)
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-sa
namespace: default
automountServiceAccountToken: false
- 하지만, git 등으로 관리해야할 경우 yaml로 저장하는 것이 좋다.
- 만약 토큰이 자동으로 마운트되는 것을 원치않는다면
automountServiceAccountToken: false로 지정하면 된다. (기본값이true)- 주로 정적 웹서버, Job 등의 경우 API 서버와의 통신이 아예 불필요하므로 이 설정을 하는 것이 보안상 좋다.
Pod에 할당
apiVersion: v1
kind: Pod
metadata:
name: my-dashboard-pod
spec:
serviceAccountName: dashboard-sa # 여기에 서비스 어카운트 이름 지정
containers:
- name: my-dashboard
image: my-dashboard-image
automountServiceAccountToken: false
Pod에ServiceAccount를 할당할 때는spec.serviceAccountName필드에 지정하면 된다.automountServiceAccountToken옵션은Pod레벨에서도 지정 가능하다.
외부 접속을 위한 토큰 생성
- CI/CD 툴이나 외부 모니터링 도구처럼 클러스터 외부에서 접속해야 할 때는 수동으로 토큰을 생성해서 이 토큰으로
ServiceAccount의 권한을 가지고 클러스터에 접근해야한다.
kubectl create token <serviceAccount이름>
- 위 명령어로 토큰 값을 출력할 수 있다.
- 기본 유효기간은 1시간이며,
--duration플래그로 연장할 수 있다.
팁
- 근데, 외부에서 토큰을 사용할 경우
kubelet이 자동 갱신하지 못하는데, CI/CD 툴이나 외부 모니터링 도구를 사용할 때 위처럼 토큰을 발급받아서 사용한다면 수동으로 갱신해야하는건가? AWS Secret Manager등의 외부 보안 볼트 시스템을 사용하여 토큰을 안전하게 보관하고, 외부 툴은 이 볼트 시스템에 접근하여 토큰을 사용한다.cron job,AWS Lambda등으로 주기적으로 클러스터에 접근하여 새로운 토큰을 발급받는다.
- 이로써 토큰 수명을 짧게 유지함 + 최소 권한 원칙을 동시에 만족시킬 수 있다.
쿠버네티스 버전별 변화
| 구분 | ~ v1.21 (과거) | v1.22 ~ v1.23 (과도기) | v1.24+ (현재) |
|---|---|---|---|
| 서비스 어카운트 생성 시 | 영구 토큰(Secret 객체 형태) 자동 생성됨 | 영구 토큰(Secret) 자동 생성됨 (하지만 파드는 이걸 안 씀) | 영구 토큰(Secret) 생성 안 됨 |
| 파드에 마운트되는 것 | 자동 생성된 Secret | TokenRequest로 받은 단기 토큰 (Projected Volume) | TokenRequest로 받은 단기 토큰 (Projected Volume) |
| 외부 접속용 토큰 | 생성된 Secret 값 복사해서 사용 | 생성된 Secret 값 복사해서 사용 | kubectl create token 명령어로 직접 발급 |
레퍼런스
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- Udemy - Certified Kubernetes Administrator (CKA) with Practice Tests (Mumshad)