가시다님께서 진행하신 CI/CD 스터디 추가 실습 내용을 기반으로 작성했다.
CI/CD 스터디에서 HashiCorp Vault를 이용해 시크릿 관리와 Kubernetes 연동을 실습했다.
이 글에서는 그때 정리한 내용을 바탕으로 다음 내용을 한 번에 훑어본다.
- 왜 이제는 “시크릿 관리 도구”가 필수인지
- HashiCorp Vault가 무엇을 해결해 주는지
- Kind 기반 Kubernetes에 Vault를 설치하는 방법
- KV 시크릿 엔진으로 정적 시크릿을 저장하는 기본 흐름
- Vault Agent + Sidecar 패턴으로 애플리케이션과 Vault를 자연스럽게 붙이는 방법
1. 시크릿과 현대 인프라: 왜 이제는 그냥 .env로는 안 되는가
1-1. 시크릿(Secret)이란?
시크릿은 “노출되면 안 되는 모든 정보”라고 보면 된다. 대표적인 것만 정리해도 이 정도다.
- 사용자/시스템 자격 증명
- 비밀번호, SSH Key, DB 계정(ID/PW)
- 서비스 연동 및 자동화 키
- AWS/GCP/Azure Credential, GitHub Token, Slack/Webhook Token, OpenAI API Key 등
- 보안 통신 및 암호화 자산
- TLS 인증서, 개인 키, 데이터 암호화 키
과거에는 이런 시크릿이 많지 않았고, 변경 주기도 길었다.
하지만 클라우드, Kubernetes, MSA로 넘어오면서 상황이 완전히 바뀌었다.
1-2. 아키텍처 변화가 만든 시크릿 지옥
아키텍처를 아주 거칠게 요약하면 이렇게 진화해 왔다.
- 메인프레임 / 모놀리식
- 한두 개의 큰 시스템 안에서 모든 게 돌아감
- 관리해야 할 시크릿이 적고, 위치도 명확함
- 3-Tier / 웹 + 앱 + DB
- Web / WAS / DB로 나뉘지만, 여전히 인프라는 “정적”
- 클라우드 / Kubernetes / MSA / DevOps 시대
- 수십~수백 개의 마이크로서비스
- 컨테이너가 계속 생성/삭제되는 동적 환경
- AWS, GCP, 외부 SaaS, 각종 API까지 전부 자격 증명이 필요
결과적으로:
- 시크릿 개수가 폭발적으로 증가
- 컨테이너/VM이 수시로 생겼다가 사라지니, 시크릿도 동적으로 관리해야 함
- Git, 설정 파일, CI/CD 도구, 개발자 PC 등 여기저기 흩어짐
이 현상을 HashiCorp는 “Secret Sprawl(시크릿 스프롤)”이라고 부른다.
한마디로, 여기저기 퍼져 있는 시크릿 때문에 누가 뭘 쓰는지 아무도 모르는 상태다.
1-3. Zero Trust와 시크릿
요즘 보안 키워드 중 하나가 Zero Trust(제로 트러스트)다.
- 과거: “내부망이면 어느 정도는 믿자” (성·해자 모델)
- 지금: “내부/외부 구분 의미 없다. 누구든, 무엇이든 항상 검증”
시크릿 관점에서 보면:
- “내부망에 있는 서비스니까 DB 접근해도 되겠지” 같은 발상은 이제 위험하다.
- 대신
- 저 서비스가 정말 누구인지(Identity)
- 어떤 리소스에(Permission)
- 얼마 동안(TTL)
만 접근할지, 명시적으로 통제해야 한다.
이걸 제대로 하기 위해서는, 시크릿을 한 곳에서 통합 관리하고
“누가, 무엇을, 얼마나, 어떻게” 썼는지 추적 가능한 시스템이 필요하다.
그게 바로 HashiCorp Vault 같은 도구다.
2. HashiCorp Vault 한눈에 보기
Vault는 HashiCorp에서 만든 신원 기반(Identity-based) 시크릿 및 암호화 관리 시스템이다.
핵심 키워드만 정리하면 다음 네 가지다.
- 시크릿 중앙 저장소
- 토큰, API Key, 비밀번호, 인증서, 암호화 키 등 모든 시크릿을 중앙에서 암호화 저장
- 애플리케이션 코드나 설정 파일에 하드코딩할 필요가 없어짐
- 동적 시크릿(Dynamic Secrets)
- 요청이 올 때마다 DB 계정이나 클라우드 Credential을 즉시 생성
- TTL이 지나면 자동 폐기 → 유출돼도 피해를 줄일 수 있음
- 신원 기반 접근 제어(Identity-based Access)
- 사람(개발자), 애플리케이션, 시스템 모두 “신원(Identity)”로 구분
- LDAP, OIDC, Kubernetes, AWS IAM 등으로 인증 후 Policy로 권한 제어
- 감사 로그(Audit)
- 누가, 언제, 어떤 시크릿을 조회/수정했는지 상세 기록
- 컴플라이언스/보안 감사 대응에 유리
Vault의 동작 흐름을 단순히 요약하면:
- 클라이언트(사람/앱)가 인증(Auth Method)으로 로그인
- Vault가 외부 IdP/플랫폼을 통해 신원 검증
- 해당 신원에 매핑된 Policy를 확인해 권한을 판별
- 토큰(Token)을 발급하고, 이 토큰으로 시크릿/암호화 기능을 사용
3. 실습 환경: Kind 기반 Kubernetes에 Vault 설치
여기서는 로컬에서 쉽게 테스트할 수 있도록 Kind + Helm으로 Vault를 올리는 과정을 정리한다.
3-1. Kind 클러스터 준비
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000 # Vault UI
hostPort: 30000
- containerPort: 30001 # Jenkins UI
hostPort: 30001
- containerPort: 30002 # DB
hostPort: 30002
- containerPort: 30003 # Sample App
hostPort: 30003
EOF
3-2. Dev Mode로 Vault 설치 (Helm)
학습용으로는 Dev Mode가 편하다.
특징:
- In-memory storage → 재시작 시 데이터 초기화
- Auto Unseal → 바로 Unseal 상태로 올라옴
- Root token을 고정 값으로 지정 가능
네임스페이스와 Helm Repo 설정:
kubectl create namespace vault
helm repo add hashicorp https://helm.releases.hashicorp.com
helm search repo hashicorp/vault
Dev 용 values 파일:
cat <<EOF > vault-values-dev.yaml
global:
enabled: true
tlsDisable: true
injector:
enabled: true # Sidecar Injection을 위한 설정
server:
dev:
enabled: true
devRootToken: "root" # 학습용 고정 Root Token
dataStorage:
enabled: false # Dev 모드는 in-memory
service:
type: "NodePort"
nodePort: 30000
ui:
enabled: true
EOF
설치:
helm upgrade vault hashicorp/vault -n vault -f vault-values-dev.yaml --install
kubens vault
kubectl get pods,svc
Vault 상태 확인:
kubectl exec -ti vault-0 -- vault status
Dev 모드라 Initialized=true, Sealed=false로 바로 뜬다.
3-3. CLI 설정 및 로그인
Mac 기준:
brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault --version
export VAULT_ADDR='http://localhost:30000'
vault status
vault login # Token: root
Vault UI는 http://localhost:30000 으로 접속해서 Root Token으로 로그인하면 된다.
4. KV 시크릿 엔진으로 정적 시크릿 관리하기
Vault의 가장 기본적인 사용법은 KV(키/값) 시크릿 엔진에 시크릿을 저장하는 것이다.
Dev 모드에서는 기본적으로 secret/ 경로에 KV 엔진이 하나 올라가 있다.
4-1. 시크릿 저장
현재 활성화된 시크릿 엔진:
vault secrets list
Path Type
---- ----
cubbyhole/ cubbyhole
identity/ identity
secret/ kv
sys/ system
샘플 시크릿 저장:
vault kv put secret/sampleapp/config \
username="demo" \
password="p@ssw0rd"
조회:
vault kv get secret/sampleapp/config
====== Data ======
Key Value
--- -----
password p@ssw0rd
username demo
UI에서도 Secrets → secret → sampleapp/config 로 들어가면 같은 값을 확인할 수 있다.
4-2. HTTP API로 읽어보기
동일 데이터를 API로도 가져올 수 있다.
curl -s \
--header "X-Vault-Token: root" \
--request GET \
http://127.0.0.1:30000/v1/secret/data/sampleapp/config | jq
응답 구조를 보면 data.data 아래에 우리가 넣은 username/password가 들어 있다.
이 경로(/v1/secret/data/...)와 구조를 이해하면, 애플리케이션에서 직접 API를 호출해 시크릿을 가져오는 것도 가능하다.
5. Vault Agent와 Sidecar 패턴
Vault를 도입하면 거의 바로 부딪히는 문제가 하나 있다.
“앱에서 Vault를 어떻게 붙일까?”
5-1. 직접 연동 방식의 문제
애플리케이션이 Vault SDK를 직접 사용하면 다음을 전부 구현해야 한다.
- Kubernetes, AWS, AppRole 등 Auth Method 별 로그인 로직
- 발급받은 토큰의 TTL 관리, 자동 갱신(Renew), 재로그인 처리
- Vault 장애/네트워크 에러 시 재시도 및 백오프
- Vault에서 가져온 JSON을 파싱해서 파일/환경변수에 반영
- 시크릿 rotation 시 재반영 및 앱 재기동/재로드 처리
※ 운영팀 관점에서 보면, 이 로직을 각 언어/각 서비스마다 개발팀에 맡기는 건 현실적으로 위험하다는 의견이 많다.
5-2. Vault Agent가 해결해 주는 것
Vault Agent는 클라이언트 옆(Sidecar)에서 돌면서 다음을 대신 해준다.
- Auto-Auth
- Kubernetes Service Account, AWS IAM, AppRole 등으로 자동 로그인
- Token Lifecycle 관리
- 토큰 TTL 체크 → 자동 갱신 → 실패 시 재로그인까지 처리
- 템플릿 렌더링(Consul Template 내장)
- Vault에서 가져온 시크릿을 .env, config.yaml, tls.crt 같은 파일로 렌더링
- 시크릿이 갱신되면 파일도 자동 업데이트
애플리케이션은 단순히:
- “/config/app.env 파일을 읽는다”
- “/etc/tls/tls.crt, tls.key를 읽어서 TLS 설정한다”
정도만 하면 된다. Vault API를 직접 몰라도 된다.
5-3. Kubernetes에서의 Sidecar 패턴
Kubernetes에서는 Vault Agent를 Pod 안에 Sidecar 컨테이너로 함께 배포한다.
- Vault Agent Injector(웹훅)가 Pod 정의를 가로채서
- Sidecar 컨테이너 추가
- 시크릿이 마운트될 공유 Volume 추가
- Auto-Auth 설정 추가
- 앱 컨테이너는 마운트된 파일만 읽어서 애플리케이션 설정에 사용
이 패턴을 쓰면:
- 개발자는 “시크릿이 어디서 왔는지” 몰라도 되고
- 플랫폼 팀은 Vault Policy, TTL, Rotation 전략을 중앙에서 통제할 수 있고
- 언어에 따라 구현이 제각각 갈라지지 않는다.
6. 마치며: Vault를 도입할 때 생각해 볼 포인트
※ 개인적으로 Vault는 “크고 복잡한 환경에서 반드시 필요한 인프라 보안 레이어”라고 본다.
단, 처음부터 너무 많은 것을 한 번에 하려 하면 팀이 지치기 때문에, 단계적으로 가져가는 게 현실적이다.
예를 들면 이런 식의 단계적 접근을 생각해 볼 수 있다.
- Git/설정 파일에 하드코딩된 시크릿을 Vault(KV 엔진)로 옮기기
- 사람이 쓰는 정적 자격 증명부터 Vault로 통합
- Kubernetes, CI/CD(Jenkins, GitHub Actions 등)와 Vault 연동
- DB 계정, 클라우드 Credential을 동적 시크릿으로 전환
- Audit Log, Policy 고도화, Zero Trust 관점의 접근 제어 정교화
이 글에서 다룬 내용은 그 중에서도:
- Vault가 왜 필요한지에 대한 개념
- 로컬 Kubernetes에 Vault를 올리는 기본 실습
- KV 시크릿 엔진으로 시크릿을 중앙 관리하는 맛보기
- Vault Agent + Sidecar 패턴으로 애플리케이션 연동의 방향성
까지를 정리한 것이다.
추가로 Dynamic Secrets, PKI 엔진, Transit 엔진(암호화 서비스) 등으로 확장하면
실제 프로덕션 환경에서도 꽤 강력한 시크릿/암호화 플랫폼을 만들 수 있다.
'스터디(Study) > CI·CD Study' 카테고리의 다른 글
| Jenkins · Argo CD · Keycloak · OpenLDAP로 Kubernetes SSO + RBAC 구성하기 [부록 실습] (0) | 2025.11.22 |
|---|---|
| 예제로 배우는 Argo CD 5장: Argo CD로 쿠버네티스 클러스터 부트스트랩 (0) | 2025.11.22 |
| 예제로 배우는 Argo CD 4장: 접근 제어 (1) | 2025.11.15 |
| 예제로 배우는 Argo CD 3장: Argo CD 운영 (1) | 2025.11.08 |
| 예제로 배우는 Argo CD 2장: Argo CD 시작하기 (0) | 2025.11.08 |

댓글