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를 호출해야 한다면:
- 전용 ServiceAccount 생성
- 필요 최소 권한만 RBAC로 부여
- 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 |