본문 바로가기
devops/cicd

[CI/CD] 7주차 - Vault (1)

by gnobaaaar 2025. 11. 29.

클러스터 구성

# kind k8s 배포
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 배포(PostgreSQL 또는 MySQL)
    hostPort: 30002
  - containerPort: 30003 # # Sample App
    hostPort: 30003
EOF

 

암호(대칭키/비대칭키)

https://tech.kakaopay.com/post/kakaopayins-envelope-encryption/

 

우리는 암호화하는데 왜 키를 사용할까? | 카카오페이 기술 블로그

현대 암호화의 발전 흐름을 이해하고 실무에 적용했던 경험에 대해서 공유합니다.

tech.kakaopay.com

케르크호프스의 원리
: 키를 제외한 시스템의 다른 모든 내용이 알려지더라도 암호 체계는 안전해야 한다

 

대칭키 암호화

하나의 같은 키 (비밀키)를 가지고 암호화와 복호화 모두를 수행합니다.

- 빠르고 효율적

- 대량의 암호화에 최적

- 다만, 키관리가 어렵고 탈취 위험이 있습니다.

대표적인 알고리즘으로 DES, 3DES, AES, SEED 등이 있습니다.

 

비대칭키 암호화 = 공개키 암호화

비대칭키 암호화는 암호화 키와 복호화 키를 서로 다른 키를 사용하는 방식을 의미합니다.

 

두 개의 키를 사용합니다.

공개키 (public key)

개인키 (private key)

- 키 전달이 안전하고, 디지털서명, 인증서 등에 사용이 가능합니다.

- 대칭키보다 속도가 훨씬 드립니다. (주로 키 교환 및 서명에서 사용됩니다)

대표적인 알고리즘으로 RSA, DSA, ECC 등이 있습니다.

 

동작방식

목표 : 나에게 암호문을 안전하게 보내게하기

 

1. 상대방에게 공개키를 전달합니다.

공개키는 노출되어도 문제 없기에 네트워크를 통해 그대로 전송이 가능합니다.

2. 상대방이 내 공개키로 데이터를 암호화합니다.

3. 상대방이 암호문을 나에게 보냅니다.

4. 나는 받은 암호문을 개인키로 복호화합니다.

 

현재 TLS에서는 두가지 방식을 모두 사용합니다. (하이브리드 암호화)

비대칭키로 먼저 대칭키를 안전하게 교환합니다.

대칭키로 대량의 데이터를 빠르게 암호화 합니다.

 

전자서명

정리중

 

PKI

정리중

 

 

 

Vault 개요

 

시크릿 중앙 관리와 Vault의 필요성

IT 인프라와 애플리케이션 아키텍처가 복잡해지면서 기존의 방식으로 Secret을 안전하게 관리하는 것이 불가능해졌습니다.

특히, 현대 클라우드, MSA, DevOps 시대가 되면서

각 서비스 컨테이너, API 연동마다 고유한 자격증명이 필요해졌고 관리가 필요한 시크릿의 수가 급격히 증가했습니다.

 

시크릿 스프롤 (Secret Sprawl)

시크릿이 코드 저장소(Git), 설정 파일(config.yml), 환경 변수, 개발자 PC 등 여러 곳에 하드코딩되거나 방치

https://www.hashicorp.com/en/resources/what-is-secret-sprawl-why-is-it-harmful

 

 

 

제로 트러스트 (Zero Trust) 보안 모델

과거 보안모델

성과 해자 방식으로 내부망(ex. DMZ)에 들어오면 내부의 시스템은 서로를 신뢰하였습니다.

흔히 같은 사설망에서는 서로를 신뢰하는 방식입니다.

 

하지만 클라우드와 MSA 환경에서는 이러한 내부, 외부의 경계가 모호해졌습니다.

해커가 일단 내부망에 접근하면, 신뢰를 기반으로 다른 시스템에 쉽게 접근이 가능합니다.

 

"절대 신뢰하지 말고, 항상 검증하라 (Never Trust, Always Verify)"

-> 로 트러스트의 핵심

 

모든 접근 요청을 의심하고 검증합니다.

  • 기존: "저 서비스는 내부망에 있으니깐 DB에 접근해도 돼." (위치 기반 신뢰)
  • 제로 트러스트: "저 서비스가 정말 '주문 서비스'가 맞는지 신원(Identity)을 확인하고, DB의 '주문 테이블'에만 SELECT할 수 있는 최소한의 권한5분 동안만 부여하겠어." (신원 기반 + 최소 권한 + 동적 접근)

제로 트러스트는 아래와 같이 요구합니다.

  • 경계 기반 보안의 종말: 내부망이라고 해서 안전하거나 신뢰할 수 없음 → Never Trust, Always Verify
  • '사람' 뿐만 아니라 '시스템'의 신원 확인: 모든 사용자(사람)와 머신(애플리케이션, 컨테이너)은 접근 전 반드시 신원을 인증해야 함 → Never Trust, Always Verify
  • 최소 권한의 원칙 (Principle of Least Privilege): 인증된 신원이라도, 작업에 필요한 '최소한의 권한'만 '최소한의 시간' 동안 부여받아야 함.

 

Vault의 필요성

HashiCorp Vault는 복잡한 아키텍처, 제로트러스트를 해결하기 위해 설계된 시크릿 중앙 관리 솔루션 입니다.

  • 1. 시크릿 스프롤(분산) 문제 해결 → 시크릿 중앙 저장소
    • 모든 시크릿(DB/API 키, 인증서, 토큰 등)을 Vault라는 하나의 안전한 저장소에 암호화하여 중앙 관리합니다. 더 이상 코드나 설정 파일에 시크릿을 하드코딩할 필요가 없습니다.
  • 2. 동적 인프라 문제 해결 → 동적 시크릿 (Dynamic Secrets)
    • Vault는 요청이 있을 때마다 '실시간으로' 시크릿(e.g., 10분짜리 DB 임시 계정)을 생성하고, 사용이 끝나면 자동으로 폐기합니다. 시크릿의 생명 주기를 관리합니다.
  • 3. 제로 트러스트(신원 확인) 문제 해결 → 신원 기반 접근 (Identity-Based Access)
    • Vault는 사람(LDAP, Okta 등)뿐만 아니라 머신(Kubernetes, AWS IAM, GCP 등)의 신원을 인증할 수 있습니다. 인증된 신원(Identity)에게만 정책(Policy)에 따라 정확한 시크릿 접근 권한을 부여합니다.
  • 4. 감사 및 통제 문제 해결 → 감사 로그 (Audit Logs)
    • '누가(어떤 시스템이)', '언제', '어떤 시크릿에' 접근했는지 상세한 로그를 제공하여 강력한 통제와 추적성을 확보합니다.

 

이러한 기능들이 어떻게 현대 IT 환경의 보안 문제를 해결하는지 깊이 있게 고민해보기!

 

 

 

Vault란

https://developer.hashicorp.com/vault/docs/about-vault/what-is-vault

 

What is Vault? | Vault | HashiCorp Developer

Vault provides centralized, encrypted, and audited management for static secrets, dynamic credentials, certificates, identity authentication, and secrets from cloud providers like AWS, Azure, and Google to simplify the secret management lifecycle and regul

developer.hashicorp.com

 

신원 기반의 시크릿 및 암호화 관리 시스템입니다.

인증 및 인가를 통해 암호화 서비스를 제공하고 시크릿에 대한 안전하고 제한된 접근을 보장합니다.

 

 

Vault 엑세스 제어 4가지 핵심요소

 

누가 (인증)

  • 가장 먼저 신뢰할 수 있는 주체인지 확인
  • ID/PW, GitHub 토큰, K8s Service Account, AWS IAM 등 다양한 방식을 통해 신원 검증
  • 검증된 사용자에게 Vault를 사용할 수 있는 토큰(Token)을 발급합니다.

무엇을 (대상지점)

  • 대상 리소스: Database, Web Server, Object Storage(S3), Cloud Console 등 민감한 자산들.
  • 다양한 시스템(Secret Engine)에 접근할 수 있는 단일한 게이트웨이(Gateway) 역할을 수행합니다.

얼마동안 (TTL)

한번 발급된 권한이 영원히 유효하다면, 유출되었을 때 큰 보안 사고로 이어집니다.

  • 핵심 개념: TTL (Time To Live, 유효 기간)
  • 동작: "이 DB 접속 권한은 딱 1시간 동안만 유효해"라고 제한을 둡니다.
  • Vault 역할: 영구적인 키 대신, 시간이 지나면 자동으로 만료되는 임시 자격 증명(Lease)을 발급합니다.

라이프사이클 (자동화)

  • 접근 키 관리: 생성(Create) → 갱신(Renew) → 폐기(Revoke)의 과정을 자동화합니다.
  • 동적 시크릿 (Dynamic Secrets): 사용자가 요청할 때 계정을 즉시 생성하고, 사용이 끝나면 즉시 삭제합니다 → Just in Time(JIT)
  • Vault 역할: 관리자의 개입 없이 시스템이 알아서 키의 수명주기를 관리하여 운영 부담과 보안 위험을 동시에 줄입니다.

 

Vault 동작방식

토큰(Token)을 기반으로 작동

토큰은 클라이언트의 정책(Policy)과 연결

각 정책은 경로(path) 기반으로 설정

정책 규칙은 클라이언트가 해당 경로에서 수행할 수 있는 작업과 접근 가능성을 제한

Vault에서는 토큰을 수동으로 생성해 클라이언트에 할당할 수도 있고, 클라이언트가 로그인하여 토큰을 직접 획득할 수도 있습니다

 

Vault의 핵심 워크플로

 

  1. 인증 (Authenticate): Vault에서 인증은 클라이언트가 Vault에 자신이 누구인지 증명할 수 있는 정보를 제공하는 과정입니다. 클라이언트가 인증 메서드를 통해 인증되면, 토큰이 생성되고 정책과 연결됩니다.
  2. 검증 (Validation): Vault는 Github, LDAP, AppRole 등과 같은 신뢰할 수 있는 외부 소스를 통해 클라이언트를 검증합니다.
  3. 인가 (Authorize): 클라이언트는 Vault의 보안 정책과 비교됩니다. 이 정책은 Vault 토큰을 사용하여 클라이언트가 접근할 수 있는 API 엔드포인트를 정의하는 규칙의 집합입니다. 정책은 Vault 내 특정 경로나 작업에 대한 접근을 허용하거나 거부하는 선언적 방식으로 권한을 제어합니다.
  4. 접근 (Access): Vault는 클라이언트의 신원에 연관된 정책을 기반으로 토큰을 발급하여 비밀, 키, 암호화 기능 등에 대한 접근을 허용합니다. 클라이언트는 이후 작업에서 해당 Vault 토큰을 사용할 수 있습니다.

 

특징 HashiCorp Vault
주요 기능 다양한 환경과 플랫폼에서 secret을 저장, 액세스 및 배포하기 위한 포괄적인 secret 관리 솔루션
암호화 높은 유연성과 보안을 위해 여러 암호화 백엔드(예: AWS KMS, Azure Key Vault, GCP KMS)를 지원하는 고급 암호화 메커니즘을 제공합니다.
접근 제어 역할, 경로 및 작업을 기반으로 세분화된 권한을 허용하는 세부적인 액세스 제어 정책(ACL)을 구현합니다.
동적 secret 데이터베이스, 클라우드 자격 증명, SSH 키와 같은 리소스에 대한 일시적이고 주문형 액세스를 제공하여 동적 secret 생성을 지원합니다.
감사 로깅 모든 작업과 액세스 요청을 추적하여 책임과 추적성을 보장하기 위한 포괄적인 감사 로그를 제공합니다.
완성 Kubernetes, Terraform, Jenkins 및 클라우드 공급자와 같은 광범위한 도구 및 서비스와의 광범위한 통합을 통해 광범위한 애플리케이션 범위가 가능합니다.
설치 복잡성 서버 배포 및 구성을 포함한 더 많은 설정 및 인프라가 필요하며 학습 곡선이 더 가파를 수 있습니다.
secret rotation 자동화된 secret rotation을 지원하여 secret이 정기적으로 업데이트되고 노출 위험이 최소화되도록 합니다.
API 및 CLI 다양한 작업을 위한 vault와의 광범위한 프로그래밍 액세스 및 상호 작용을 허용하는 풍부한 API 및 CLI를 제공합니다.
사용 사례 동적 secret 생성, 서비스로서의 암호화, 다양한 애플리케이션 및 환경에서의 안전한 데이터 저장을 포함한 광범위한 사용 사례에 적합합니다.
전개 최적의 성능과 보안을 위해 전용 인프라와 리소스가 필요한 독립 실행형 서비스로 배포됨
확장성 분산 환경에서 대량의 secret과 여러 클라이언트를 처리할 수 있는 높은 확장성을 위해 설계되었습니다.
버전 관리 secret 버전 관리를 지원하여 사용자가 시간 경과에 따라 다양한 버전의 secret을 추적하고 관리할 수 있도록 합니다.
오픈소스 추가 기능과 지원을 제공하는 엔터프라이즈 버전과 함께 오픈 소스 도구로 사용 가능

 

 

Vault 기본 구조와 동작방식의 이해

 

손님이 호텔에 도착하면, 본인확인을 하고 신원 확인되면 방키를 얻습니다. -> Token 발급

방키는 특정 층/시설에만 접근이 가능합니다 -> Vault Policy 적용된 Token

 

Vault의 인증과 권한부여

Vault는 인증을 직접 처리하지 않습니다.

-> 사용자가 누구인지 확인하는 기능을 직접 수행하지 않습니다.

-> 대신, OIDC, LDAP, AWS IAM 과 같은 외부 IDP(Identity Provider)에게 위임합니다.

 

동작방식

  1. 외부 IDP가 인증한 사용자 정보를 Vault로 전달
  2. Vault는 해당 “ID”에 매핑된 Policy를 확인
  3. 사용자가 접근할 수 있는 Secret/Engine/Path를 결정
  4. 그 범위가 담긴 Token을 발급

 

 

 

 

 

Vault 설치 (Dev Mode)

Dev Mode

  • In-Memory Storage: 데이터를 메모리에 저장합니다. 프로세스가 종료되면 데이터가 사라집니다.
  • Auto Unseal: 자동으로 봉인이 해제된 상태로 시작됩니다. 별도의 Unseal Key 입력과정이 없습니다.
  • Root Token: 초기 루트 토큰이 지정된 값(여기서는 root)으로 고정됩니다.

 

Helm을 사용한 Vault 배포

# Create a Kubernetes namespace.
kubectl create namespace vault

# View all resources in a namespace.
kubectl get all --namespace vault

# Setup Helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com

# Check that you have access to the chart.
helm search repo hashicorp/vault

NAME                            	CHART VERSION	APP VERSION	DESCRIPTION
hashicorp/vault                 	0.31.0       	1.20.4     	Official HashiCorp Vault Chart
hashicorp/vault-secrets-gateway 	0.0.2        	0.1.0      	A Helm chart for Kubernetes
hashicorp/vault-secrets-operator	1.0.1        	1.0.1      	Official Vault Secrets Operator Chart

 

Helm chart 설정을 위해 values.yaml을 생성해줍니다.

Sidecar Injection

devRootToken

# vault-values-dev.yaml 생성
cat <<EOF > vault-values-dev.yaml
global:
  enabled: true
  tlsDisable: true

injector:
  enabled: true
  # Sidecar Injection을 위해 필요한 설정

server:
  dev:
    enabled: true
    devRootToken: "root" # 학습 편의를 위해 Root Token을 'root'로 고정
  
  # 데이터 영구 저장이 필요 없으므로 비활성화 (Dev모드는 메모리 사용)
  dataStorage:
    enabled: false

  # UI 활성화 및 NodePort 노출
  service:
    type: "NodePort"
    nodePort: 30000
    
  ui:
    enabled: true
EOF

 

이제 vault를 설치해줍니다.

# Helm Install 실행
helm upgrade vault hashicorp/vault -n vault -f vault-values-dev.yaml --install

# 네임스페이스 변경 : vault
kubens vault

Context "kind-myk8s" modified.
Active namespace is "vault".

# 배포확인
k get pods,svc,pvc

NAME                                        READY   STATUS              RESTARTS   AGE
pod/vault-0                                 0/1     ContainerCreating   0          9s
pod/vault-agent-injector-556c5dd8fb-7w7mh   0/1     ContainerCreating   0          9s

NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
service/vault                      ClusterIP   10.96.236.165   <none>        8200/TCP,8201/TCP   9s
service/vault-agent-injector-svc   ClusterIP   10.96.235.29    <none>        443/TCP             9s
service/vault-internal             ClusterIP   None            <none>        8200/TCP,8201/TCP   9s

 

Vault 초기화 및 잠금해제

kubectl exec -ti vault-0 -- vault status

Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    1
Threshold       1
Version         1.20.4
Build Date      2025-09-23T13:22:38Z
Storage Type    inmem
Cluster Name    vault-cluster-4336e9b4
Cluster ID      c45bb2d0-69c4-03d7-909f-f0f4bd7d61fc
HA Enabled      false

 

dev mode로 설치했기 때문에 Unseal 과정이 없습니다.

파드내부에서 vault status를 보면

Seal Type       shamir  # seal 방식
Initialized     true    # vault 초기화 여부 (prd설치에서 자세히 확인)
Sealed          false   # unseal(봉인) 여부 -> 사용가능
Total Shares    1       # master 키를 1개의 조각으로 생성
Threshold       1       # vault unseal 하려면 1개의 key 필요 (최소 설정값)

 

 

SSS (Shamir Secert Sharing) 방식

위에서 Type이었던 shamir 방식에 대해서 확인해보겠습니다.

  • 암호학자 아디 샤미르(Adi Shamir)의 이름에서 따온 이 시크릿 공유 알고리즘은 개인이 특정 시크릿 정보를 보유하지 않고 결합 될 때에야 암호화 된 루트 키를 해제할 수 있는 단일 키로 조합되는 방식입니다.
  • 개별조각은 비밀을 알 수 없지만 일정수 (Threshold)가 모이면 원래 비밀(루트키)를 재구성 가능합니다.
  • 이 알고리즘은 N개의 Unseal Key를 생성(Key Shares)하고, 그 중 M개의 Key를 제공(Key Threshold)하면 이를 토대로 Root Key를 획득 및 Unseal을 수행
  • -> Key Shares 5개, Threshold: 3개를 설정하면 과반수 이상 참여했으므로 Root Key 제공

 

 

해당 방식은 왜 사용될까요?

Vault Core에서 가장 중요한 Key는 Barrier Key (Master Key)입니다.

Storage Backend에 저장되는 모든 데이터를 암호화/복호화하는 핵심 키입니다.

 

이 Barrier Key를 그대로 제공하는 것은 매우 위험하기 때문에

Vault는 이를 Shamir 방식으로 여러 개의 Unseal Key로 분할하여 보호합니다.

 

 

 

CLI 설정 (mac OS)

brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault --version  # 설치 확인

# NodePort로 공개한 30000 Port로 설정
export VAULT_ADDR='http://localhost:30000'

# vault 상태확인
vault status

 

설치된 vault는 Root Token으로 접근합니다.

Dev mode에서는 편의상 root로 설정했기 때문에 해당 값으로 접근해봅니다.

# Root Token으로 로그인
vault login

Token (will be hidden): root # Dev 모드로 설치시 설정한 Root Token
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                  Value
---                  -----
token                root
token_accessor       euQQ1Uf8L2zDZioBqmgx7Go0
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

 

root token으로 포털 로그인도 해보겠습니다.

 

 

 

 

Vault 설치 (Prd Mode)

vault 구성의 전체적인 흐름 확인을 위해서 Production Mode 설치를 진행해보겠습니다.

프로덕션 환경에서는 HA 구성, TLS, 스토리지 등을 고려해서 구행해야합니다.

 

Helm 배포

# Create a Kubernetes namespace.
kubectl create namespace vault

# View all resources in a namespace.
kubectl get all --namespace vault

# Setup Helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com

# Check that you have access to the chart.
helm search repo hashicorp/vault
# NAME                                    CHART VERSION   APP VERSION     DESCRIPTION                          
# hashicorp/vault                         0.30.0          1.19.0          Official HashiCorp Vault Chart       
# hashicorp/vault-secrets-gateway         0.0.2           0.1.0           A Helm chart for Kubernetes          
# hashicorp/vault-secrets-operator        0.10.0          0.10.0          Official Vault Secrets Operator Chart

 

Helm 차트 배포를 위해 Values 설정을 진행하겠습니다.

전체 Values.yaml은 아래와 같습니다.

cat <<EOF > override-values.yaml
global:
  enabled: true
  tlsDisable: true  # Disable TLS for demo purposes

server:
  image:
    repository: "hashicorp/vault"
    tag: "1.19.0"

  standalone:
    enabled: true
    replicas: 1  # 단일 노드 실행

    config: |
      ui = true
      disable_mlock = true
      cluster_name = "vault-local"

      listener "tcp" {
        address = "[::]:8200"
        cluster_address = "[::]:8201"
        tls_disable = 1
      }

      storage "raft" {
        path = "/vault/data"
        node_id = "vault-dev-node-1"
      }
  service:
    enabled: true
    type: NodePort
    port: 8200
    targetPort: 8200
    nodePort: 30000   # Kind에서 열어둔 포트 중 하나 사용

injector:
  enabled: true

ui:
  enabled: true
  serviceType: "NodePort"
EOF

 

각 부분에 대해 좀 확인해보겠습니다.

tlsDisable 을 통해 TLS 인증서를 사용하지 않고 평문 HTTP에 대해 동작하도록 합니다.

global:
  enabled: true
  tlsDisable: true  # Disable TLS for demo purposes

 

Standalone모드로 배포됩니다.

vault 하나의 파드와 Raft Storage + HA 가 없습니다.

standalone:
  enabled: true
  replicas: 1

 

mlock() 은 Linux 시스템콜으로,

프로세스가 특정 메모리 영역을 RAM에 고정시키는 기술입니다.

즉, 절대 swap(스왑) 공간으로 내려가지 않게 보장합니다.

https://docs.redhat.com/ko/documentation/red_hat_enterprise_linux_for_real_time/9/html/understanding_rhel_for_real_time/con_mlock-system-calls_assembly_memory-management-on-rhel-for-real-time-

 

2.3. mlock() 시스템 호출 | RHEL for Real Time 이해 | Red Hat Enterprise Linux for Real Time | 9 | Red Hat Documentation

Red Hat Enterprise Linux for Real Time 형식멀티 페이지단일 페이지모든 문서를 PDF로 표시

docs.redhat.com

 

Vault는 메모리 안에 다음과 같은 민감한 데이터를 보관합니다.

- 마스터키 (Barrier Key)

- 암호화 키

- 단기 세션키

- Token

- 인증정보

 

이러한 민감정보는 디스크 스왑 공간에 기록되면 안됩니다.

CPU/RAM 부족시 OS는 메모리 페이지를 swap으로 밀어내는데, 해당 동작을 막기 위해

mlock()을 사용합니다.

그래서 Vault의 기본 설정은 아래와 같습니다.

disable_mlock = false (기본값)

 

하지만, 컨테이너 환경에서는 mlock() 사용은 불가능합니다.

- 권한없음 : 기본 컨테이너는 CAP_IPC_LOCK(IPC 메모리 잠금 권한) 권한을 가지고 있지않습니다

- 컨테이너 내부에서 mlock을 사용하면 컨테이너의 보안격리 모델이 깨질 수  있음

- OCI 런타임(runc 등)이 메모리 락 사용기능을 제한

-> 기본적으로 cgroup + namespaces 구조상 mlock은 사용불가능 합니다.

 

따라서, 아래와 같이 설정됩니다.

disable_mlock = true

 

 

또한 Vault의 데이터 저장 방식을 설정합니다.

storage "raft" {
  path = "/vault/data"
  node_id = "vault-dev-node-1"
}

 

Vault는 실행 시 상태(state)와 모든 암호화된 데이터를

“Storage Backend”에 저장해야 합니다.

Standalone/HA 환경에서 가장 많이 쓰이는 저장소가 Raft입니다.

 

 

Vault kubernetes injector (Webhook) 기능도 활성화해줍니다.

애플리케이션이 Vault로 부터 자동으로 시크릿 정보를 받아올 수 있습니다. (아래에서 자세하게 설명)

injector:
  enabled: true

 

 

이제 values 파일을 가지고 설치를 진행합니다.

# Helm Install 실행
helm upgrade vault hashicorp/vault -n vault -f override-values.yaml --install

# 네임스페이스 변경 : vault
kubens vault
Context "kind-myk8s" modified.
Active namespace is "vault".

# 배포확인
k get pods,svc,pvc

NAME                                        READY   STATUS              RESTARTS   AGE
pod/vault-0                                 0/1     ContainerCreating   0          11s
pod/vault-agent-injector-56459c7545-9n94t   0/1     ContainerCreating   0          11s

NAME                               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                         AGE
service/vault                      NodePort    10.96.36.121   <none>        8200:30000/TCP,8201:31091/TCP   11s
service/vault-agent-injector-svc   ClusterIP   10.96.240.81   <none>        443/TCP                         11s
service/vault-internal             ClusterIP   None           <none>        8200/TCP,8201/TCP               11s

NAME                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/data-vault-0   Bound    pvc-6f5739c5-14e9-4a62-bed2-b98fd327bcb1   10Gi       RWO            standard       <unset>                 11s

 

 

vault-0 파드 기동이 정상적이지 않습니다.

로그를 확인해보겠습니다.

 

서버는 실행되었지만 초기화가 되지 않은 것을 확인할 수 있습니다.

 

Vault 초기화 및 잠금해제

Vault의 상태를 확인해보겠습니다.

# Vault Status 명령으로 Sealed 상태확인
kubectl exec -ti vault-0 -- vault status

 

초기화 되지않았고 Seal 상태인 것을 확인할 수 있습니다.

Vault를 init-unseal.sh 를 사용하여 Unseal 자동화를 진행합니다

 

init-unseal.sh를 생성하고 실행합니다.

#!/bin/bash

# Vault Pod 이름
VAULT_POD="vault-0"

# Vault 명령 실행
VAULT_CMD="kubectl exec -i $VAULT_POD -- vault"

# 출력 저장 파일
VAULT_KEYS_FILE="./vault-keys.txt"
UNSEAL_KEY_FILE="./vault-unseal-key.txt"
ROOT_TOKEN_FILE="./vault-root-token.txt"

# Vault 초기화 (Unseal Key 1개만 생성되도록 설정)
$VAULT_CMD operator init -key-shares=1 -key-threshold=1 \
  | sed 's/\x1b\[[0-9;]*m//g' \
  | tr -d '\r' \
  > "$VAULT_KEYS_FILE"

# Unseal Key / Root Token 추출
grep 'Unseal Key 1:' "$VAULT_KEYS_FILE" | awk -F': ' '{print $2}' | tr -d ' ' > "$UNSEAL_KEY_FILE"
grep 'Initial Root Token:' "$VAULT_KEYS_FILE" | awk -F': ' '{print $2}' | tr -d ' ' > "$ROOT_TOKEN_FILE"

# Unseal 수행
UNSEAL_KEY=$(cat "$UNSEAL_KEY_FILE")
$VAULT_CMD operator unseal "$UNSEAL_KEY"

# 결과 출력
echo "[🔓] Vault Unsealed!"
echo "[🔐] Root Token: $(cat $ROOT_TOKEN_FILE)"

 

# 실행 권한 부여
chmod +x init-unseal.sh

# 실행
./init-unseal.sh

 

 

vault status 명령어로 Unseal 되었는지 확인하겠습니다.

 

포털에서 root Token으로 접속해봅니다.

스크립트에서 생성한 vault-root-token.txt 파일에서 확인 가능합니다.

 

CLI 설정 (mac OS)

brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault --version  # 설치 확인

# NodePort로 공개한 30000 Port로 설정
export VAULT_ADDR='http://localhost:30000'

# vault 상태확인
vault status

# Root Token으로 로그인
vault login

Token (will be hidden): 
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                  Value
---                  -----
token                hvs.egeVgnhMKgnFqof6YLfiPtLa
token_accessor       wWpBsO3TqQEybFF0le2YmNGX
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

 

 

KV 시크릿 엔진 활성화 및 샘플 구성

Vault에는 여러 종류의 Secret Engine이 있습니다. 

그중 KV(Key-Value) 엔진은 Key=Vaule 형태로 데이터를 저장하는 엔진입니다. (Vault의 기본 저장소)

 정적 시크릿(Static Secret) 저장하는 방식

 

https://developer.hashicorp.com/vault/docs/secrets/kv

 

KV - Secrets Engines | Vault | HashiCorp Developer

The KV secrets engine can store arbitrary secrets.

developer.hashicorp.com

 

Vault KV version2 엔진을 활성화하고 샘플 데이터를 저장하겠습니다.

Version1 : KV 버전관리 불가 / Version2 : KV 버전관리 가능

버전 특징
KV version 1 버전관리 없음, 삭제 시 바로 삭제
KV version 2 버전관리 지원(rollback 가능), soft delete, metadata 포함

 

 

KV 엔진 활성화 및 샘플 데이터 추가

vault 시크릿 엔진 목록을 조회해보겠습니다.

kubectl exec -ti vault-0 -- vault login

을 통해 로그인 후 진행합니다.

 

# 활성화된 시크릿 엔진 확인
Path          Type         Accessor              Description
----          ----         --------              -----------
cubbyhole/    cubbyhole    cubbyhole_b5ceebc5    per-token private secret storage
identity/     identity     identity_56c2424e     identity store
sys/          system       system_aae5cf29       system endpoints used for control, policy and debugging

 

KV v2 형태로 활성화 하기 위해서 아래 명령어를 수행합니다.

(Dev 모드에서는 기본값으로 활성화 되어있습니다)

vault secrets enable -path=secret kv-v2

# 활성화 후 
Success! Enabled the kv-v2 secrets engine at: secret/

 

다시 목록을 조회해 보겠습니다.

 

# 샘플 시크릿 저장 (경로: secret/sampleapp/config)
vault kv put secret/sampleapp/config \
  username="demo" \
  password="p@ssw0rd"
  
# 입력된 데이터 확인
vault kv get secret/sampleapp/config

======== Secret Path ========
secret/data/sampleapp/config

======= Metadata =======
Key                Value
---                -----
created_time       2025-11-20T02:45:37.136708888Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

====== Data ======
Key         Value
---         -----
password    p@ssw0rd
username    demo

 

Vault UI 확인

[Secrets Engine] 탭에 접속 후 [sampleapp - config] 접속하여 실제 저장된 Key / Value 확인

  • username : demo
  • password : p@ssw0rd

 

 

경로 확인하는 명령어

curl -s --header "X-Vault-Token: [루트토큰]" \
  --request GET http://127.0.0.1:30000/v1/secret/data/sampleapp/config | jq
{
  "request_id": "d4470ffb-867f-591c-6109-97a6555a7d3d",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "data": {
      "password": "p@ssw0rd",
      "username": "demo"
    },
    "metadata": {
      "created_time": "2025-11-30T06:02:59.920888908Z",
      "custom_metadata": null,
      "deletion_time": "",
      "destroyed": false,
      "version": 1
    }
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null,
  "mount_type": "kv"
}

 

 

'devops > cicd' 카테고리의 다른 글

[CI/CD] 8주차 - Hashicorp Vault/VSO on K8S  (1) 2025.12.06
[CI/CD] 7주차 - Vault (2)  (1) 2025.12.03
[CI/CD] 6주차 - Argo CD 3/3  (0) 2025.11.23
keycloak - Oauth - OIDC  (0) 2025.11.16
[CI/CD] 5주차 - Argo CD 2/3  (0) 2025.11.16