7주차 - Vault
0. 실습 환경 구성
Kind K8s 배포 (WSL기반)
(⎈|N/A:N/A) zosys@4:~$ 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
Creating cluster "myk8s" ...
✓ Ensuring node image (kindest/node:v1.32.8) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-myk8s"
You can now use your cluster with:
kubectl cluster-info --context kind-myk8s
Thanks for using kind! 😊
1. Vault 개요
사전 지식
1. 정보 보안의 3요소 (CIA Triad)
- 기밀성(Confidentiality)
- 허가된 사람(시스템)만 정보에 접근해야한다.
- 무결성(Integrity)
- 정보가 허가 없이 변조되거나 삭제되지 않아야 한다. 변경 될 경우 식별이 되어야한다.
- 가용성(Availability)
- 사용자가 원할 때는 언제든지 서비스를 이용가능해야한다.
2.액세스 제어의 3단계(AAA)
- 인증(Authentication)
- 신원을 확인하는 절차(출입 게이트에 사원증)
- 인가(Authorization)
- 인증된 사용자에게 허용된 권한을 부여하는 절차.(사원증에 따른 출입구역제한)
- 감사/계정관리(Accounting/Auditing)
- 사용자가 수행한 모든활동을 기록하고 추적하는것(CCTV 녹화,출입기록로그)
시크릿이란?
A. 사용자 및 시스템 접근 자격 증명 ex) 비밀번호,SSH KEY,DB Credential
B. 서비스 연동 및 자동화 키 ex) Cloud Credentials,Token,API Key
C. 보안 통신 및 암호화 자산 ex) PKI, TLS인증서,암호화키
Vault를 필요한 시크릿 중앙관리가 필요한 이유
기존 모놀리식구조나 3Tier구조와 달리 MSA아키텍쳐가 도입되어 인프라와 아키텍쳐가 상당히 복잡해지며 모든 “시크릿”을 안전하게 관리하기가 불가능하기때문이다.
Vault란?
- HashiCorp Vault는 신원 기반(identity-based)의 시크릿 및 암호화 관리 시스템입니다.
- 인증 및 인가방법을 통해 암호화서비스를 제공하여 비밀에 대한 안전하고 감사가능하며, 제한된 접근을 보장
- Vault의 4가지 핵심요소
- 누가(Who) : 인증(Authentication)
- 무엇에(What) : 대상 지정(Target System)
- 얼마동안(How Long) : 접근시간제어(TTL)
- 라이프사이클(Lifecycle) : 자동화(Automation)
2. Vault 동작 방식
Vault의 동작 방식 이해
개별 ID인증/인가를 통해 필요한 자격 증명 동적발급

Authentication을 위한 절차

3. Kubenetes에 Vault설치
Vault on kubernetes 설치
실습 환경 구성(개발모드로 진행)
네임스페이스 생성 및 Helm Repo추가
(⎈|kind-myk8s:N/A) zosys@4:~$ kubectl create namespace vault
namespace/vault created
(⎈|kind-myk8s:N/A) zosys@4:~$ helm repo add hashicorp https://helm.releases.hashicorp.com
"hashicorp" has been added to your repositories
(⎈|kind-myk8s:N/A) zosys@4:~$ 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설정 및 배포
(⎈|kind-myk8s:N/A) zosys@4:~$ cat vault-values-dev.yaml
global:
enabled: true
tlsDisable: true
injector:
enabled: true
server:
dev:
enabled: true
devRootToken: "root"
dataStorage:
enabled: false
service:
type: "NodePort"
nodePort: 30000
ui:
enabled: true
(⎈|kind-myk8s:N/A) zosys@4:~$ cat vault-values-dev.yaml
global:
enabled: true
tlsDisable: true
injector:
enabled: true
server:
dev:
enabled: true
devRootToken: "root"
dataStorage:
enabled: false
service:
type: "NodePort"
nodePort: 30000
ui:
enabled: true
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it 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-5d53df9b
Cluster ID 195a8699-aff7-c091-925e-8fb0d437777b
HA Enabled false
wsl2환경에서 실습환경 구성
(⎈|kind-myk8s:vault) zosys@4:~$ sudo apt-get update
[sudo] password for zosys:
Get:1 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease
Hit:3 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:4 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:5 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Hit:6 https://ppa.launchpadcontent.net/cncf-buildpacks/pack-cli/ubuntu noble InRelease
Fetched 48.5 kB in 1s (41.7 kB/s)
Reading package lists... Done
(⎈|kind-myk8s:vault) zosys@4:~$ sudo apt-get install -y gpg curl lsb-release
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
gpg is already the newest version (2.4.4-2ubuntu17.3).
gpg set to manually installed.
curl is already the newest version (8.5.0-2ubuntu10.6).
lsb-release is already the newest version (12.0-2).
lsb-release set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 48 not upgraded.
(⎈|kind-myk8s:vault) zosys@4:~$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com noble main
(⎈|kind-myk8s:vault) zosys@4:~$ sudo apt-get update
Hit:1 https://download.docker.com/linux/ubuntu noble InRelease
Get:2 https://apt.releases.hashicorp.com noble InRelease [12.9 kB]
Get:3 https://apt.releases.hashicorp.com noble/main amd64 Packages [210 kB]
Hit:4 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:5 http://security.ubuntu.com/ubuntu noble-security InRelease
Hit:6 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:7 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Hit:8 https://ppa.launchpadcontent.net/cncf-buildpacks/pack-cli/ubuntu noble InRelease
Fetched 223 kB in 1s (196 kB/s)
Reading package lists... Done
(⎈|kind-myk8s:vault) zosys@4:~$ sudo apt-get install -y vault
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
vault
0 upgraded, 1 newly installed, 0 to remove and 48 not upgraded.
Need to get 169 MB of archives.
After this operation, 512 MB of additional disk space will be used.
Get:1 https://apt.releases.hashicorp.com noble/main amd64 vault amd64 1.21.1-1 [169 MB]
Fetched 169 MB in 14s (11.9 MB/s)
Selecting previously unselected package vault.
(Reading database ... 93628 files and directories currently installed.)
Preparing to unpack .../vault_1.21.1-1_amd64.deb ...
Unpacking vault (1.21.1-1) ...
Setting up vault (1.21.1-1) ...
Generating Vault TLS key and self-signed certificate...
..+...+....+...+.....+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+....+.....+......+.+..+............+...+...+...+......+......+.......+...+.........+...............+......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*........+.+...+..+..........+..............+..........+...+........+..........+..............+...+.+..+.......+...............+...............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......+.+.............................+..........+..+.........+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.........+.+.....+.+..+..........+........+..........+...+..+...................+...+...+..+......+..........+...........+.+.....+.......+.................+....+.................+...............+....+....................................+........+....+...........+......+.+..............+...+...+............+.+.....+.........+................+...........+................+..+...+...+......+.............+......+.........+..+...+.+.....+.......+........+.........+......+.........+.......+..............+.+.....+.............+..+....+..............+..........+......+.....+.........+................+..+.......+..+......+...+......+.+........+....+..+............................+...+...+......+..............+.......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
Vault TLS key and self-signed certificate have been generated in '/opt/vault/tls'.
(⎈|kind-myk8s:vault) zosys@4:~$ vault --version
Vault v1.21.1 (2453aac2638a6ae243341b4e0657fd8aea1cbf18), built 2025-11-18T13:04:32Z
(⎈|kind-myk8s:vault) zosys@4:~$ export VAULT_ADDR='http://localhost:30000'
(⎈|kind-myk8s:vault) zosys@4:~$ 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-5d53df9b
Cluster ID 195a8699-aff7-c091-925e-8fb0d437777b
HA Enabled false
(⎈|kind-myk8s:vault) zosys@4:~$ vatuls login
vatuls: command not found
(⎈|kind-myk8s:vault) zosys@4:~$ 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 root
token_accessor Z79KiTYlABr4QrIXgYNfLsyn
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]

실습
KV시크릿 엔진 활성화 및 샘플구성 → 정적시크릿(Static Secret)
(⎈|kind-myk8s:vault) zosys@4:~$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_668bf8fc per-token private secret storage
identity/ identity identity_827e2b1e identity store
secret/ kv kv_eb39bee4 key/value secret storage
sys/ system system_07d18235 system endpoints used for control, policy and debugging
(⎈|kind-myk8s:vault) zosys@4:~$ vault kv put secret/sampleapp/config \
username="demo" \
password="p@ssw0rd"
======== Secret Path ========
secret/data/sampleapp/config
======= Metadata =======
Key Value
--- -----
created_time 2025-11-24T15:27:21.004785439Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
(⎈|kind-myk8s:vault) zosys@4:~$ vault kv get secret/sampleapp/config
======== Secret Path ========
secret/data/sampleapp/config
======= Metadata =======
Key Value
--- -----
created_time 2025-11-24T15:27:21.004785439Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password p@ssw0rd
username demo

Vault Agent와 Sidecar 패턴
실습
1. Vault AppRole 방식 인증 구성
- 인증 구성 및 정책 적용
(⎈|kind-myk8s:vault) zosys@4:~$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
token/ token auth_token_6a22d402 token based credentials n/a
(⎈|kind-myk8s:vault) zosys@4:~$ vault policy write sampleapp-policy - <<EOF
> path "secret/data/sampleapp/*" {
> capabilities = ["read"]
> }
> EOF
Success! Uploaded policy: sampleapp-policy
(⎈|kind-myk8s:vault) zosys@4:~$ vault write auth/approle/role/sampleapp-role token_policies="sampleapp-policy" secret_id_ttl="100h" token_ttl="100h" token_max_ttl="200h"
Success! Data written to: auth/approle/role/sampleapp-role
(⎈|kind-myk8s:vault) zosys@4:~$ SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/sampleapp-role/secret-id)
(⎈|kind-myk8s:vault) zosys@4:~$ echo $ROLE_ID
b3712987-c900-3f0f-d381-e86c19c0ec72
(⎈|kind-myk8s:vault) zosys@4:~$ echo $SECRET_ID
098b8b14-dc3a-fe6f-d777-efe805f7a48c
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl create secret generic vault-approle -n vault \
> --from-literal=role_id="${ROLE_ID}" \
> --from-literal=secret_id="${SECRET_ID}" \
> --save-config \
> --dry-run=client -o yaml | kubectl apply -f -
secret/vault-approle created
2. Vault Agent Sidecar연동
(⎈|kind-myk8s:vault) zosys@4:~$ cat << EOF | kubectl create configmap vault-agent-config -n vault --from-file=agent-config.hcl=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -
> vault {
> address = "http://vault.vault.svc:8200"
> }
>
> auto_auth {
> method "approle" {
> config = {
> role_id_file_path = "/etc/vault/approle/role_id"
> secret_id_file_path = "/etc/vault/approle/secret_id"
> remove_secret_id_file_after_reading = false
> }
> }
>
> sink "file {
> config = {
> path = "/etc/vault-agent-token/token"
> }
> }
> }
>
> template_config {
> static_secret_render_interval = "20s"
> }
>
> template {
> destination = "/etc/secrets/index.html"
> contents = <<EOH
> <html>
> <body>
> <p>username: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.username}} {{ end }}</p>
> <p>password {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.password}} {{ end }}</p>
> </body>
> </html>
> EOH
> }
> EOF
configmap/vault-agent-config created
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl apply -n vault -f test.yaml
deployment.apps/nginx-vault-demo created
(⎈|kind-myk8s:vault) zosys@4:~$ cat test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-vault-demo
spec:
replicas: 1
selector:
matchLabels:
app: nginx-vault-demo
template:
metadata:
labels:
app: nginx-vault-demo
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: html-volume
mountPath: /usr/share/nginx/html
- name: vault-agent-sidecar
image: hashicorp/vault:latest
args:
- "agent"
- "-config=/etc/vault/agent-config.hcl"
volumeMounts:
- name: vault-agent-config
mountPath: /etc/vault
- name: vault-approle
mountPath: /etc/vault/approle
- name: vault-token
mountPath: /etc/vault-agent-token
- name: html-volume
mountPath: /etc/secrets
volumes:
- name: vault-agent-config
configMap:
name: vault-agent-config
- name: vault-approle
secret:
secretName: vault-approle
- name: vault-token
emptyDir: {}
- name: html-volume
emptyDir: {}
3. SVC생성
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx-vault-demo
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001
EOF
service/nginx-service created
4. 컨테이너 확인
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl get pod -l app=nginx-vault-demo
NAME READY STATUS RESTARTS AGE
nginx-vault-demo-7776649597-2jk4f 2/2 Running 0 10s
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl describe pod -l app=nginx-vault-demo
Name: nginx-vault-demo-7776649597-2jk4f
Namespace: vault
Priority: 0
Service Account: default
Node: myk8s-control-plane/172.18.0.2
Start Time: Thu, 27 Nov 2025 01:27:58 +0900
Labels: app=nginx-vault-demo
pod-template-hash=7776649597
Annotations: <none>
Status: Running
IP: 10.244.0.8
IPs:
IP: 10.244.0.8
Controlled By: ReplicaSet/nginx-vault-demo-7776649597
-------------------------중략 -------------------------------
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io
NAME WEBHOOKS AGE
vault-agent-injector-cfg 1 2d1h
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- vault agent -h
Usage: vault agent [options]
This command starts a Vault Agent that can perform automatic authentication
in certain environments.
Start an agent with a configuration file:
$ vault agent -config=/etc/vault/config.hcl
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/approle/secret_id
87fb5719-5b31-dd97-e701-08ba809d3121(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/approle/role_id
b3712987-c900-3f0f-d381-e86c19c0ec72(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/approle/role_id
(⎈|kind-myk8s:vault) zosys@4:~$ ec72(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vls -l /etc/vault/approlear -- cat /etc/vault/approle/role_id
total 0
lrwxrwxrwx 1 root root 14 Nov 26 16:27 role_id -> ..data/role_id
lrwxrwxrwx 1 root root 16 Nov 26 16:27 secret_id -> ..data/secret_id
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/agent-config.hcl
vault {
address = "http://vault.vault.svc:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/etc/vault/approle/role_id"
secret_id_file_path = "/etc/vault/approle/secret_id"
remove_secret_id_file_after_reading = false
}
}
sink "file" {
config = {
path = "/etc/vault-agent-token/token"
}
}
}
template_config {
static_secret_render_interval = "20s"
}
template {
destination = "/etc/secrets/index.html"
contents = <<EOH
<html>
<body>
<p>username: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.username }}{{ end }}</p>
<p>password: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.password }}{{ end }}</p>
</body>
</html>
EOH
}
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c nginx -- ls -l /usr/share/nginx/html
total 4
-rw-r--r-- 1 100 1000 94 Nov 26 16:28 index.html
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n vault deploy/nginx-vault-demo -c nginx -- cat /usr/share/nginx/html/index.html
<html>
<body>
<p>username: demo</p>
<p>password: p@ssw0rd</p>
</body>
</html>
5. 실제 배포된 화면 확인

6. 변경후 재배포 확인


4. Jenkins + Vault (AppRole) - CI
실습1. Jenkins + KV 시크릿
1. 젠킨스는 두가지 방법 중 Pod배포 방식으로 진행
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl create ns jenkins
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
-------중략-----------
namespace/jenkins created
persistentvolumeclaim/jenkins-pvc created
deployment.apps/jenkins created
service/jenkins-svc created
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl get deploy,svc,ep,pvc -n jenkins
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/jenkins 1/1 1 1 2m21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/jenkins-svc NodePort 10.96.150.6 <none> 8080:30001/TCP,50000:31211/TCP 2m21s
NAME ENDPOINTS AGE
endpoints/jenkins-svc 10.244.0.10:50000,10.244.0.10:8080 2m21s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/jenkins-pvc Bound pvc-ea0d13e8-ea9d-49cf-879c-578d1532fbc3 10Gi RWO standard <unset> 2m21s
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n jenkins deploy/jenkins -- cat /var/jenkins_home/secrets/initialAdminPassword
0db0da89485340638ecf03a53599de62
*배포 및 어드민설정/Vault플러그인 설치


2. Vault Approle정보 확인
(⎈|kind-myk8s:vault) zosys@4:~/approle-creds$ cat role_id.txt
b3712987-c900-3f0f-d381-e86c19c0ec72
(⎈|kind-myk8s:vault) zosys@4:~/approle-creds$ cat secret_id.txt
87fb5719-5b31-dd97-e701-08ba809d3121
3. vault plugin 설치 및 credential 설정

4. 파이프 라인 작성 및 구동. pod배포시에 시스템 설정 및 젠킨스파이프라인내에 http://vault.vault.svc:8200로 설정할것.

실습2. Jenkins + 동적(Dynamic) DB 시크릿
1. 인프라 구성
(⎈|kind-myk8s:vault) zosys@4:~$ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: default
spec:
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
env:
- name: POSTGRES_PASSWORD
value: "rootpassword"
- name: POSTGRES_DB
value: "mydb"
ports:
- containerPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: default
spec:
type: NodePort
ports:
- port: 5432
targetPort: 5432
nodePort: 30002 # [External] Jenkins 접속용
selector:
app: postgres
EOF
deployment.apps/postgres created
service/postgres created
2. Vault DB Engine 설정
(⎈|kind-myk8s:vault) zosys@4:~$ export VAULT_ADDR=http://127.0.0.1:30000
(⎈|kind-myk8s:vault) zosys@4:~$ export VAULT_TOKEN=root
(⎈|kind-myk8s:vault) zosys@4:~$ vault secrets enable database
Success! Enabled the database secrets engine at: database/
(⎈|kind-myk8s:vault) zosys@4:~$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_668bf8fc per-token private secret storage
database/ database database_43519aa6 n/a
identity/ identity identity_827e2b1e identity store
secret/ kv kv_eb39bee4 key/value secret storage
sys/ system system_07d18235 system endpoints used for control, policy and debugging
(⎈|kind-myk8s:vault) zosys@4:~$ vault write database/config/my-postgresql-database \
plugin_name=postgresql-database-plugin \
allowed_roles="jenkins-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres.default.svc.cluster.local:5432/mydb?sslmode=disable" \
username="postgres" \
password="rootpassword"
Success! Data written to: database/config/my-postgresql-database
(⎈|kind-myk8s:vault) zosys@4:~$ vault write database/roles/jenkins-role \
db_name=my-postgresql-database \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
Success! Data written to: database/roles/jenkins-role
3. 기존 AppRole 권한 확장 진행
(⎈|kind-myk8s:vault) zosys@4:~$ vault policy write sampleapp-policy - <<EOF
# 1. KV v2 데이터 읽기
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
# 2. KV v2 목록 조회 (플러그인 에러 방지용 필수!)
path "secret/metadata/sampleapp/*" {
capabilities = ["list", "read"]
}
# 3. DB Creds 발급
path "database/creds/jenkins-role" {
capabilities = ["read"]
}
EOF
Success! Uploaded policy: sampleapp-policy
(⎈|kind-myk8s:vault) zosys@4:~$ vault policy read sampleapp-policy
# 1. KV v2 데이터 읽기
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
# 2. KV v2 목록 조회 (플러그인 에러 방지용 필수!)
path "secret/metadata/sampleapp/*" {
capabilities = ["list", "read"]
}
# 3. DB Creds 발급
path "database/creds/jenkins-role" {
capabilities = ["read"]
}
(⎈|kind-myk8s:vault) zosys@4:~$ vault write auth/approle/role/sampleapp-role \
token_policies="default,sampleapp-policy" \
secret_id_ttl="0" \
token_ttl="1h" \
token_max_ttl="4h"
Success! Data written to: auth/approle/role/sampleapp-role

4. 젠킨스 파이프라인 작성

(⎈|kind-myk8s:vault) zosys@4:~$ kubectl exec -it -n default deploy/postgres -- psql -U postgres
psql (13.23 (Debian 13.23-1.pgdg13+1))
Type "help" for help.
postgres=# \du
List of roles
Role name | Attributes | Member of
----------------------------------------------------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
v-approle-jenkins--sKg8NpSTXnFzluA9jTvf-1764314075 | Password valid until 2025-11-28 08:14:40+00 | {}
5. 암호화(Encryption)와 Vault Transit엔진
이번 실습에서 주로 다룰 내용은 계층별 암호화 방안 중 애플리케이션 계층에 대한 암호화를 진행한다.
실습
0. 사전준비
(⎈|kind-myk8s:vault) zosys@4:~$ export NS=vault-demo
export IMAGE=hyungwookhub/vault-transit-demo:v1 # 이번 실습에서는 제 개인 저장소에 업로드한 이미지를 사용
# export IMAGE=DOCKER_HUB_USER/vault-transit-demo:latest # 본인 계정으로 교체
export VAULT_ADDR=http://localhost:30000 # NodePort 엔드포인트
export VAULT_TOKEN=root # 실습용 토큰
1. Vault Transit활성화
(⎈|kind-myk8s:vault) zosys@4:~$ 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-5d53df9b
Cluster ID 195a8699-aff7-c091-925e-8fb0d437777b
HA Enabled false
(⎈|kind-myk8s:vault) zosys@4:~$ vault secrets enable transit
Success! Enabled the transit secrets engine at: transit/
(⎈|kind-myk8s:vault) zosys@4:~$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_668bf8fc per-token private secret storage
database/ database database_43519aa6 n/a
identity/ identity identity_827e2b1e identity store
secret/ kv kv_eb39bee4 key/value secret storage
sys/ system system_07d18235 system endpoints used for control, policy and debugging
transit/ transit transit_692f884a n/a
(⎈|kind-myk8s:vault) zosys@4:~$ vault write -f transit/keys/ds-poc type=aes256-gcm96
Key Value
--- -----
allow_plaintext_backup false
auto_rotate_period 0s
deletion_allowed false
derived false
exportable false
imported_key false
keys map[1:1764317025]
latest_version 1
min_available_version 0
min_decryption_version 1
min_encryption_version 0
name ds-poc
supports_decryption true
supports_derivation true
supports_encryption true
supports_signing false
type aes256-gcm96
(⎈|kind-myk8s:vault) zosys@4:~$ vault list transit/keys
Keys
----
ds-poc
(⎈|kind-myk8s:vault) zosys@4:~$ PLAINTEXT="My Data"
(⎈|kind-myk8s:vault) zosys@4:~$ CIPHERTEXT=$(vault write -field=ciphertext transit/encrypt/ds-poc \
plaintext=$(echo -n "$PLAINTEXT" | base64))
(⎈|kind-myk8s:vault) zosys@4:~$ echo "ciphertext: $CIPHERTEXT"
ciphertext: vault:v1:aR/otS5ymKQcqqKN/jQ8RBVIQDf+4voBtzKXbKbwnUaosy4=
(⎈|kind-myk8s:vault) zosys@4:~$ vault write -field=plaintext transit/decrypt/ds-poc \
ciphertext="$CIPHERTEXT" | base64 -d && echo
My Data
2. MYSQL 배포진행 (NodePort 30002)
(⎈|kind-myk8s:vault) zosys@4:~$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: ${NS}
---
---------중략-------------
namespace/vault-demo created
deployment.apps/mysql created
service/mysql created
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl -n ${NS} rollout status deploy/mysql
deployment "mysql" successfully rolled out
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl -n ${NS} exec -it deploy/mysql -- \
mysql -uroot -prootpassword -e "CREATE DATABASE IF NOT EXISTS VaultData;"
mysql: [Warning] Using a password on the command line interface can be insecure.
(⎈|kind-myk8s:vault) zosys@4:~$ kubectl -n ${NS} exec -it deploy/mysql -- \
mysql -uroot -prootpassword -e "SHOW DATABASES LIKE 'VaultData';"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------------+
| Database (VaultData) |
+----------------------+
| VaultData |
+----------------------+
3. Transit Demo APP 배포
(⎈|kind-myk8s:vault) zosys@4:~$ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-transit-demo
namespace: ${NS}
-----중략----------
deployment.apps/vault-transit-demo created
service/vault-transit-demo created


(⎈|kind-myk8s:vault) zosys@4:~$ kubectl -n ${NS} exec -it deploy/mysql -- \
mysql -uroot -prootpassword -e "USE VaultData; SHOW TABLES; SELECT id,data,date_created FROM vault_data;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------------+
| Tables_in_VaultData |
+---------------------+
| vault_data |
+---------------------+
+----+-----------------------------------------------------------+----------------------------+
| id | data | date_created |
+----+-----------------------------------------------------------+----------------------------+
| 1 | vault:v1:jAuhJlZtaoX20eeh87hXjQ1toUpyYjleuCK9roZWVi5VyF3w | 2025-11-28 17:11:09.457000 |
+----+-----------------------------------------------------------+----------------------------+
(⎈|kind-myk8s:vault) zosys@4:~$ echo "hello vault transit" > original.txt
(⎈|kind-myk8s:vault) zosys@4:~$ md5sum original.txt
5b92abfe363ae7212a37a55f96bf5967 original.txt


4.원본파일과 복호화파일 해쉬값비교
(⎈|kind-myk8s:vault) zosys@4:~$ md5sum original.txt
5b92abfe363ae7212a37a55f96bf5967 original.txt
(⎈|kind-myk8s:vault) zosys@4:~$ md5sum original.txt.enc
63b7c4829152bfb93fc8c8a7101f7cab original.txt.enc
(⎈|kind-myk8s:vault) zosys@4:~$ md5sum original.dec.txt
5b92abfe363ae7212a37a55f96bf5967 original.dec.tx