안녕하세요! 오늘은 쿠버네티스 보안의 기본이자 핵심인 Service Account(서비스 어카운트)에 대해 깊이 파헤쳐 보려 합니다.
단순히 "파드(Pod)에 권한 줄 때 쓰는 거 아니야?"라고 알고 계셨다면, 오늘 포스팅을 통해 조금 더 깊은 내용을 가져가실 수 있습니다. 특히 최근 쿠버네티스 버전에서 표준이 된 Projected Volume과 Bound Token 개념은 보안 측면에서 매우 중요하기 때문에 꼭 이해하고 넘어가야 합니다.
10분만 투자해서 쿠버네티스 인증 구조의 핵심을 마스터해 보세요! 🚀

1. Service Account(SA): 파드를 위한 신분증 🪪
우리가 회사 건물에 들어갈 때 사원증을 찍듯이, 쿠버네티스 클러스터 내부에서 파드(Pod) 내의 애플리케이션이 API 서버와 소통하려면 신분증이 필요합니다. 이것이 바로 Service Account입니다.
👤 User Account vs. 🤖 Service Account
- User Account: 사람(Human)을 위한 계정입니다. (관리자, 개발자 등). 주로 전역적(Global)으로 관리되며, AWS IAM이나 Google 계정 등 외부 시스템과 연결됩니다.
- Service Account: 프로세스(Bot)를 위한 계정입니다. 네임스페이스(Namespace)에 종속된다는 점이 가장 큰 특징입니다.
파드를 생성할 때 별도로 지정하지 않으면, 쿠버네티스는 자동으로 해당 네임스페이스의 default 서비스 어카운트를 할당합니다.
2. 과거의 방식: "영원히 썩지 않는 열쇠" (Legacy) 🗝️
예전(Legacy) 방식에서는 서비스 어카운트를 생성하면 자동으로 Secret(시크릿) 리소스가 만들어졌습니다. 그리고 이 시크릿 안에는 만료 기한이 없는(No Expiration) 토큰이 들어있었죠.
이 방식은 치명적인 단점이 있었습니다.
- 보안 취약: 토큰을 한 번 탈취당하면, 관리자가 수동으로 폐기하기 전까지 해커가 영원히 사용할 수 있습니다.
- 관리 불편: 토큰을 교체(Rotation) 하려면 시크릿을 지우고 다시 만드는 번거로운 작업이 필요했습니다.
그래서 쿠버네티스 커뮤니티는 Projected Volume이라는 새로운 기술을 도입하게 됩니다.
3. 현재의 표준: Projected Volume과 "살아있는 토큰" ✨
최신 쿠버네티스에서는 토큰을 정적인 Secret에 저장하지 않습니다. 대신 Projected Volume을 이용해 파드가 생성되는 그 순간에 API 서버로부터 "임시 토큰"을 발급받아 파드에 꽂아줍니다.
📽️ 왜 이름이 "Projected(투영된)" 인가요?
일반적인 볼륨 마운트가 하나의 저장소를 연결하는 것이라면, Projected Volume은 여러 소스(Source)를 한 곳의 디렉터리에 모아서(투영해서) 보여주는 기술이기 때문입니다.
보통 다음 세 가지 정보를 한 폴더(/var/run/secrets/kubernetes.io/serviceaccount)에 섞어서 보여줍니다.
- serviceAccountToken: 인증을 위한 JWT 토큰
- configMap (kube-root-ca.crt): API 서버 신뢰를 위한 인증서
- downwardAPI: 파드의 네임스페이스 정보
4. 핵심 기술: Bound Service Account Token 🔗
Projected Volume을 통해 주입되는 토큰은 Bound Token이라고 부릅니다. 어딘가에 강력하게 "묶여(Bound)" 있기 때문입니다. 이 개념이 보안의 핵심입니다.
① Time Bound (시간 제한) ⏳
이 토큰은 유효기간이 있습니다 (기본 1시간).
- Legacy: 유효기간 없음.
- Modern: expirationSeconds가 설정됨.
② Object Bound (파드 종속) 📦
이 토큰은 발급된 특정 파드(Pod UID)와 운명을 같이 합니다.
- 파드가 삭제되면 토큰도 즉시 무효화됩니다.
- 공격자가 토큰을 복사해서 다른 파드에서 쓰려고 해도, 토큰 내부의 정보와 실행 환경이 일치하지 않으면 거부될 수 있습니다.
③ Audience Bound (사용처 제한) 🎯
토큰에 aud(Audience) 필드를 설정할 수 있습니다.
- "이 토큰은 AWS 인증용이야"라고 발급받았다면, 이 토큰으로 쿠버네티스 API 서버를 해킹하려 해도 "어? 넌 AWS용이잖아?" 하고 거부합니다.
- Istio 같은 서비스 메시가 이 기능을 적극 활용하여 서비스 간 인증을 수행합니다.
5. YAML 파일 뜯어보기 📝
여러분의 파드 YAML 파일 맨 아래쪽을 보면, kubelet이 자동으로 추가한 다음과 같은 설정을 볼 수 있습니다.
YAML
volumes:
- name: kube-api-access-xxxxx
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607 # 👈 1시간 뒤 만료!
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
이 설정 덕분에 파드 내부의 애플리케이션은 /var/run/secrets/kubernetes.io/serviceaccount/token 파일을 읽어서 안전하게 통신할 수 있는 것입니다.
6. 토큰이 만료되면 앱은 죽나요? (Token Rotation) 🔄
"1시간 뒤에 만료된다면, 내 서비스도 1시간 뒤에 멈추나요?"
아니요! 걱정하지 마세요.
Kubelet이 아주 부지런하게 움직입니다.
- 토큰 만료 시간이 다가오면 Kubelet이 자동으로 API 서버에 새 토큰을 요청합니다.
- 그리고 파드 내부에 마운트 된 token 파일을 새로운 토큰 값으로 덮어쓰기(Update) 합니다.
- 애플리케이션(대부분의 K8s 클라이언트 라이브러리)은 주기적으로 파일을 다시 읽어서 토큰을 갱신합니다.
⚠️ 주의할 점: 직접 애플리케이션을 개발한다면, 토큰 파일을 처음에만 읽고 끝내는 것이 아니라 주기적으로 다시 읽는 로직(Reload)을 구현해야 합니다. (Go 클라이언트 등 표준 라이브러리는 이미 구현되어 있습니다.)
7. 정리하며 🎁
오늘 내용을 세 줄로 요약해 보겠습니다.
- Service Account는 파드가 쿠버네티스 API와 대화하기 위한 신분증이다.
- 보안을 위해 Projected Volume 방식을 사용하여, 수명이 짧고 자동 갱신되는 토큰(Bound Token)을 사용한다.
- 이 토큰은 파드와 운명을 같이하며, 특정 파드에 묶여(Bound) 있어 탈취되어도 위험이 적다.
이제 kubectl get pod -o yaml을 쳤을 때 나오는 복잡한 projected 구문이 두렵지 않으시죠? 이것은 여러분의 클러스터를 안전하게 지키기 위한 쿠버네티스의 세심한 배려랍니다. 🛡️
오늘도 안전하고 즐거운 쿠버네티스 생활 되세요!
'클라우드 > 쿠버네티스' 카테고리의 다른 글
| 🚀 클라우드 네이티브의 핵심, 개발자 포털(Developer Portal) 입문 가이드: 자율성과 효율성의 균형 잡기 (0) | 2025.12.21 |
|---|---|
| 🚀 마이크로서비스로 가는 가장 안전한 징검다리: 왜 '모듈러 모놀리스'를 거쳐야 할까? (0) | 2025.12.20 |
| [클라우드/Network] GKE의 34.x 대역과 EKS의 100.64.x 대역, 도대체 정체가 뭘까? 🕵️♂️☁️ (0) | 2025.12.19 |
| [Kubernetes] 파드를 3개나 띄웠는데 왜 한 노드에만 몰릴까? (스케줄러의 비밀) 🧐 (0) | 2025.12.19 |
| 🏗️ [쿠버네티스] 파드에 디스크를 직접 연결하면 안 되는 이유 (PV, PVC, SC의 필요성) (0) | 2025.12.11 |