Security - Service Account

2026. 1. 2. 16:53·CKA

Kubernetes에는 계정이 크게 2종류가 있습니다.

  • User Account: 사람이 쓰는 계정(관리자/개발자 등)
  • ServiceAccount: 파드 안에서 돌아가는 프로세스(=기계/애플리케이션) 가 쓰는 계정

특히 Kubernetes는 User는 클러스터 전역(네임스페이스와 무관) 개념이고, ServiceAccount는 네임스페이스 범위(Namespaced) 라는 점이 실무에서 중요합니다. (Kubernetes)


1) ServiceAccount는 언제 쓰나?

ServiceAccount는 “클러스터 안/밖의 애플리케이션이 Kubernetes API를 호출해야 할 때” 사용합니다.

  • Prometheus: API를 폴링해서 메트릭/리소스 정보를 수집
  • Jenkins/CI-CD: 배포 자동화(Deployment 생성/업데이트 등)
  • 사내/커스텀 대시보드: “Pod 목록을 조회해서 화면에 보여주는” 같은 기능

결국 핵심은: Kubernetes API를 호출하려면 인증이 필요하고, 그 인증 주체로 ServiceAccount를 쓴다 입니다.


2) ServiceAccount 토큰이 하는 일 (Bearer Token)

ServiceAccount는 “정체성(Identity)”이고, 이 정체성을 API 서버에 증명하는 값이 토큰(Token) 입니다.

API 호출할 때는 보통 HTTP 헤더로 전달합니다.

curl -H "Authorization: Bearer <TOKEN>" https://<apiserver>/api/v1/pods

3) 기본(default) ServiceAccount와 “자동 연결”

Kubernetes는 기본적으로 각 네임스페이스에 default ServiceAccount를 가지고 있습니다.
그리고 Pod를 만들 때 serviceAccountName을 지정하지 않으면 기본적으로 default SA가 연결됩니다.

확인:

kubectl get sa -n default
kubectl describe sa default -n default

kubectl get pod <pod> -n default -o yaml | grep -i serviceAccount
kubectl describe pod <pod> -n default | grep -i "Service Account"

4) Pod 안에 토큰이 “어디에” 생기나? (Projected Volume)

Pod에 ServiceAccount가 연결되면, Kubernetes는 토큰을 파드 내부에 마운트해 줍니다. 보통 경로는:

/var/run/secrets/kubernetes.io/serviceaccount

안에는 보통 이런 파일들이 있습니다.

  • token (JWT 형태 토큰)
  • ca.crt (API 서버 CA)
  • namespace (현재 네임스페이스)

Pod 안에서 확인:

kubectl exec -n default <pod> -- ls -al /var/run/secrets/kubernetes.io/serviceaccount
kubectl exec -n default <pod> -- cat /var/run/secrets/kubernetes.io/serviceaccount/namespace

최신 Kubernetes에서는 이 토큰이 TokenRequest 기반의 “수명 제한 토큰”이고, projected volume로 마운트되며, Pod가 삭제되면 토큰도 자동으로 무효화됩니다. (Kubernetes)


5) 왜 커스텀 ServiceAccount가 필요하나?

default ServiceAccount는 보통 권한이 제한적입니다(특히 RBAC가 켜져 있으면 더더욱).
따라서 특정 애플리케이션이 Kubernetes API를 호출해야 한다면:

  1. 전용 ServiceAccount 생성
  2. 필요 최소 권한만 RBAC로 부여
  3. Pod에 그 SA를 연결

이 패턴이 정석입니다.


6) ServiceAccount 만들기 (명령형/선언형)

명령형

kubectl create serviceaccount dashboard-sa -n default
kubectl get sa -n default
kubectl describe sa dashboard-sa -n default

선언형(YAML)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-sa
  namespace: default
kubectl apply -f sa.yaml

7) Pod에 ServiceAccount 연결하기

Pod(또는 Deployment) 스펙에 serviceAccountName을 지정합니다. (Kubernetes)

apiVersion: v1
kind: Pod
metadata:
  name: dashboard
  namespace: default
spec:
  serviceAccountName: dashboard-sa
  containers:
    - name: app
      image: your-dashboard-image:latest

주의: .spec.serviceAccountName은 Pod 생성 시점(또는 템플릿)에서만 설정할 수 있고, 이미 생성된 Pod에서 바꾸는 것은 불가합니다. (Kubernetes)


8) (중요) RBAC로 “최소 권한” 부여하기

예: 대시보드가 default 네임스페이스의 Pod 목록만 읽으면 된다면:

Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: dashboard-reader
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

RoleBinding (ServiceAccount에 연결)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dashboard-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: dashboard-sa
    namespace: default
roleRef:
  kind: Role
  name: dashboard-reader
  apiGroup: rbac.authorization.k8s.io

적용:

kubectl apply -f role.yaml
kubectl apply -f rolebinding.yaml

권한 점검:

kubectl auth can-i list pods -n default --as=system:serviceaccount:default:dashboard-sa

9) 토큰 자동 마운트를 막고 싶다면: automountServiceAccountToken: false

API를 전혀 호출하지 않는 앱인데 “혹시 모를 토큰 노출”을 줄이고 싶다면 자동 마운트를 끌 수 있습니다.

(A) ServiceAccount 레벨에서 끄기

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-sa
  namespace: default
automountServiceAccountToken: false

(B) Pod 레벨에서 끄기 (더 우선 적용하고 싶을 때)

apiVersion: v1
kind: Pod
metadata:
  name: dashboard
  namespace: default
spec:
  serviceAccountName: dashboard-sa
  automountServiceAccountToken: false
  containers:
    - name: app
      image: your-dashboard-image:latest

10) “클러스터 밖”에서 쓸 토큰 만들기: kubectl create token

외부 대시보드, CI/CD 도구, 외부 모니터링 등에서 토큰을 직접 넣어야 하는 경우가 있습니다.
이때는 ServiceAccount에 대해 시간 제한 토큰을 발급받습니다.

kubectl create token dashboard-sa -n default
kubectl create token dashboard-sa -n default --duration 24h
  • --duration으로 만료 시간을 요청할 수 있지만, 최종 만료 시간은 서버 정책에 따라 달라질 수 있습니다. (Kubernetes)
  • 이 방식은 TokenRequest 기반이며, 예전처럼 “자동으로 Secret에 장기 토큰이 생성되는 방식”이 기본이 아닙니다. (Kubernetes)

토큰으로 API 호출 예시

가능하면 -k(TLS 검증 생략) 대신 CA를 쓰는 게 안전합니다. (클러스터 내부라면 ca.crt가 마운트되어 있음)

TOKEN="$(kubectl create token dashboard-sa -n default --duration 10m)"
APISERVER="https://<apiserver>:6443"

curl --cacert /path/to/ca.crt \
  -H "Authorization: Bearer ${TOKEN}" \
  "${APISERVER}/api/v1/namespaces/default/pods"

11) (옵션) JWT 토큰 내용 확인(만료/주체 등)

ServiceAccount 토큰은 JWT인 경우가 많습니다. payload를 간단히 보면 “어떤 SA인지, 언제 만료되는지”를 확인할 수 있습니다.

TOKEN="$(kubectl create token dashboard-sa -n default --duration 10m)"

python - <<'PY'
import os, json, base64
t = os.environ["TOKEN"].split(".")[1]
t += "=" * (-len(t) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(t)), indent=2, ensure_ascii=False))
PY

12) (주의) “만료 없는 장기 토큰”이 꼭 필요하다면? (Secret 기반)

문서상으로는 kubernetes.io/service-account-token 타입 Secret을 만들어 장기 토큰을 만들 수도 있습니다. 다만 권장 경로는 TokenRequest(=짧은 토큰) 입니다. (Kubernetes)

kubectl apply -n default -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: dashboard-sa-token
  annotations:
    kubernetes.io/service-account.name: dashboard-sa
type: kubernetes.io/service-account-token
EOF

장기 토큰은 유출 시 리스크가 커서, 가능하면 kubectl create token(시간 제한 토큰) + 주기적 재발급/회전 방식이 안전합니다.


13) “어떤 클러스터에 생성되나?” (클러스터 지정은 YAML이 아니라 kubeconfig)

ServiceAccount/Role/RoleBinding 등은 YAML 안에 “대상 클러스터”를 지정하는 필드가 없습니다.
어느 클러스터에 적용되는지는 kubectl이 현재 바라보는 컨텍스트(클러스터)로 결정됩니다.

kubectl config current-context
kubectl config get-contexts
kubectl --context <context-name> apply -f sa.yaml

요약

  • ServiceAccount는 “파드(애플리케이션)가 Kubernetes API에 접근할 때 쓰는 ID”다.
  • 토큰은 그 ID를 증명하는 Bearer Token이며, 최신 Kubernetes에서는 TokenRequest 기반 단기 토큰 + projected volume 마운트가 기본 흐름이다. (Kubernetes)
  • 기본 SA가 자동 연결되지만, 실무에서는 전용 SA + 최소 RBAC 권한 + 필요 시 automount 끄기가 표준이다.
  • 클러스터 밖에서 쓸 토큰은 kubectl create token으로 발급한다. (Kubernetes)

 

 

Practice Test: https://uklabs.kodekloud.com/topic/practice-test-service-accounts-2/

'CKA' 카테고리의 다른 글

Security - 도커 보안 기초 + 쿠버네티스의 Security Context  (0) 2026.01.02
Security - Secret of Docker Registry  (0) 2026.01.02
Security - ClusterRole / ClusterRoleBinding  (0) 2026.01.02
Security - Authorization(RBAC)  (0) 2026.01.01
Security - API Groups  (0) 2026.01.01
'CKA' 카테고리의 다른 글
  • Security - 도커 보안 기초 + 쿠버네티스의 Security Context
  • Security - Secret of Docker Registry
  • Security - ClusterRole / ClusterRoleBinding
  • Security - Authorization(RBAC)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      조회 성능 최적화
      양방향 맵핑
      프록시 팩토리
      고급
      프록시
      gesingleresult
      스레드
      typequery
      JPQL
      cglib
      @within
      버퍼
      @discriminatorvalue
      hibernate5module
      jpq
      requset scope
      페치 조인
      @args
      Target
      log trace
      @discriminatorcolumn
      빈 후처리기
      Thread
      자바
      김영한
      reentarantlock
      단방향 맵핑
      jdk 동적 프록시
      락
      WAS
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Security - Service Account
    상단으로

    티스토리툴바