
가시다(gasida) 님이 진행하는 AEWS(Amazon EKS Workshop Study) 3기 과정으로 학습한 내용을 정리 또는 실습한 내용을 정리한 게시글입니다.10주차는 하시코프 유형욱님이 K8s Secret 관련 주제로 Vault 소개와 실습(macOS환경)을 진행해 주셨고 이를 정리한 글입니다.
❤️❤️❤️ 열혈한 강의를 하여주신 하시코프 유형욱님께 깊은 감사를 드립니다 ❤️❤️❤️
# 작업 디렉토리 생성 후 이동
mkdir cicd-labs
cd cicd-labs
# cicd-labs 작업 디렉토리 IDE(VSCODE 등)로 열어두기
code .
#
cat <<EOT > docker-compose.yaml
services:
jenkins:
container_name: jenkins
image: jenkins/jenkins
restart: unless-stopped
networks:
- cicd-network
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- jenkins_home:/var/jenkins_home
volumes:
jenkins_home:
networks:
cicd-network:
driver: bridge
EOT
# 배포
docker compose up -d
[+] Running 12/12
✔ jenkins Pulled 24.2s
✔ e4b8da63e67a Pull complete 1.0s
✔ cb6b359ad2fe Pull complete 1.0s
✔ 08f6bab0cb52 Pull complete 6.5s
✔ 599265d0bee4 Pull complete 20.9s
✔ 8f7a49bcaa0e Pull complete 19.5s
✔ ec2511b50f87 Pull complete 1.3s
✔ 74901fce1a6a Pull complete 1.1s
✔ d15499e83589 Pull complete 1.0s
✔ f4657d27c8ae Pull complete 19.6s
✔ 2a5996dba6d5 Pull complete 1.1s
✔ e184c2818798 Pull complete 19.8s
[+] Running 3/3
✔ Network cicd-labs_cicd-network Created 0.0s
✔ Volume "cicd-labs_jenkins_home" Created 0.0s
✔ Container jenkins Started 0.5s
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
jenkins jenkins/jenkins "/usr/bin/tini -- /u…" jenkins 32 seconds ago Up 32 seconds 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp
# 기본 정보 확인
for i in jenkins ; do echo ">> container : $i <<"; docker compose exec
$i sh -c "whoami && pwd"; echo; done
>> container : jenkins <<
jenkins
/
# 도커를 이용하여 각 컨테이너로 접속
docker compose exec jenkins bash
jenkins@8dfb955f0f5a:/$ ls
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
exit
# Jenkins 초기 암호 확인
docker compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
d770512bf50141ef942cd7620954b80a
# Jenkins 웹 접속 주소 확인 : 계정 / 암호 입력 >> admin / qwe123
open "http://127.0.0.1:8080" # macOS
웹 브라우저에서 http://127.0.0.1:8080 접속 # Windows
# (참고) 로그 확인 : 플러그인 설치 과정 확인
docker compose logs jenkins -f
jenkins | Running from: /usr/share/jenkins/jenkins.war
jenkins | webroot: /var/jenkins_home/war
jenkins | 2025-04-10 22:04:47.117+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file
jenkins | 2025-04-10 22:04:47.555+0000 [id=1] WARNING o.e.j.ee9.nested.ContextHandler#setContextPath: Empty contextPath
jenkins | 2025-04-10 22:04:47.582+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-12.0.19; built: 2025-04-01T13:28:40.005Z; git: 23436cd577b4238238eb192683dfc2b1476c6b87; jvm 17.0.14+7
jenkins | 2025-04-10 22:04:47.783+0000 [id=1] INFO o.e.j.e.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.ee9.jsp.JettyJspServlet
jenkins | 2025-04-10 22:04:47.805+0000 [id=1] INFO o.e.j.s.DefaultSessionIdManager#doStart: Session workerName=node0
jenkins | 2025-04-10 22:04:48.070+0000 [id=1] INFO hudson.WebAppMain#contextInitialized: Jenkins home directory: /var/jenkins_home found at: EnvVars.masterEnvVars.get("JENKINS_HOME")
jenkins | 2025-04-10 22:04:48.135+0000 [id=1] INFO o.e.j.s.handler.ContextHandler#doStart: Started
....
jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
jenkins | 2025-04-10 22:12:01.815+0000 [id=257] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization
jenkins | 2025-04-10 22:12:01.816+0000 [id=93] INFO h.m.UpdateCenter$CompleteBatchJob#run: Completed installation of 88 plugins in 1 min 58 sec

# 클러스터 배포 전 확인
docker ps
# Create a cluster with kind
MyIP=<각자 자신의 PC IP>
MyIP=192.168.0.254
# cicd-labs 디렉터리에서 아래 파일 작성
cat > kind-3node.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "192.168.0.254" # $MyIP로 설정하셔도 됩니다.
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
- containerPort: 30004
hostPort: 30004
- containerPort: 30005
hostPort: 30005
- containerPort: 30006
hostPort: 30006
- role: worker
- role: worker
EOF
kind create cluster --config kind-3node.yaml --name myk8s --image kindest/node:v1.32.2
Creating cluster "myk8s" ...
✓ Ensuring node image (kindest/node:v1.32.2) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-myk8s"
You can now use your cluster with:
kubectl cluster-info --context kind-myk8s
Have a nice day! 👋
# 확인
kind get nodes --name myk8s
myk8s-worker
myk8s-worker2
myk8s-control-plane
kubens default
Context "kind-myk8s" modified.
Active namespace is "default".
# kind 는 별도 도커 네트워크 생성 후 사용 : 기본값 172.18.0.0/16
docker network ls
NETWORK ID NAME DRIVER SCOPE
4cbcf5d6ed31 bridge bridge local
ed7574143b6e cicd-labs_cicd-network bridge local
88153fefe41f host host local
4a1bac68fb38 kind bridge local
6e2fe0aabee3 none null local
docker inspect kind | jq
[
{
"Name": "kind",
"Id": "4a1bac68fb3814234d8ace297f7410f75b157df2ee87eb6d8b2bd8cbfac7a175",
"Created": "2025-03-29T07:40:25.439081048Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv4": true,
"EnableIPv6": true,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
},
{
"Subnet": "fc00:f853:ccd:e793::/64",
"Gateway": "fc00:f853:ccd:e793::1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"128365a166f5096ec30ee1eb0561e58ae6eb9ae98ebd51cba451f8267348dc1f": {
"Name": "myk8s-control-plane",
"EndpointID": "1eabfaf860ac8781d6de543770fc6354862632a391b820f726fffda9ddcf8712",
"MacAddress": "ea:9e:6d:60:59:63",
"IPv4Address": "172.19.0.4/16",
"IPv6Address": "fc00:f853:ccd:e793::4/64"
},
"6cd290d85e574cf531326608203b805a4d1cf625e35539b000c8dd6672dc0b29": {
"Name": "myk8s-worker",
"EndpointID": "4104a3e5cb42413234ba1597ef14c8e17df1b9f1ecc08546fab0ccdd94ae6e85",
"MacAddress": "e6:22:76:e3:cd:e4",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": "fc00:f853:ccd:e793::2/64"
},
"e14b3bc36f7da01e4858b05627bbfea7d5d24b0550c132abc40ea9bb67eb1ac1": {
"Name": "myk8s-worker2",
"EndpointID": "a14db4663da7ce0e27804d31dd8d0cbf70cae2c97852dbc8814ea24d6dcf567a",
"MacAddress": "8a:7b:5d:cc:7b:02",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": "fc00:f853:ccd:e793::3/64"
}
},
"Options": {
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.driver.mtu": "65535"
},
"Labels": {}
}
]
# k8s api 주소 확인 : 어떻게 로컬에서 접속이 되는 걸까?
kubectl cluster-info
Kubernetes control plane is running at https://192.168.0.254:51857
CoreDNS is running at https://192.168.0.254:51857/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
# 노드 정보 확인 : CRI 는 containerd 사용
kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
myk8s-control-plane Ready control-plane 2m44s v1.32.2 172.19.0.4 <none> Debian GNU/Linux 12 (bookworm) 6.10.14-linuxkit containerd://2.0.3
myk8s-worker Ready <none> 2m29s v1.32.2 172.19.0.2 <none> Debian GNU/Linux 12 (bookworm) 6.10.14-linuxkit containerd://2.0.3
myk8s-worker2 Ready <none> 2m29s v1.32.2 172.19.0.3 <none> Debian GNU/Linux 12 (bookworm) 6.10.14-linuxkit containerd://2.0.3
# 파드 정보 확인 : CNI 는 kindnet 사용
kubectl get pod -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-668d6bf9bc-c5hfz 1/1 Running 0 3m12s 10.244.0.3 myk8s-control-plane <none> <none>
kube-system coredns-668d6bf9bc-qcbsk 1/1 Running 0 3m12s 10.244.0.2 myk8s-control-plane <none> <none>
kube-system etcd-myk8s-control-plane 1/1 Running 0 3m20s 172.19.0.4 myk8s-control-plane <none> <none>
kube-system kindnet-2zqzf 1/1 Running 0 3m13s 172.19.0.4 myk8s-control-plane <none> <none>
kube-system kindnet-lqjkz 1/1 Running 0 3m7s 172.19.0.3 myk8s-worker2 <none> <none>
kube-system kindnet-mhn4s 1/1 Running 0 3m7s 172.19.0.2 myk8s-worker <none> <none>
kube-system kube-apiserver-myk8s-control-plane 1/1 Running 0 3m20s 172.19.0.4 myk8s-control-plane <none> <none>
kube-system kube-controller-manager-myk8s-control-plane 1/1 Running 0 3m20s 172.19.0.4 myk8s-control-plane <none> <none>
kube-system kube-proxy-kl79h 1/1 Running 0 3m7s 172.19.0.3 myk8s-worker2 <none> <none>
kube-system kube-proxy-skx7l 1/1 Running 0 3m7s 172.19.0.2 myk8s-worker <none> <none>
kube-system kube-proxy-zrplw 1/1 Running 0 3m13s 172.19.0.4 myk8s-control-plane <none> <none>
kube-system kube-scheduler-myk8s-control-plane 1/1 Running 0 3m20s 172.19.0.4 myk8s-control-plane <none> <none>
local-path-storage local-path-provisioner-7dc846544d-f6bl2 1/1 Running 0 3m12s 10.244.0.4 myk8s-control-plane <none> <none>
# 네임스페이스 확인 >> 도커 컨테이너에서 배운 네임스페이스와 다릅니다!
kubectl get namespaces
NAME STATUS AGE
default Active 3m47s
kube-node-lease Active 3m47s
kube-public Active 3m47s
kube-system Active 3m47s
local-path-storage Active 3m43s
# 컨트롤플레인/워커 노드(컨테이너) 확인 : 도커 컨테이너 이름은 myk8s-control-plane , myk8s-worker/worker-2 임을 확인
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6cd290d85e57 kindest/node:v1.32.2 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes myk8s-worker
e14b3bc36f7d kindest/node:v1.32.2 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes myk8s-worker2
128365a166f5 kindest/node:v1.32.2 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes 0.0.0.0:30000-30006->30000-30006/tcp, 192.168.0.254:51857->6443/tcp myk8s-control-plane
8dfb955f0f5a jenkins/jenkins "/usr/bin/tini -- /u…" 21 minutes ago Up 21 minutes 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp jenkins
docker images
# 디버그용 내용 출력에 ~/.kube/config 권한 인증 로드
kubectl get pod -v6
I0411 07:26:20.973604 73279 loader.go:402] Config loaded from file: /Users/sjkim/.kube/config
I0411 07:26:20.974632 73279 envvar.go:172] "Feature gate default state" feature="ClientsPreferCBOR" enabled=false
I0411 07:26:20.974640 73279 envvar.go:172] "Feature gate default state" feature="InformerResourceVersion" enabled=false
I0411 07:26:20.974643 73279 envvar.go:172] "Feature gate default state" feature="WatchListClient" enabled=false
I0411 07:26:20.974644 73279 envvar.go:172] "Feature gate default state" feature="ClientsAllowCBOR" enabled=false
I0411 07:26:20.996491 73279 round_trippers.go:560] GET https://192.168.0.254:51857/api/v1/namespaces/default/pods?limit=500 200 OK in 18 milliseconds
No resources found in default namespace.
# kube config 파일 확인
cat ~/.kube/config
# 네임스페이스 생성 및 파라미터 파일 작성
cd cicd-labs
kubectl create ns argocd
cat <<EOF > argocd-values.yaml
dex:
enabled: false
server:
service:
type: NodePort
nodePortHttps: 30002
extraArgs:
- --insecure # HTTPS 대신 HTTP 사용
EOF
# 설치
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd --version 7.8.13 -f argocd-values.yaml --namespace argocd
NAME: argocd
LAST DEPLOYED: Fri Apr 11 07:29:57 2025
NAMESPACE: argocd
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
In order to access the server UI you have the following options:
1. kubectl port-forward service/argocd-server -n argocd 8080:443
and then open the browser on http://localhost:8080 and accept the certificate
2. enable ingress in the values file `server.ingress.enabled` and either
- Add the annotation for ssl passthrough: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-1-ssl-passthrough
- Set the `configs.params."server.insecure"` in the values file and terminate SSL at your ingress: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-2-multiple-ingress-objects-and-hosts
After reaching the UI the first time you can login with username: admin and the random password generated during the installation. You can find the password by running:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
(You should delete the initial secret afterwards as suggested by the Getting Started Guide: https://argo-cd.readthedocs.io/en/stable/getting_started/#4-login-using-the-cli)
# 확인
kubectl get pod,svc,ep,secret,cm -n argocd
NAME READY STATUS RESTARTS AGE
pod/argocd-application-controller-0 1/1 Running 0 93s
pod/argocd-applicationset-controller-cccb64dc8-9n4hz 1/1 Running 0 93s
pod/argocd-notifications-controller-7cd4d88cd4-28b5x 1/1 Running 0 93s
pod/argocd-redis-6c5698fc46-xp8n6 1/1 Running 0 93s
pod/argocd-repo-server-5f6c4f4cf4-p7fdv 1/1 Running 0 93s
pod/argocd-server-7cb958f5fb-8qblv 1/1 Running 0 93s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/argocd-applicationset-controller ClusterIP 10.96.69.180 <none> 7000/TCP 93s
service/argocd-redis ClusterIP 10.96.220.240 <none> 6379/TCP 93s
service/argocd-repo-server ClusterIP 10.96.49.203 <none> 8081/TCP 93s
service/argocd-server NodePort 10.96.72.188 <none> 80:30080/TCP,443:30002/TCP 93s
NAME ENDPOINTS AGE
endpoints/argocd-applicationset-controller 10.244.1.3:7000 93s
endpoints/argocd-redis 10.244.1.2:6379 93s
endpoints/argocd-repo-server 10.244.2.4:8081 93s
endpoints/argocd-server 10.244.2.5:8080,10.244.2.5:8080 93s
NAME TYPE DATA AGE
secret/argocd-initial-admin-secret Opaque 1 92s
secret/argocd-notifications-secret Opaque 0 94s
secret/argocd-redis Opaque 1 96s
secret/argocd-secret Opaque 3 94s
secret/sh.helm.release.v1.argocd.v1 helm.sh/release.v1 1 2m3s
NAME DATA AGE
configmap/argocd-cm 9 94s
configmap/argocd-cmd-params-cm 32 94s
configmap/argocd-gpg-keys-cm 0 94s
configmap/argocd-notifications-cm 1 94s
configmap/argocd-rbac-cm 4 94s
configmap/argocd-redis-health-configmap 2 94s
configmap/argocd-ssh-known-hosts-cm 1 94s
configmap/argocd-tls-certs-cm 0 94s
configmap/kube-root-ca.crt 1 3m31s
kubectl get crd | grep argo
applications.argoproj.io 2025-04-10T22:30:27Z
applicationsets.argoproj.io 2025-04-10T22:30:28Z
appprojects.argoproj.io 2025-04-10T22:30:27Z
kubectl get appproject -n argocd -o yaml
apiVersion: v1
items:
- apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
creationTimestamp: "2025-04-10T22:30:29Z"
generation: 1
name: default
namespace: argocd
resourceVersion: "1457"
uid: b8160841-af21-421d-8fe0-3d5a926bce72
spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
destinations:
- namespace: '*'
server: '*'
sourceRepos:
- '*'
status: {}
kind: List
metadata:
resourceVersion: ""
# configmap
kubectl get cm -n argocd argocd-cm -o yaml
apiVersion: v1
data:
admin.enabled: "true"
application.instanceLabelKey: argocd.argoproj.io/instance
application.sync.impersonation.enabled: "false"
exec.enabled: "false"
server.rbac.log.enforce.enable: "false"
statusbadge.enabled: "false"
timeout.hard.reconciliation: 0s
timeout.reconciliation: 180s
url: https://argocd.example.com
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
creationTimestamp: "2025-04-10T22:30:27Z"
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.14.7
helm.sh/chart: argo-cd-7.8.13
name: argocd-cm
namespace: argocd
kubectl get cm -n argocd argocd-rbac-cm -o yaml
apiVersion: v1
data:
policy.csv: ""
policy.default: ""
policy.matchMode: glob
scopes: '[groups]'
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
creationTimestamp: "2025-04-10T22:30:27Z"
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-rbac-cm
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.14.7
helm.sh/chart: argo-cd-7.8.13
name: argocd-rbac-cm
namespace: argocd
# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
Po-147u8y9vTWqur
# Argo CD 웹 접속 주소 확인 : 초기 암호 입력 (admin 계정)
open "http://127.0.0.1:30002" # macOS
# Windows OS경우 직접 웹 브라우저에서 http://127.0.0.1:30002 접속

참조 : What is Vault?
HashiCorp Vault는 신원 기반(identity-based)의 시크릿 및 암호화 관리 시스템입니다. 이 시스템은 인증(authentication) 및 인가(authorization) 방법을 통해 암호화 서비스를 제공하여 비밀에 대한 안전하고 감사 가능하며 제한된 접근을 보장합니다.
시크릿(Secret)이란 접근을 철저히 통제하고자 하는 모든 것을 의미하며, 예를 들어 토큰, API 키, 비밀번호, 암호화 키 또는 인증서 등이 이에 해당합니다. Vault는 모든 시크릿에 대해 통합된 인터페이스를 제공하면서, 엄격한 접근 제어와 상세한 감사 로그 기록 기능을 제공합니다.
외부 서비스용 API 키, 서비스 지향 아키텍처 간 통신을 위한 자격 증명 등은 플랫폼에 따라 누가 어떤 비밀에 접근했는지를 파악하기 어려울 수 있습니다. 여기에 키 롤링(교체), 안전한 저장, 상세한 감사 로그까지 추가하려면 별도의 커스텀 솔루션 없이는 거의 불가능합니다. Vault는 바로 이 지점에서 해결책을 제공합니다.
Vault는 클라이언트(사용자, 기계, 애플리케이션 등)를 검증하고 인가한 후에만 비밀이나 저장된 민감한 데이터에 접근할 수 있도록 합니다.


Vault는 주로 토큰(Token)을 기반으로 작동하며, 이 토큰은 클라이언트의 정책(Policy)과 연결되어 있습니다. 각 정책은 경로(path) 기반으로 설정되며, 정책 규칙은 클라이언트가 해당 경로에서 수행할 수 있는 작업과 접근 가능성을 제한합니다.
Vault에서는 토큰을 수동으로 생성해 클라이언트에 할당할 수도 있고, 클라이언트가 로그인하여 토큰을 직접 획득할 수도 있습니다.
아래 그림은 Vault의 핵심 워크플로우를 보여줍니다.

Vault의 핵심 워크플로우는 다음 네 단계로 구성됩니다:
오늘날 대부분의 기업은 자격 증명이 조직 전반에 걸쳐 무분별하게 퍼져 있습니다.
비밀번호, API 키, 자격 증명 등이 일반 텍스트로 앱 소스 코드, 설정 파일, 기타 여러 위치에 저장되어 있습니다. 자격 증명이 이처럼 여기저기 흩어져 있으면 누가 무엇에 접근하고 권한이 있는지를 명확히 파악하기 어렵고, 그로 인해 큰 부담이 따릅니다. 일반 텍스트로 자격 증명을 저장하면 내부 공격자든 외부 공격자든 악의적인 공격 가능성이 크게 증가합니다.
Vault는 이러한 문제를 해결하기 위해 설계되었습니다.
Vault는 이러한 모든 자격 증명을 한 곳에 중앙 집중화하여 정의함으로써, 자격 증명의 불필요한 노출을 줄입니다. 하지만 Vault는 여기서 멈추지 않고, 사용자, 애플리케이션, 시스템이 인증 및 명시적으로 인가된 후에만 리소스에 접근할 수 있도록 보장하며, 클라이언트의 모든 작업 기록을 추적하고 저장하는 감사 로그 기능도 제공합니다.
Vault의 주요 기능은 다음과 같습니다:
1. 안전한 비밀 저장 (Secure Secret Storage): → Static 시크릿 : Vault는 임의의 key/value 형식의 시크릿을 저장할 수 있으며, 이 시크릿은 영구 저장소에 기록되기 전에 암호화됩니다. 따라서 저장소에 직접 접근하더라도 비밀을 열람할 수 없습니다.
Vault는 Disk, Consul 등 다양한 저장소를 지원합니다.
2. 동적 비밀 (Dynamic Secrets): Vault는 AWS나 SQL 데이터베이스와 같은 일부 시스템에 대해 요청 시 비밀을 동적으로 생성할 수 있습니다. 예를 들어, 애플리케이션이 S3 버킷에 접근해야 할 때 Vault에 자격 증명을 요청하면, Vault는 해당 권한을 가진 AWS 키쌍을 생성해줍니다. 이 동적 시크릿은 일정 시간이 지나면 자동으로 폐기됩니다.
3. 데이터 암호화 (Data Encryption): Vault는 데이터를 저장하지 않고 암호화 및 복호화를 수행할 수 있습니다.
이를 통해 보안 팀은 암호화 매개변수를 정의하고, 개발자는 암호화된 데이터를 SQL 데이터베이스 등 외부 저장소에 안전하게 저장할 수 있습니다.
4. 임대 및 갱신 (Leasing and Renewal): Vault에 저장된 모든 시크릿은 임대 기간(lease)이 설정되어 있으며, 이 기간이 끝나면 해당 비밀은 자동으로 폐기됩니다. 클라이언트는 내장된 갱신 API를 통해 임대를 연장할 수 있습니다.
5. 폐기 (Revocation): Vault는 비밀 폐기를 기본적으로 지원합니다. 단일 비밀뿐만 아니라 특정 사용자에 의해 읽힌 모든 비밀, 또는 특정 유형의 모든 비밀 등 비밀의 계층 구조 전체를 폐기할 수 있습니다. 이 기능은 키 롤링이나 침입 발생 시 시스템을 신속하게 차단하는 데 유용합니다.


출처: https://wlsdn3004.tistory.com/11 [IT DevOps 기록:티스토리]

# 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
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
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_disable = 1
}
storage "file" {
path = "/vault/data"
}
service:
enabled: true
type: NodePort
port: 8200
targetPort: 8200
nodePort: 30000 # 🔥 Kind에서 열어둔 포트 중 하나 사용
injector:
enabled: true
EOF
# Helm Install 실행
helm upgrade vault hashicorp/vault -n vault -f override-values.yaml --install
Release "vault" does not exist. Installing it now.
NAME: vault
LAST DEPLOYED: Fri Apr 11 09:34:52 2025
NAMESPACE: vault
STATUS: deployed
REVISION: 1
NOTES:
Thank you for installing HashiCorp Vault!
Now that you have deployed Vault, you should look over the docs on using
Vault with Kubernetes available here:
https://developer.hashicorp.com/vault/docs
Your release is named vault. To learn more about the release, try:
$ helm status vault
$ helm get manifest vault
# 네임스페이스 변경 : 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 Running 0 56s
pod/vault-agent-injector-56459c7545-zslsg 1/1 Running 0 56s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/vault NodePort 10.96.3.62 <none> 8200:30000/TCP,8201:32187/TCP 56s
service/vault-agent-injector-svc ClusterIP 10.96.250.85 <none> 443/TCP 56s
service/vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 56s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/data-vault-0 Bound pvc-20fbe519-1548-4f18-a239-aeb310c67155 10Gi RWO standard <unset> 56s



# Vault Status 명령으로 Sealed 상태확인
kubectl exec -ti vault-0 -- vault status
Key Value
--- -----
Seal Type shamir
Initialized false
Sealed true
Total Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version 1.19.0
Build Date 2025-03-04T12:36:40Z
Storage Type file
HA Enabled false
command terminated with exit code 2
cat <<EOF > init-unseal.sh
#!/bin/bash
# Vault Pod 이름
VAULT_POD="vault-0"
# Vault 명령 실행
VAULT_CMD="kubectl exec -ti \$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}' > "\$UNSEAL_KEY_FILE"
grep 'Initial Root Token:' "\$VAULT_KEYS_FILE" | awk -F': ' '{print \$2}' > "\$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)"
EOF
# 실행 권한 부여
chmod +x init-unseal.sh
# 실행
./init-unseal.sh
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.19.0
Build Date 2025-03-04T12:36:40Z
Storage Type file
Cluster Name vault-cluster-8b16c381
Cluster ID b35528c9-4160-9f5d-2739-e0b9ceb88088
HA Enabled false
[🔓] Vault Unsealed!
[🔐] Root Token: hvs.lVDAL27sdG1y3c6VTCxYL8pT
kubectl exec -ti vault-0 -- vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false <-- 상태 변경 됨
Total Shares 1
Threshold 1
Version 1.19.0
Build Date 2025-03-04T12:36:40Z
Storage Type file
Cluster Name vault-cluster-8b16c381
Cluster ID b35528c9-4160-9f5d-2739-e0b9ceb88088
HA Enabled false
kubectl get all --namespace vault
NAME READY STATUS RESTARTS AGE
pod/vault-0 1/1 Running 0 16m
pod/vault-agent-injector-56459c7545-zslsg 1/1 Running 0 16m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/vault NodePort 10.96.3.62 <none> 8200:30000/TCP,8201:32187/TCP 16m
service/vault-agent-injector-svc ClusterIP 10.96.250.85 <none> 443/TCP 16m
service/vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 16m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/vault-agent-injector 1/1 1 1 16m
NAME DESIRED CURRENT READY AGE
replicaset.apps/vault-agent-injector-56459c7545 1 1 1 16m
NAME READY AGE
statefulset.apps/vault 1/1 16m
(참고) UI에 접속해서 Unseal Key 입력도 가능

이제 Unseal이 마무리 되었으므로 Root Token 값을 사용하여 UI에 접속할 수 있습니다.


brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault --version # 설치 확인
# NodePort로 공개한 30000 Port로 설정
export VAULT_ADDR='http://192.168.0.254:30000'
# vault 상태확인
vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.19.0
Build Date 2025-03-04T12:36:40Z
Storage Type file
Cluster Name vault-cluster-8b16c381
Cluster ID b35528c9-4160-9f5d-2739-e0b9ceb88088
HA Enabled false
# 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.lVDAL27sdG1y3c6VTCxYL8pT
token_accessor D8wqAd0JtzGLjzX2SLRwbtvE
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
→ Vault KV version 2 엔진을 활성화하고 샘플 데이터를 저장합니다.
→ Version1 : KV 버전관리 불가 / Version2 : KV 버전관리 가능
Step 1. KV 엔진 활성화 및 샘플 데이터 추가
# KV v2 형태로 엔진 활성화
vault secrets enable -path=secret kv-v2
Success! Enabled the kv-v2 secrets engine at: secret/
# 샘플 시크릿 저장
vault kv put secret/sampleapp/config \
username="demo" \
password="p@ssw0rd"
======== Secret Path ========
secret/data/sampleapp/config
======= Metadata =======
Key Value
--- -----
created_time 2025-04-11T01:07:35.898436677Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
# 입력된 데이터 확인
vault kv get **secret/sampleapp/config**
======== Secret Path ========
secret/data/sampleapp/config
======= Metadata =======
Key Value
--- -----
created_time 2025-04-11T01:07:35.898436677Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
**password p@ssw0rd
username demo**
Step2. Vault UI : [Secrets Engine] 탭에 접속 후 [sampleapp - config] 접속하여 실제 저장된 Key / Value 확인
- username : demo
- password : p@ssw0rd

Step3. (참고) 경로 확인하는 명령 가이드

Vault Agent Injector는 Kubernetes Pod 내부에 Vault Agent를 자동으로 주입해주는 기능입니다. 이를 통해 어플리케이션이 Vault로부터 자동으로 비밀 정보를 받아올 수 있게 됩니다. 하지만 이를 사용하기 전에 몇 가지 사전 준비가 필요합니다.
1. Vault가 설치되어 있고, Kubernetes와 통합되어 있어야 합니다
2. Vault Agent Injector가 클러스터에 배포되어 있어야 합니다
3. Kubernetes 인증 방식이 활성화되어야 합니다
4. 정책과 역할이 정의되어 있어야 합니다
5. 애플리케이션 Pod에 주입할 주석(annotation)을 추가해야 합니다
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "example-role"



# 1. AppRole 인증 방식 활성화
vault auth enable approle || echo "AppRole already enabled"
Success! Enabled approle auth method at: approle/
vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
approle/ approle auth_approle_5e875a9e n/a n/a
token/ token auth_token_ce15d494 token based credentials n/a
# 2. 정책 생성
vault policy write sampleapp-policy - <<EOF
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
EOF
Success! Uploaded policy: sampleapp-policy
# 3. AppRole Role 생성
vault write auth/approle/role/sampleapp-role \
token_policies="sampleapp-policy" \
secret_id_ttl="1h" \
token_ttl="1h" \
token_max_ttl="4h"
Success! Data written to: auth/approle/role/sampleapp-role
# 4. Role ID 및 Secret ID 추출 및 저장
ROLE_ID=$(vault read -field=role_id auth/approle/role/sampleapp-role/role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/sampleapp-role/secret-id)
echo "ROLE_ID: $ROLE_ID"
ROLE_ID: 6b26b5f7-9fd6-9fcb-cc98-89ff2adf2d20
echo "SECRET_ID: $SECRET_ID"
SECRET_ID: 916f2540-6bb3-020c-2c83-d1c0317f647e
# 5. 파일로 저장
mkdir -p approle-creds
echo "$ROLE_ID" > approle-creds/role_id.txt
echo "$SECRET_ID" > approle-creds/secret_id.txt
# 6. (옵션) Kubernetes Secret으로 저장
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
Vault Agent는 vault-agent-config.hcl 설정을 통해 연결할 Vault의 정보와, Template 구성, 렌더링 주기, 참조할 Vault KV 위치정보 등을 정의한다.
vault-agent-config.hcl) - HCLcat <<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
kubectl apply -n vault -f - <<EOF
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: {}
EOF
deployment.apps/nginx-vault-demo created
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 # Kind에서 설정한 Port
EOF
service/nginx-service created
# 파드 내에 사이드카 컨테이너 추가되어 2/2 확인
NAME READY STATUS RESTARTS AGE
nginx-vault-demo-7776649597-sff46 2/2 Running 0 57s
kubectl describe pod -l app=nginx-vault-demo
...
Containers:
nginx:
Container ID: containerd://067f02c254d53c94de7568437fe873aec498c157830d49447060658e9771ff1c
Image: nginx:latest
Image ID: docker.io/library/nginx@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 11 Apr 2025 12:55:24 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/usr/share/nginx/html from html-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2m6sr (ro)
vault-agent-sidecar:
Container ID: containerd://29a2fa378f2ec52b228264a8035c717dba1c6ba046305995f5ab95f8ac9cce6c
Image: hashicorp/vault:latest
Image ID: docker.io/hashicorp/vault@sha256:ee674e47dcf85849aadf255b5341f76c0e1a474bc5fa9be9cdfff2a2edf9a628
Port: <none>
Host Port: <none>
Args:
agent
-config=/etc/vault/agent-config.hcl
State: Running
Started: Fri, 11 Apr 2025 12:55:46 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/etc/secrets from html-volume (rw)
/etc/vault from vault-agent-config (rw)
/etc/vault-agent-token from vault-token (rw)
/etc/vault/approle from vault-approle (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2m6sr (ro)
...
# 볼륨 마운트 확인
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- ls -l /etc/vault-agent-token
total 4
-rw-r----- 1 vault vault 95 Apr 11 03:55 token
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault-agent-token/token ; echo
hvs.CAESIME1SLIjY5eIuIv85VlGOGwoa4osSaS3_wAr9f1TwON0Gh4KHGh2cy5BeGpGYmQ1Y3ppcHJKNlBtVUJLd2dKV1U
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- ls -al /etc/vault
...
lrwxrwxrwx 1 root root 23 Apr 11 03:55 agent-config.hcl -> ..data/agent-config.hcl
drwxrwxrwt 3 root root 120 Apr 11 03:55 approle
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/agent-config.hcl
...
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- ls -al /etc/vault/approle
...
lrwxrwxrwx 1 root root 14 Apr 11 03:55 role_id -> ..data/role_id
lrwxrwxrwx 1 root root 16 Apr 11 03:55 secret_id -> ..data/secret_id
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/approle/role_id ; echo
6b26b5f7-9fd6-9fcb-cc98-89ff2adf2d20
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/vault/approle/secret_id ; echo
916f2540-6bb3-020c-2c83-d1c0317f647e
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- ls -l /etc/secrets
total 4
-rw-r--r-- 1 vault vault 94 Apr 11 03:55 index.html
kubectl exec -it deploy/nginx-vault-demo -c vault-agent-sidecar -- cat /etc/secrets/index.html
<html>
<body>
<p>username: demo</p>
<p>password: p@ssw0rd</p>
</body>
</html>
kubectl exec -it 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>
# 로그 확인
kubectl stern -l app=nginx-vault-demo -c vault-agent-sidecar
+ nginx-vault-demo-7776649597-sff46 › vault-agent-sidecar
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Couldn't start vault with IPC_LOCK. Disabling IPC_LOCK, please use --cap-add IPC_LOCK
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar ==> Note: Vault Agent version does not match Vault server version. Vault Agent version: 1.19.1, Vault server version: 1.19.0
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar ==> Vault Agent started! Log data will stream in below:
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar ==> Vault Agent configuration:
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.sink.file: creating file sink
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.sink.file: file sink configured: path=/etc/vault-agent-token/token mode=-rw-r----- owner=100 group=1000
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Api Address 1: http://bufconn
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Cgo: disabled
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Log Level:
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Version: Vault v1.19.1, built 2025-04-02T15:43:01Z
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar Version Sha: aa75903ec499b2236da9e7bbbfeb7fd16fa4fd9d
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.exec.server: starting exec server
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.exec.server: no env templates or exec config, exiting
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.auth.handler: starting auth handler
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.auth.handler: authenticating
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.sink.server: starting sink server
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent.template.server: starting template server
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.056Z [INFO] agent: (runner) creating new runner (dry: false, once: false)
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.057Z [INFO] agent: (runner) creating watcher
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.066Z [INFO] agent.auth.handler: authentication successful, sending token to sinks
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.066Z [INFO] agent.auth.handler: starting renewal process
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent.template.server: template server received new token
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent.sink.file: token written: path=/etc/vault-agent-token/token
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent: (runner) stopping
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent: (runner) creating new runner (dry: false, once: false)
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent: (runner) creating watcher
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.067Z [INFO] agent: (runner) starting
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.070Z [INFO] agent.auth.handler: renewed auth token
nginx-vault-demo-7776649597-sff46 vault-agent-sidecar 2025-04-11T03:55:47.075Z [INFO] agent: (runner) rendered "(dynamic)" => "/etc/secrets/index.html"
# mutating admission
kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io
NAME WEBHOOKS AGE
vault-agent-injector-cfg 1 3h27m




# Kubernetes Auth Method 활성화
vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/
# Kubernetes Auth Config 설정
vault write auth/kubernetes/config \
token_reviewer_jwt="$(kubectl get secret $(kubectl get serviceaccount vault -n vault -o jsonpath='{.secrets[0].name}') -n vault -o jsonpath="{.data.token}" | base64 --decode)" \
kubernetes_host="$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[0].cluster.server}')" \
kubernetes_ca_cert="$(kubectl get secret $(kubectl get serviceaccount vault -n vault -o jsonpath='{.secrets[0].name}') -n vault -o jsonpath='{.data.ca\.crt}' | base64 --decode)"
Success! Data written to: auth/kubernetes/config
# 필요한 Policy 작성 (앞선 과정에서 만들었으므로 생략가능)
vault policy write sampleapp-policy - <<EOF
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
EOF
Success! Uploaded policy: sampleapp-policy
# Role 생성 (Injector가 로그인할 수 있도록)
vault write auth/kubernetes/role/sampleapp-role \
bound_service_account_names="vault-ui-sa" \
bound_service_account_namespaces="vault" \
policies="sampleapp-policy" \
ttl="24h"
Success! Data written to: auth/kubernetes/role/sampleapp-role





# Role ID 확인 및 Secret ID 신규 발급
ROLE_ID=$(vault read -field=role_id auth/approle/role/sampleapp-role/role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/sampleapp-role/secret-id)
echo "ROLE_ID: $ROLE_ID"
ROLE_ID: 6b26b5f7-9fd6-9fcb-cc98-89ff2adf2d20
echo "SECRET_ID: $SECRET_ID"
SECRET_ID: f60e75ff-9e2b-2af3-05d2-355f5a2573a0
# Role ID
vault read auth/approle/role/<role-name>/role-id
# Secret ID
vault write -f auth/approle/role/<role-name>/secret-id
# 예시
vault read auth/approle/role/sampleapp-role/role-id
Key Value
--- -----
role_id 678c0c6e-57df-bb23-1427-f6318843a514


jenkins-vault-kv 입력 후 생성pipeline {
agent any
environment {
VAULT_ADDR = 'http://192.168.0.2:30000' // 실제 Vault 주소로 변경!!!
}
stages {
stage('Read Vault Secret') {
steps {
withVault([
vaultSecrets: [
[
path: 'secret/sampleapp/config',
engineVersion: 2,
secretValues: [
[envVar: 'USERNAME', vaultKey: 'username'],
[envVar: 'PASSWORD', vaultKey: 'password']
]
]
],
configuration: [
vaultUrl: "${VAULT_ADDR}",
vaultCredentialId: 'vault-approle-creds'
]
]) {
sh '''
echo "Username from Vault: $USERNAME"
echo "Password from Vault: $PASSWORD"
'''
script {
echo "Username (env): ${env.USERNAME}"
echo "Password (env): ${env.PASSWORD}"
}
}
}
}
}
}

실행결과


유의사항
secret/data/sampleapp/configsecret/sampleapp/config
참조 : ArgoCD Vault Plugin,Secret Management with GitOps and Argo CD Vault Plugin
ArgoCD Vault Plugin 소개
설치/구성관련 내용 요약(ChatGPT) - Installing in Argo CD
Argo CD Vault Plugin의 공식 문서에서는 Argo CD에 플러그인을 설치하는 방법으로 네 가지를 제시하고 있습니다:
이 중 사이드카 컨테이너를 활용한 방법은 Argo CD v2.4.0부터 도입된 최신 방식으로, 보안성과 유지보수 측면에서 권장됩니다.
kubectl apply -f - <<EOF
kind: Secret
apiVersion: v1
metadata:
name: argocd-vault-plugin-credentials
namespace: argocd
type: Opaque
stringData:
VAULT_ADDR: "http://vault.vault:8200"
AVP_TYPE: "vault"
AVP_AUTH_TYPE: "approle"
AVP_ROLE_ID: 6b26b5f7-9fd6-9fcb-cc98-89ff2adf2d20 #Role_ID
AVP_SECRET_ID: f60e75ff-9e2b-2af3-05d2-355f5a2573a0
#Secret_ID
EOF
secret/argocd-vault-plugin-credentials created
git clone https://github.com/hyungwook0221/argocd-vault-plugin.git
cd argocd-vault-plugin/manifests/cmp-sidecar
# argocd 네임스페이스 설정
kubens argocd
# 생성될 메니페스트 파일에 대한 확인
kubectl kustomize .
apiVersion: v1
data:
avp-helm.yaml: "---\napiVersion: argoproj.io/v1alpha1\nkind: ConfigManagementPlugin\nmetadata:\n
\ name: argocd-vault-plugin-helm\nspec:\n allowConcurrency: true\n\n # Note:
this command is run _before_ any Helm templating is done, therefore the logic
is to check\n # if this looks like a Helm chart\n discover:\n find:\n command:\n
\ - sh\n - \"-c\"\n - \"find . -name 'Chart.yaml' && find
. -name 'values.yaml'\"\n generate:\n # **IMPORTANT**: passing `${ARGOCD_ENV_HELM_ARGS}`
effectively allows users to run arbitrary code in the Argo CD \n # repo-server
(or, if using a sidecar, in the plugin sidecar). Only use this when the users
are completely trusted. If\n # possible, determine which Helm arguments are
needed by your users and explicitly pass only those arguments.\n command:\n
\ - sh\n - \"-c\"\n - |\n helm template $ARGOCD_APP_NAME
-n $ARGOCD_APP_NAMESPACE ${ARGOCD_ENV_HELM_ARGS} . |\n argocd-vault-plugin
generate -\n lockRepo: false\n"
avp-kustomize.yaml: |
---
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: argocd-vault-plugin-kustomize
spec:
allowConcurrency: true
# Note: this command is run _before_ anything is done, therefore the logic is to check
# if this looks like a Kustomize bundle
discover:
find:
command:
- find
- "."
- -name
- kustomization.yaml
generate:
command:
- sh
- "-c"
- "kustomize build . | argocd-vault-plugin generate -"
lockRepo: false
avp.yaml: |
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: argocd-vault-plugin
spec:
allowConcurrency: true
discover:
find:
command:
- sh
- "-c"
- "find . -name '*.yaml' | xargs -I {} grep \"<path\\|avp\\.kubernetes\\.io\" {} | grep ."
generate:
command:
- argocd-vault-plugin
- generate
- "."
lockRepo: false
kind: ConfigMap
metadata:
name: cmp-plugin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-repo-server
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-repo-server
template:
metadata:
labels:
app.kubernetes.io/name: argocd-repo-server
spec:
automountServiceAccountToken: true
containers:
- command:
- /var/run/argocd/argocd-cmp-server
envFrom:
- secretRef:
name: argocd-vault-plugin-credentials
image: quay.io/argoproj/argocd:v2.7.9
name: avp-helm
securityContext:
runAsNonRoot: true
runAsUser: 999
volumeMounts:
- mountPath: /var/run/argocd
name: var-files
- mountPath: /home/argocd/cmp-server/plugins
name: plugins
- mountPath: /tmp
name: tmp
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
name: cmp-plugin
subPath: avp-helm.yaml
- mountPath: /usr/local/bin/argocd-vault-plugin
name: custom-tools
subPath: argocd-vault-plugin
- command:
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.7.9
name: avp-kustomize
securityContext:
runAsNonRoot: true
runAsUser: 999
volumeMounts:
- mountPath: /var/run/argocd
name: var-files
- mountPath: /home/argocd/cmp-server/plugins
name: plugins
- mountPath: /tmp
name: tmp
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
name: cmp-plugin
subPath: avp-kustomize.yaml
- mountPath: /usr/local/bin/argocd-vault-plugin
name: custom-tools
subPath: argocd-vault-plugin
- command:
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.7.9
name: avp
securityContext:
runAsNonRoot: true
runAsUser: 999
volumeMounts:
- mountPath: /var/run/argocd
name: var-files
- mountPath: /home/argocd/cmp-server/plugins
name: plugins
- mountPath: /tmp
name: tmp
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
name: cmp-plugin
subPath: avp.yaml
- mountPath: /usr/local/bin/argocd-vault-plugin
name: custom-tools
subPath: argocd-vault-plugin
- image: quay.io/argoproj/argocd:v2.8.13
name: repo-server
initContainers:
- args:
- curl -L https://github.com/argoproj-labs/argocd-vault-plugin/releases/download/v$(AVP_VERSION)/argocd-vault-plugin_$(AVP_VERSION)_linux_amd64
-o argocd-vault-plugin && chmod +x argocd-vault-plugin && mv argocd-vault-plugin
/custom-tools/
command:
- sh
- -c
env:
- name: AVP_VERSION
value: 1.18.0
image: registry.access.redhat.com/ubi8
name: download-tools
volumeMounts:
- mountPath: /custom-tools
name: custom-tools
volumes:
- configMap:
name: cmp-plugin
name: cmp-plugin
- emptyDir: {}
name: custom-tools
# -k 옵션으로 kusomize 실행
kubectl apply -n argocd -k .
configmap/cmp-plugin created
Warning: resource deployments/argocd-repo-server is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
deployment.apps/argocd-repo-server configured
k exec -it -n vault vault-0 -- sh
# vault pod shell에 접속 후 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.lVDAL27sdG1y3c6VTCxYL8pT
token_accessor D8wqAd0JtzGLjzX2SLRwbtvE
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
# 확인명령
/ $ vault read auth/kubernetes/role/argocd
No value found at auth/kubernetes/role/argocd
secret
deployment
argocd-repo-server
Step 3. 샘플 Application 배포하여 Vault와 동기화
Step 3-1) Application.yaml 작성
kubectl apply -n argocd -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: default
source:
path: infra/helm
repoURL: https://github.com/hyungwook0221/spring-boot-debug-app
targetRevision: main
plugin:
name: argocd-vault-plugin-helm
env:
- name: HELM_ARGS
value: -f new-values.yaml
syncPolicy:
automated:
prune: true
selfHeal: true
EOF

serviceAccount:
create: true
image:
repository: luafanti/spring-boot-debug-app
tag: main
pullPolicy: IfNotPresent
replicaCount: 1
resources:
memoryRequest: 256Mi
memoryLimit: 512Mi
cpuRequest: 500m
cpuLimit: 1
probes:
liveness:
initialDelaySeconds: 15
path: /actuator/health/liveness
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 3
periodSeconds: 5
readiness:
initialDelaySeconds: 15
path: /actuator/health/readiness
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 3
periodSeconds: 5
ports:
http:
name: http
value: 8080
management:
name: management
value: 8081
envs:
- name: VAULT_SECRET_USER
value: <path:secret/data/sampleapp/config#username>
- name: VAULT_SECRET_PASSWORD
value: <path:secret/data/sampleapp/config#password>
log:
level:
spring: "info"
service: "info"
Step 3-3) 실제 배포시 적용된 화면
ArgoCD Vault Plugin 적용된 화면 : [DETAILS] - [PARAMETERS]

Application 배포화면
Deployment에 적용된 env 값 확인 :
envs:
- name: VAULT_SECRET_USER
value: <path:secret/data/sampleapp/config#username>
- name: VAULT_SECRET_PASSWORD
value: <path:secret/data/sampleapp/config#password>

ArgoCD App 삭제 kubectl delete applications demo
(참고) Unknown 에러 발생시 redis 파드 재배포 후 필요




# vault-operator-values.yaml
defaultVaultConnection:
enabled: true
address: "http://vault.vault.svc.cluster.local:8200"
skipTLSVerify: false
controller:
manager:
clientCache:
persistenceModel: direct-encrypted
storageEncryption:
enabled: true
mount: k8s-auth-mount
keyName: vso-client-cache
transitMount: demo-transit
kubernetes:
role: auth-role-operator
serviceAccount: vault-secrets-operator-controller-manager
tokenAudiences: ["vault"]
- Values 구성요소 분석
- `defaultVaultConnection`: 기본 Vault 연결 설정을 구성
- `address`: vault.vault.svc.cluster.local:8200 (Helm으로 설치된 Vault의 ClusterIP)
- `skipTLSVerify: false`: TLS 검증 비활성화 안 함 (Vault에 TLS 적용된 경우 주의 필요)
- **clientCache 설정**
- `persistenceModel`: direct-encrypted: 암호화된 데이터를 직접 저장
- `storageEncryption.enabled`: true: 암호화 기능 활성화
- `transitMount: demo-transit`: 앞에서 Vault에 만든 Transit 엔진 mount path
- `keyName: vso-client-cache`: Transit에서 사용하는 암호화 키
- `mount: k8s-auth-mount`: Kubernetes 인증 방식에서 사용할 auth path
- `kubernetes.role`: auth-role-operator 라는 Role에 지정된 정책으로 암복호화 가능
- `serviceAccount`: VSO가 사용하는 ServiceAccount 이름
- `tokenAudiences`: Vault 서버에서 사용하는 audience 설정
- 위와 같은 설정으로 VSO는 Vault에 인증된 후, 동적/정적 시크릿을 Kubernetes 리소스로 가져오고, 가져온 시크릿 데이터를 자체적으로 **암호화해 캐시** 가능
helm install vault-secrets-operator hashicorp/vault-secrets-operator \
-n vault-secrets-operator-system \
--create-namespace \
--values vault-operator-values.yaml
NAME: vault-secrets-operator
LAST DEPLOYED: Fri Apr 11 16:17:38 2025
NAMESPACE: vault-secrets-operator-system
STATUS: deployed
REVISION: 1
#
kubectl get-all -n vault-secrets-operator-system
NAME NAMESPACE AGE
configmap/kube-root-ca.crt vault-secrets-operator-system 23s
configmap/vault-secrets-operator-manager-config vault-secrets-operator-system 23s
endpoints/vault-secrets-operator-metrics-service vault-secrets-operator-system 23s
pod/vault-secrets-operator-controller-manager-7f67cd89fd-htprm vault-secrets-operator-system 23s
secret/sh.helm.release.v1.vault-secrets-operator.v1 vault-secrets-operator-system 23s
secret/vso-cc-storage-hmac-key vault-secrets-operator-system 5s
serviceaccount/default vault-secrets-operator-system 23s
serviceaccount/vault-secrets-operator-controller-manager vault-secrets-operator-system 23s
service/vault-secrets-operator-metrics-service vault-secrets-operator-system 23s
deployment.apps/vault-secrets-operator-controller-manager vault-secrets-operator-system 23s
replicaset.apps/vault-secrets-operator-controller-manager-7f67cd89fd vault-secrets-operator-system 23s
lease.coordination.k8s.io/b0d477c0.hashicorp.com vault-secrets-operator-system 5s
endpointslice.discovery.k8s.io/vault-secrets-operator-metrics-service-gbw8m vault-secrets-operator-system 23s
rolebinding.rbac.authorization.k8s.io/vault-secrets-operator-leader-election-rolebinding vault-secrets-operator-system 23s
role.rbac.authorization.k8s.io/vault-secrets-operator-leader-election-role vault-secrets-operator-system 23s
vaultauth.secrets.hashicorp.com/vault-secrets-operator-default-transit-auth vault-secrets-operator-system 21s
vaultconnection.secrets.hashicorp.com/default vault-secrets-operator-system 21s
#
kubectl get pod -n vault-secrets-operator-system
NAME READY STATUS RESTARTS AGE
vault-secrets-operator-controller-manager-7f67cd89fd-htprm 2/2 Running 0 42s
kubectl describe pod -n vault-secrets-operator-system
...
Service Account: vault-secrets-operator-controller-manager
...
Containers:
kube-rbac-proxy:
Container ID: containerd://db3eae7b836fb4f1b4236c494c8fa96ada94769a6c602e1a150c75293a6a4162
Image: quay.io/brancz/kube-rbac-proxy:v0.18.1
...
manager:
Container ID: containerd://1ab1545fb4bd86ac52d6c7609a3e962cd2d1a81daa9bbd9c82f79d9a0d8b6466
Image: hashicorp/vault-secrets-operator:0.10.0
...
#
kubectl rbac-tool lookup vault-secrets-operator-controller-manager
SUBJECT | SUBJECT TYPE | SCOPE | NAMESPACE | ROLE | BINDING
--------------------------------------------+----------------+-------------+-------------------------------+---------------------------------------------+-----------------------------------------------------
vault-secrets-operator-controller-manager | ServiceAccount | ClusterRole | | vault-secrets-operator-proxy-role | vault-secrets-operator-proxy-rolebinding
vault-secrets-operator-controller-manager | ServiceAccount | ClusterRole | | vault-secrets-operator-manager-role | vault-secrets-operator-manager-rolebinding
vault-secrets-operator-controller-manager | ServiceAccount | Role | vault-secrets-operator-system | vault-secrets-operator-leader-election-role | vault-secrets-operator-leader-election-rolebinding
#
kubectl rolesum vault-secrets-operator-controller-manager -n vault-secrets-operator-system
ServiceAccount: vault-secrets-operator-system/vault-secrets-operator-controller-manager
Secrets:
Policies:
• [RB] vault-secrets-operator-system/vault-secrets-operator-leader-election-rolebinding ⟶ [R] vault-secrets-operator-system/vault-secrets-operator-leader-election-role
Resource Name Exclude Verbs G L W C U P D DC
configmaps [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
events [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✔ ✖ ✖
leases.coordination.k8s.io [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
• [CRB] */vault-secrets-operator-manager-rolebinding ⟶ [CR] */vault-secrets-operator-manager-role
Resource Name Exclude Verbs G L W C U P D DC
configmaps [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖
daemonsets.apps [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✔ ✖ ✖
deployments.apps [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✔ ✖ ✖
events [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✔ ✖ ✖
hcpauths.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
hcpauths.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
hcpauths.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
hcpvaultsecretsapps.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
hcpvaultsecretsapps.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
hcpvaultsecretsapps.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
rollouts.argoproj.io [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✔ ✖ ✖
secrets [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔
secrettransformations.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
secrettransformations.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
secrettransformations.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
serviceaccounts [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖
serviceaccounts/token [*] [-] [-] ✔ ✔ ✔ ✔ ✖ ✖ ✖ ✖
statefulsets.apps [*] [-] [-] ✔ ✔ ✔ ✖ ✖ ✔ ✖ ✖
vaultauthglobals.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultauthglobals.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultauthglobals.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
vaultauths.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultauths.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultauths.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
vaultconnections.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultconnections.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultconnections.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
vaultdynamicsecrets.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultdynamicsecrets.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultdynamicsecrets.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
vaultpkisecrets.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultpkisecrets.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultpkisecrets.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
vaultstaticsecrets.secrets.hashicorp.com [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖
vaultstaticsecrets.secrets.hashicorp.com/finalizers [*] [-] [-] ✖ ✖ ✖ ✖ ✔ ✖ ✖ ✖
vaultstaticsecrets.secrets.hashicorp.com/status [*] [-] [-] ✔ ✖ ✖ ✖ ✔ ✔ ✖ ✖
• [CRB] */vault-secrets-operator-proxy-rolebinding ⟶ [CR] */vault-secrets-operator-proxy-role
Resource Name Exclude Verbs G L W C U P D DC
subjectaccessreviews.authorization.k8s.io [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖
tokenreviews.authentication.k8s.io [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖
#
kubectl get vaultauth -n vault-secrets-operator-system vault-secrets-operator-default-transit-auth -o jsonpath='{.spec}' | jq
{
"kubernetes": {
"audiences": [
"vault"
],
"role": "auth-role-operator",
"serviceAccount": "vault-secrets-operator-controller-manager",
"tokenExpirationSeconds": 600
},
"method": "kubernetes",
"mount": "k8s-auth-mount",
"storageEncryption": {
"keyName": "vso-client-cache",
"mount": "demo-transit"
},
"vaultConnectionRef": "default"
}
kubectl get vaultconnection -n vault-secrets-operator-system default -o jsonpath='{.spec}' | jq
{
"address": "http://vault.vault.svc.cluster.local:8200",
"skipTLSVerify": false
}
kubectl create ns postgres
helm repo add bitnami https://charts.bitnami.com/bitnami
helm upgrade --install postgres bitnami/postgresql \
--namespace postgres \
--set auth.audit.logConnections=true \
--set auth.postgresPassword=secret-pass
Release "postgres" does not exist. Installing it now.
NAME: postgres
LAST DEPLOYED: Fri Apr 11 16:21:54 2025
NAMESPACE: postgres
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: postgresql
CHART VERSION: 16.6.3
APP VERSION: 17.4.0
Did you know there are enterprise versions of the Bitnami catalog? For enhanced secure software supply chain features, unlimited pulls from Docker, LTS support, or application customization, see Bitnami Premium or Tanzu Application Catalog. See https://www.arrow.com/globalecs/na/vendors/bitnami for more information.
** Please be patient while the chart is being deployed **
PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster:
postgres-postgresql.postgres.svc.cluster.local - Read/Write connection
To get the password for "postgres" run:
export POSTGRES_PASSWORD=$(kubectl get secret --namespace postgres postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)
To connect to your database run the following command:
kubectl run postgres-postgresql-client --rm --tty -i --restart='Never' --namespace postgres --image docker.io/bitnami/postgresql:17.4.0-debian-12-r15 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
--command -- psql --host postgres-postgresql -U postgres -d postgres -p 5432
> NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID 1001} does not exist"
To connect to your database from outside the cluster execute the following commands:
kubectl port-forward --namespace postgres svc/postgres-postgresql 5432:5432 &
PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432
WARNING: The configured password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue.
WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
- primary.resources
- readReplicas.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
# psql 로그인 확인
kubectl exec -it -n postgres postgres-postgresql-0 -- sh -c 'PGPASSWORD=secret-pass psql -U postgres -h localhost'
psql (17.4)
Type "help" for help.
postgres=#
kubectl exec -it -n postgres postgres-postgresql-0 -- sh -c "PGPASSWORD=secret-pass psql -U postgres -h localhost -c '\l'"
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges
-----------+----------+----------+-----------------+-------------+-------------+--------+-----------+-----------------------
postgres | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
template0 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
(3 rows)
#
kubectl exec -it vault-0 -n vault -- cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIIYJPloAf87sswDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNTA0MTAyMjE2MzlaFw0zNTA0MDgyMjIxMzlaMBUx
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC2LRnWiqx+Wq2BTu8WFO/gNFMvffRRW/TSMSAflUY64w0acXR+NM2XoeUW
j8tiz1LwGEGf7iSvmzN2t35x9TObLGU6NY6zEnO33ZOaqfhm1ZihHv5rle3+WiEl
6TFJIaWFmxb1MjPnCEqkMzaMQ70Nxuv5O6PbE6N7AKJ5+RWlJK/FQbyXLOVTg9qV
omCYSEDEC/+X8HSM/vEzTRunBcE7MLN7JSjF8PWy4GnPEzbG7cIhJ4xwHOMXm9/L
nMqq0+MdNuaR2W2xfDcRYUjZf7qZ7Q17spdbtTzMgX0fnKJTwLWjykch6JgK9zxf
8txrW5C276StC8WAB4GrzfskA0wVAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQk9qVRSGdZRO/jEOZGp+eOqHLymDAV
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQAIkiGxISGX
ELIj52ZMWNlj4+bT/MqqUoG2NXMIVSDW/rjS6RwjLhm5ubeltfESSx8cQcvh2IfL
sVSXZGVQk9Cn4Ki7/AHRSGkA2yQ9VNy937/7IfcRfwUyBHUR6yC0B+0URs7kmvim
eNvEWv+ySxdpeEJX2na/lzhXurV6ftnXtGa/6YGaWqsrNG5/4v8KDLM1vbH8hwGT
JDKZQpl+U6q2fyXkei/txap4XhGc43mNCO/eFQWfhmCBuiL9xXJVjqhMb5T5CNiR
XIHqlzbAvHR4v+z8VgMOC5XrN7hlfcpNrfaV7p+jhdr2CIGRrRRUegWILF9rt0mD
YOBZ+7E4fpnu
-----END CERTIFICATE-----
# 해당 ca.crt 는 k8s 의 루트인증서 정보
kubectl exec -it vault-0 -n vault -- cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt > vso-ca.crt
openssl x509 -in vso-ca.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 6959158324709093067 (0x6093e5a007fceecb)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
...
# vault 서비스 어카운트의 token 확인
kubectl exec -it vault-0 -n vault -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6IkMzZ1NValRPLWJJbDdWRU15ekk2bWdJMHhKT1RrR2M0Wk1nelR0blRWajAifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzc1ODkwMjkyLCJpYXQiOjE3NDQzNTQyOTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNDE4NTY5YWYtNDIzYi00ZThhLTg5ZjctNzM3YjhmYzc5MjRmIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJ2YXVsdCIsIm5vZGUiOnsibmFtZSI6Im15azhzLXdvcmtlcjIiLCJ1aWQiOiJjZjkzZDFiNi00YzkxLTRjMzgtYjM1My04MjU2ODQ4NjZiZmYifSwicG9kIjp7Im5hbWUiOiJ2YXVsdC0wIiwidWlkIjoiOTVjY2NmMDUtZGYxMi00NTM1LTk4NWQtNzU5NmNiZjYyOTFkIn0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJ2YXVsdCIsInVpZCI6IjMyNjRmNDhlLWJmYTItNDZlZC1hMGE4LTg1MmY1M2E4ZWNkZSJ9LCJ3YXJuYWZ0ZXIiOjE3NDQzNTc4OTl9LCJuYmYiOjE3NDQzNTQyOTIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp2YXVsdDp2YXVsdCJ9.oPrk91-lvWHAGlIv75D9ONAag9i0Ptu7bxfKnblHCehm5tXHzuuycK78g9PJyOkD5nVjfH79izW4LIX_rS7kxrGYUpy21cD15PoEtSYK6R-xGx-XdS_O8_ChUtiniZSA9BKxbQbOj2N-rq6PnOa-LBllXYUcicZgf0-hvJD3OTEE7CaKrqxCIOaGZfnyXTU1ByrPgvGXsY-ZSGq8y7xB1v2jmOJ3wG3aGC-y2jcTPao9GOtvrmxT2CmvdgAz2HCqZeQXu5r-r0tcjuc1FflR0tTf8upjDR7DVjiA8J7sI0_NOhI7Lz1iNNnqHSj8Co92g1kJcOFzuVy44kKHEG8S2g
# https://jwt.io/ 에서 token 디코드 확인 시 PAYLOAD 부분
"https://kubernetes.default.svc.cluster.local"
],
"exp": 1775890292,
"iat": 1744354292,
"iss": "https://kubernetes.default.svc.cluster.local",
"jti": "418569af-423b-4e8a-89f7-737b8fc7924f",
"kubernetes.io": {
"namespace": "vault",
"node": {
"name": "myk8s-worker2",
"uid": "cf93d1b6-4c91-4c38-b353-825684866bff"
},
"pod": {
"name": "vault-0",
"uid": "95cccf05-df12-4535-985d-7596cbf6291d"
},
"serviceaccount": {
"name": "vault",
"uid": "3264f48e-bfa2-46ed-a0a8-852f53a8ecde"
},
"warnafter": 1744357899
},
"nbf": 1744354292,
"sub": "system:serviceaccount:vault:vault"
}
# vault SA 토큰 만료 기간 : 대략 1시간(3600초)+7초
k get pod -n vault vault-0 -o yaml
...
- name: kube-api-access-vqkvw
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
kubectl exec --stdin=true --tty=true vault-0 -n vault -- /bin/sh
----------------------------------------------------------------
# 최초 설치시 획득한 vault root token 사용.
# 예시) hvs.lVDAL27sdG1y3c6VTCxYL8pT
vault login
# Kubernetes 인증 메서드 활성화
vault auth enable -path k8s-auth-mount kubernetes
#
vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
approle/ approle auth_approle_5e875a9e n/a n/a
k8s-auth-mount/ kubernetes auth_kubernetes_ef3a1d99 n/a n/a
kubernetes/ kubernetes auth_kubernetes_65a23464 n/a n/a
token/ token auth_token_ce15d494 token based credentials n/a
# Kubernetes 클러스터 정보 구성
vault write auth/k8s-auth-mount/config \
kubernetes_host="https://kubernetes.default.svc:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
Success! Data written to: auth/k8s-auth-mount/config
# 설정 확인
vault read auth/k8s-auth-mount/config
Key Value
--- -----
disable_iss_validation true
disable_local_ca_jwt false
issuer n/a
kubernetes_ca_cert -----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIIYJPloAf87sswDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNTA0MTAyMjE2MzlaFw0zNTA0MDgyMjIxMzlaMBUx
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC2LRnWiqx+Wq2BTu8WFO/gNFMvffRRW/TSMSAflUY64w0acXR+NM2XoeUW
j8tiz1LwGEGf7iSvmzN2t35x9TObLGU6NY6zEnO33ZOaqfhm1ZihHv5rle3+WiEl
6TFJIaWFmxb1MjPnCEqkMzaMQ70Nxuv5O6PbE6N7AKJ5+RWlJK/FQbyXLOVTg9qV
omCYSEDEC/+X8HSM/vEzTRunBcE7MLN7JSjF8PWy4GnPEzbG7cIhJ4xwHOMXm9/L
nMqq0+MdNuaR2W2xfDcRYUjZf7qZ7Q17spdbtTzMgX0fnKJTwLWjykch6JgK9zxf
8txrW5C276StC8WAB4GrzfskA0wVAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQk9qVRSGdZRO/jEOZGp+eOqHLymDAV
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQAIkiGxISGX
ELIj52ZMWNlj4+bT/MqqUoG2NXMIVSDW/rjS6RwjLhm5ubeltfESSx8cQcvh2IfL
sVSXZGVQk9Cn4Ki7/AHRSGkA2yQ9VNy937/7IfcRfwUyBHUR6yC0B+0URs7kmvim
eNvEWv+ySxdpeEJX2na/lzhXurV6ftnXtGa/6YGaWqsrNG5/4v8KDLM1vbH8hwGT
JDKZQpl+U6q2fyXkei/txap4XhGc43mNCO/eFQWfhmCBuiL9xXJVjqhMb5T5CNiR
XIHqlzbAvHR4v+z8VgMOC5XrN7hlfcpNrfaV7p+jhdr2CIGRrRRUegWILF9rt0mD
YOBZ+7E4fpnu
-----END CERTIFICATE-----
kubernetes_host https://kubernetes.default.svc:443
pem_keys []
token_reviewer_jwt_set true
use_annotations_as_alias_metadata false
----------------------------------------------------------------
kubernetes_host: API 서버 주소kubernetes_ca_cert: API 서버의 CA 인증서 (Pod 내 ServiceAccount에서 자동 주입됨)token_reviewer_jwt: TokenReviewer 권한이 있는 토큰으로 Vault가 요청자의 토큰을 검증할 수 있도록 설정vault write auth/k8s-auth-mount/role/auth-role \
bound_service_account_names=demo-dynamic-app \
bound_service_account_namespaces=demo-ns \
token_ttl=0 \
token_period=120 \
token_policies=demo-auth-policy-db \
audience=vault
Success! Data written to: auth/k8s-auth-mount/role/auth-role
# auth-role 생성
vault write auth/k8s-auth-mount/role/auth-role \
bound_service_account_names=demo-dynamic-app \ # demo-dynamic-app 서비스 어카운트를 사용하는 Pod에서만 인증 허용, Pod 내부에서 Vault에 로그인하려면 이 서비스 어카운트를 써야 함
bound_service_account_namespaces=demo-ns \ # 이 Role은 오직 demo-ns 네임스페이스에서 오는 요청만 허용
token_ttl=0 \ # 발급되는 Vault 토큰의 기본 TTL 없음(0). 일반적으로 token_ttl=0이면 token_period가 사용됨
token_period=120 \ # Lease 기간이 120초인 Renewable Token 발급. TTL이 없는 대신, 2분마다 갱신 가능한 토큰을 생성. 보통 이 설정은 "periodic token"이라 불리며, long-lived session에 적합.
token_policies=demo-auth-policy-db \ # 인증에 성공하면 발급되는 토큰에 demo-auth-policy-db 정책이 적용
audience=vault # JWT 토큰의 aud (Audience) claim 검증에 사용.


# demo-db라는 경로로 Database Secret Engine을 활성화
vault secrets enable -path=demo-db database
Success! Enabled the database secrets engine at: demo-db/
# PostgreSQL 연결 정보 등록
# 해당 과정은 postgres가 정상적으로 동작 시 적용 가능
# allowed_roles: 이후 설정할 Role 이름 지정
vault write demo-db/config/demo-db \
plugin_name=postgresql-database-plugin \
allowed_roles="dev-postgres" \
connection_url="postgresql://{{username}}:{{password}}@postgres-postgresql.postgres.svc.cluster.local:5432/postgres?sslmode=disable" \
username="postgres" \
password="secret-pass"
Success! Data written to: demo-db/config/demo-db
# DB 사용자 동적 생성 Role 등록
# 해당 Role 사용 시 Vault가 동적으로 사용자 계정과 비밀번호를 생성 가능
# TTL은 생성된 자격증명의 유효 시간 (30초~10분)
## creation_statements=... : Vault가 계정을 자동 생성할 때 실행할 SQL 문. {{name}}, {{password}}, {{expiration}}은 Vault가 자동으로 채워줌.
## revocation_statements=... : Vault가 동적 사용자 계정을 폐기(revoke)할 때 실행할 SQL 문. 권한을 모두 회수.
## default_ttl="1m" / max_ttl="1m" : 기본 1분만 유효합니다. 갱신을 안 하면 1분 후 자동 만료 (계정도 자동 삭제). 최대 TTL도 1분이므로 연장도 최대 1분까지만.
vault write demo-db/roles/dev-postgres \
db_name=demo-db \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT ALL PRIVILEGES ON DATABASE postgres TO \"{{name}}\";" \
revocation_statements="REVOKE ALL ON DATABASE postgres FROM \"{{name}}\";" \
backend=demo-db \
name=dev-postgres \
default_ttl="1m" \
max_ttl="1m"
Success! Data written to: demo-db/roles/dev-postgres
# 정책 설정: DB 자격증명 읽기 권한
# demo-db/creds/dev-postgres 경로에 대한 read 권한 부여
# 추후 Kubernetes 서비스 어카운트(demo-dynamic-app)에 이 정책을 연결해서 자격증명 요청 가능
vault policy write demo-auth-policy-db - <<EOF
path "demo-db/creds/dev-postgres" {
capabilities = ["read"]
}
EOF
Success! Uploaded policy: demo-auth-policy-db
kubectl exec --stdin=true --tty=true vault-0 -n vault -- /bin/sh
----------------------------------------------------------------
# Transit Secret Engine 활성화
# transit 엔진을 demo-transit 경로로 활성화.
# 데이터를 저장하지 않고 암복호화 기능만 제공하는 Vault의 기능
# 클라이언트 캐시는 리더십 변경 시에도 Vault 토큰 및 동적 비밀 임대를 계속 추적하고 갱신할 수 있으므로 원활한 업그레이드를 지원합니다
## Vault 서버에 클라이언트 캐시를 저장하고 암호화할 수 있습니다.
## Vault 동적 비밀을 사용하는 경우 클라이언트 캐시를 영구적으로 저장하고 암호화하는 것이 좋습니다.
## 이렇게 하면 재시작 및 업그레이드를 통해 동적 비밀 임대가 유지됩니다.
vault secrets enable -path=demo-transit transit
Success! Enabled the transit secrets engine at: demo-transit/
vault secrets list -detailed
Path Plugin Accessor Default TTL Max TTL Force No Cache Replication Seal Wrap External Entropy Access Options Description UUID Version Running Version Running SHA256 Deprecation Status
---- ------ -------- ----------- ------- -------------- ----------- --------- ----------------------- ------- ----------- ---- ------- --------------- -------------- ------------------
cubbyhole/ cubbyhole cubbyhole_81343c9d n/a n/a false local false false map[] per-token private secret storage 42c8881e-ddd4-de89-0965-d5d2322252f4 n/a v1.19.0+builtin.vault n/a n/a
demo-db/ database database_22a52598 system system false replicated false false map[] n/a 7cc9dedf-df08-1fd1-6404-ab5f1a4ec34f n/a v1.19.0+builtin.vault n/a n/a
demo-transit/ transit transit_b7eb4f67 system system false replicated false false map[] n/a c14021e1-93b4-cff9-70af-853ffebeb85f n/a v1.19.0+builtin.vault n/a supported
identity/ identity identity_ff863c9a system system false replicated false false map[] identity store 48893d8e-2a03-dd93-550d-ad95a4258806 n/a v1.19.0+builtin.vault n/a n/a
secret/ kv kv_899fcc51 system system false replicated false false map[version:2] n/a 432bfbdd-040a-e190-00e1-1d17e5ee6b61 n/a v0.21.0+builtin n/a supported
sys/ system system_6c9bd623 n/a n/a false replicated true false map[] system endpoints used for control, policy and debugging b168292f-4ff2-32c1-a1dc-8a328fa5becb n/a v1.19.0+builtin.vault n/a n/a
# vso-client-cache라는 키를 생성
# 이 키는 VSO가 암복호화 시 사용할 암호화 키 역할
vault write -force demo-transit/keys/vso-client-cache
Key Value
--- -----
allow_plaintext_backup false
auto_rotate_period 0s
deletion_allowed false
derived false
exportable false
imported_key false
keys map[1:1744357522]
latest_version 1
min_available_version 0
min_decryption_version 1
min_encryption_version 0
name vso-client-cache
supports_decryption true
supports_derivation true
supports_encryption true
supports_signing false
type aes256-gcm96
# vso-client-cache 키에 대해 암호화(encrypt), 복호화(decrypt)를 허용하는 정책 생성
vault policy write demo-auth-policy-operator - <<EOF
path "demo-transit/encrypt/vso-client-cache" {
capabilities = ["create", "update"]
}
path "demo-transit/decrypt/vso-client-cache" {
capabilities = ["create", "update"]
}
EOF
Success! Uploaded policy: demo-auth-policy-operator
# Vault Secrets Operator가 사용하는 ServiceAccount에 위 정책을 바인딩
# vso가 Vault에 로그인할 때 사용할 수 있는 JWT 기반 Role 설정
# 해당 Role을 통해 Operator는 Transit 엔진을 이용한 암복호화 API 호출 가능
vault write auth/k8s-auth-mount/role/auth-role-operator \
bound_service_account_names=vault-secrets-operator-controller-manager \
bound_service_account_namespaces=vault-secrets-operator-system \
token_ttl=0 \
token_period=120 \
token_policies=demo-auth-policy-operator \
audience=vault
Success! Data written to: auth/k8s-auth-mount/role/auth-role-operator
vault read auth/k8s-auth-mount/role/auth-role-operator
Key Value
--- -----
alias_name_source serviceaccount_uid
audience vault
bound_service_account_names [vault-secrets-operator-controller-manager]
bound_service_account_namespace_selector n/a
bound_service_account_namespaces [vault-secrets-operator-system]
token_bound_cidrs []
token_explicit_max_ttl 0s
token_max_ttl 0s
token_no_default_policy false
token_num_uses 0
token_period 2m
token_policies [demo-auth-policy-operator]
token_ttl 0s
token_type default
kubectl create ns demo-ns
mkdir vso-dynamic
cd vso-dynamic
---
# vault-auth-dynamic.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: demo-ns
name: demo-dynamic-app
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: dynamic-auth
namespace: demo-ns
spec:
method: kubernetes
mount: k8s-auth-mount
kubernetes:
role: auth-role
serviceAccount: demo-dynamic-app
audiences:
- vault
---
# app-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: vso-db-demo
namespace: demo-ns
rolloutRestartTargets 을 사용하여 애플리케이션을 재배포하여 새로 업데이트된 시크릿을 사용하도록 할 수 있음refreshAfter 설정을 통해 VSO가 소스 시크릿 데이터를 동기화 하는 주기 설정가능 - Docs---
# vault-dynamic-secret.yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: vso-db-demo
namespace: demo-ns
spec:
refreshAfter: 25s
mount: demo-db
path: creds/dev-postgres
destination:
name: vso-db-demo
create: true
overwrite: true
vaultAuthRef: dynamic-auth
rolloutRestartTargets:
- kind: Deployment
name: vaultdemo
---
# app-spring-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vaultdemo
namespace: demo-ns
labels:
app: vaultdemo
spec:
replicas: 1
selector:
matchLabels:
app: vaultdemo
template:
metadata:
labels:
app: vaultdemo
spec:
volumes:
- name: secrets
secret:
secretName: "vso-db-demo"
containers:
- name: vaultdemo
image: hyungwookhub/vso-spring-demo:v5
imagePullPolicy: IfNotPresent
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: "vso-db-demo"
key: password
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: "vso-db-demo"
key: username
- name: DB_HOST
value: "postgres-postgresql.postgres.svc.cluster.local"
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: "postgres"
ports:
- containerPort: 8088
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
---
apiVersion: v1
kind: Service
metadata:
name: vaultdemo
namespace: demo-ns
spec:
ports:
- name: vaultdemo
port: 8088
targetPort: 8088
nodePort: 30003
selector:
app: vaultdemo
type: NodePort
kubectl apply -f .`
secret/vso-db-demo created
deployment.apps/vaultdemo created
service/vaultdemo created
serviceaccount/demo-dynamic-app created
vaultauth.secrets.hashicorp.com/dynamic-auth created
vaultdynamicsecret.secrets.hashicorp.com/vso-db-demo created
postgres-postgresql.postgres.svc , db는 postgres
# 스크릿이 변경되고, 적용을 위해서 파드가 42~45초 사이로 재생성됨
while true; do kubectl get pod -n demo-ns ; echo; kubectl view-secret -n demo-ns vso-db-demo --all; date; sleep 30 ; echo ; done
NAME READY STATUS RESTARTS AGE
vaultdemo-54466b5f8b-8gglh 1/1 Running 0 34s
_raw='{"password":"XkQ-J9PWOUxdaJqr8Ga0","username":"v-k8s-auth-dev-post-gJlLw0hjQSZNtI3vsPB0-1744358614"}'
password='XkQ-J9PWOUxdaJqr8Ga0'
username='v-k8s-auth-dev-post-gJlLw0hjQSZNtI3vsPB0-1744358614'
Fri Apr 11 17:04:09 KST 2025
NAME READY STATUS RESTARTS AGE
vaultdemo-7d8dc56b8c-f5s4k 1/1 Running 0 21s
_raw='{"password":"dBZuGove-sLQcPvwwR3q","username":"v-k8s-auth-dev-post-vXvDAaDe9XqLvP9K04vH-1744358658"}'
password='dBZuGove-sLQcPvwwR3q'
username='v-k8s-auth-dev-post-vXvDAaDe9XqLvP9K04vH-1744358658'
Fri Apr 11 17:04:39 KST 2025
# 실제 postgresql 에 사용자 정보 확인 : 계속 추가되고 있음..
kubectl exec -it -n postgres postgres-postgresql-0 -- sh -c "PGPASSWORD=secret-pass psql -U postgres -h localhost -c '\du'"
List of roles
Role name | Attributes
-----------------------------------------------------+------------------------------------------------------------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
v-k8s-auth-dev-post-073kCwgaqwPD9yB4REPF-1744358701 | Password valid until 2025-04-11 08:06:06+00
v-k8s-auth-dev-post-5YI48vzkiQo3iAAbEtfH-1744358568 | Password valid until 2025-04-11 08:03:53+00
v-k8s-auth-dev-post-9p9X4qcFjqYS0Z1CgENM-1744358438 | Password valid until 2025-04-11 08:01:43+00
v-k8s-auth-dev-post-CeLjNhO2M4jX9JI8C2II-1744358743 | Password valid until 2025-04-11 08:06:48+00
v-k8s-auth-dev-post-LNgZaqarkrYdeDZRE5yA-1744358307 | Password valid until 2025-04-11 07:59:32+00
v-k8s-auth-dev-post-T82jXw4tz8VlMNeSsAGL-1744358351 | Password valid until 2025-04-11 08:00:16+00
v-k8s-auth-dev-post-U163tgCi4KTeh5ALoixi-1744358264 | Password valid until 2025-04-11 07:58:49+00
v-k8s-auth-dev-post-ZKZp9hwhkpMKtMJQSITC-1744358525 | Password valid until 2025-04-11 08:03:10+00
v-k8s-auth-dev-post-aQzuu4etveKItQQ4nU9c-1744358484 | Password valid until 2025-04-11 08:02:29+00
v-k8s-auth-dev-post-chObYVU1zv3AbLRxu7kG-1744358183 | Password valid until 2025-04-11 07:57:28+00
v-k8s-auth-dev-post-gJlLw0hjQSZNtI3vsPB0-1744358614 | Password valid until 2025-04-11 08:04:39+00
v-k8s-auth-dev-post-mw3XklNZ5fDfTYpBRev1-1744358183 | Password valid until 2025-04-11 07:57:28+00
v-k8s-auth-dev-post-nCEAnQZV5SgV0K0wzcp6-1744358395 | Password valid until 2025-04-11 08:01:00+00
v-k8s-auth-dev-post-utfzStl1Tl2yPgpHv7ZA-1744358224 | Password valid until 2025-04-11 07:58:09+00
v-k8s-auth-dev-post-vXvDAaDe9XqLvP9K04vH-1744358658 | Password valid until 2025-04-11 08:05:23+00
...
# 로그 확인
kubectl stern -n demo-ns -l app=vaultdemo
+ vaultdemo-5d77487ccd-62kbw › vaultdemo
vaultdemo-5d77487ccd-62kbw vaultdemo
vaultdemo-5d77487ccd-62kbw vaultdemo . ____ _ __ _ _
vaultdemo-5d77487ccd-62kbw vaultdemo /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
vaultdemo-5d77487ccd-62kbw vaultdemo ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
vaultdemo-5d77487ccd-62kbw vaultdemo \\/ ___)| |_)| | | | | || (_| | ) ) ) )
vaultdemo-5d77487ccd-62kbw vaultdemo ' |____| .__|_| |_|_| |_\__, | / / / /
vaultdemo-5d77487ccd-62kbw vaultdemo =========|_|==============|___/=/_/_/_/
vaultdemo-5d77487ccd-62kbw vaultdemo
vaultdemo-5d77487ccd-62kbw vaultdemo :: Spring Boot :: (v3.4.4)
vaultdemo-5d77487ccd-62kbw vaultdemo
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:44.475Z INFO 1 --- [ main] c.e.vaultdemo.VaultdemoApplicationKt : Starting VaultdemoApplicationKt v0.0.1-SNAPSHOT using Java 17.0.14 with PID 1 (/app/app.jar started by root in /app)
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:44.477Z INFO 1 --- [ main] c.e.vaultdemo.VaultdemoApplicationKt : No active profile set, falling back to 1 default profile: "default"
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.269Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8088 (http)
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.277Z INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.277Z INFO 1 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.39]
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.296Z INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.296Z INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 793 ms
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.512Z INFO 1 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.810Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8088 (http) with context path '/'
vaultdemo-5d77487ccd-62kbw vaultdemo 2025-04-11T08:05:45.824Z INFO 1 --- [ main] c.e.vaultdemo.VaultdemoApplicationKt : Started VaultdemoApplicationKt in 1.631 seconds (process running for 1.922)
...
kubectl stern -n vault vault-0
+ vault-0 › vault
vault-0 vault ==> Vault server configuration:
vault-0 vault
vault-0 vault Administrative Namespace:
vault-0 vault Api Address: http://10.244.2.9:8200
vault-0 vault Cgo: disabled
vault-0 vault Cluster Address: https://vault-0.vault-internal:8201
vault-0 vault Environment Variables: HOME, HOSTNAME, HOST_IP, KUBERNETES_PORT, KUBERNETES_PORT_443_TCP, KUBERNETES_PORT_443_TCP_ADDR, KUBERNETES_PORT_443_TCP_PORT, KUBERNETES_PORT_443_TCP_PROTO, KUBERNETES_SERVICE_HOST, KUBERNETES_SERVICE_PORT, KUBERNETES_SERVICE_PORT_HTTPS, NAME, NGINX_SERVICE_PORT, NGINX_SERVICE_PORT_80_TCP, NGINX_SERVICE_PORT_80_TCP_ADDR, NGINX_SERVICE_PORT_80_TCP_PORT, NGINX_SERVICE_PORT_80_TCP_PROTO, NGINX_SERVICE_SERVICE_HOST, NGINX_SERVICE_SERVICE_PORT, PATH, POD_IP, PWD, SHLVL, SKIP_CHOWN, SKIP_SETCAP, VAULT_ADDR, VAULT_AGENT_INJECTOR_SVC_PORT, VAULT_AGENT_INJECTOR_SVC_PORT_443_TCP, VAULT_AGENT_INJECTOR_SVC_PORT_443_TCP_ADDR, VAULT_AGENT_INJECTOR_SVC_PORT_443_TCP_PORT, VAULT_AGENT_INJECTOR_SVC_PORT_443_TCP_PROTO, VAULT_AGENT_INJECTOR_SVC_SERVICE_HOST, VAULT_AGENT_INJECTOR_SVC_SERVICE_PORT, VAULT_AGENT_INJECTOR_SVC_SERVICE_PORT_HTTPS, VAULT_API_ADDR, VAULT_CLUSTER_ADDR, VAULT_K8S_NAMESPACE, VAULT_K8S_POD_NAME, VAULT_PORT, VAULT_PORT_8200_TCP, VAULT_PORT_8200_TCP_ADDR, VAULT_PORT_8200_TCP_PORT, VAULT_PORT_8200_TCP_PROTO, VAULT_PORT_8201_TCP, VAULT_PORT_8201_TCP_ADDR, VAULT_PORT_8201_TCP_PORT, VAULT_PORT_8201_TCP_PROTO, VAULT_SERVICE_HOST, VAULT_SERVICE_PORT, VAULT_SERVICE_PORT_HTTP, VAULT_SERVICE_PORT_HTTPS_INTERNAL, VERSION
vault-0 vault Go Version: go1.23.6
vault-0 vault Listener 1: tcp (addr: "[::]:8200", cluster address: "[::]:8201", disable_request_limiter: "false", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
vault-0 vault Log Level:
vault-0 vault Mlock: supported: true, enabled: false
vault-0 vault Recovery Mode: false
vault-0 vault Storage: file
vault-0 vault Version: Vault v1.19.0, built 2025-03-04T12:36:40Z
vault-0 vault Version Sha: 7eeafb6160d60ede73c1d95566b0c8ea54f3cb5a
vault-0 vault
vault-0 vault ==> Vault server started! Log data will stream in below:
vault-0 vault
vault-0 vault 2025-04-11T06:51:33.007Z [INFO] proxy environment: http_proxy="" https_proxy="" no_proxy=""
vault-0 vault 2025-04-11T06:51:33.008Z [INFO] incrementing seal generation: generation=1
vault-0 vault 2025-04-11T06:51:33.009Z [INFO] core: Initializing version history cache for core
vault-0 vault 2025-04-11T06:51:33.009Z [INFO] events: Starting event system
vault-0 vault 2025-04-11T06:52:03.036Z [INFO] core.cluster-listener.tcp: starting listener: listener_address=[::]:8201
vault-0 vault 2025-04-11T06:52:03.036Z [INFO] core.cluster-listener: serving cluster requests: cluster_listen_address=[::]:8201
vault-0 vault 2025-04-11T06:52:03.037Z [INFO] core: post-unseal setup starting
vault-0 vault 2025-04-11T06:52:03.038Z [INFO] core: loaded wrapping token key
vault-0 vault 2025-04-11T06:52:03.038Z [INFO] core: successfully setup plugin runtime catalog
vault-0 vault 2025-04-11T06:52:03.038Z [INFO] core: successfully setup plugin catalog: plugin-directory=""
vault-0 vault 2025-04-11T06:52:03.043Z [INFO] core: successfully mounted: type=system version="v1.19.0+builtin.vault" path=sys/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.043Z [INFO] core: successfully mounted: type=identity version="v1.19.0+builtin.vault" path=identity/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.045Z [INFO] core: successfully mounted: type=kv version="v0.21.0+builtin" path=secret/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.045Z [INFO] core: successfully mounted: type=cubbyhole version="v1.19.0+builtin.vault" path=cubbyhole/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.047Z [INFO] core: successfully mounted: type=token version="v1.19.0+builtin.vault" path=token/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.047Z [INFO] core: successfully mounted: type=approle version="v1.19.0+builtin.vault" path=approle/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.047Z [INFO] core: successfully mounted: type=kubernetes version="v0.21.0+builtin" path=kubernetes/ namespace="ID: root. Path: "
vault-0 vault 2025-04-11T06:52:03.048Z [INFO] rollback: Starting the rollback manager with 256 workers
vault-0 vault 2025-04-11T06:52:03.048Z [INFO] rollback: starting rollback manager
vault-0 vault 2025-04-11T06:52:03.048Z [INFO] core: restoring leases
vault-0 vault 2025-04-11T06:52:03.050Z [INFO] expiration: lease restore complete
vault-0 vault 2025-04-11T06:52:03.051Z [INFO] identity: entities restored
vault-0 vault 2025-04-11T06:52:03.051Z [INFO] identity: groups restored
vault-0 vault 2025-04-11T06:52:03.051Z [INFO] core: usage gauge collection is disabled
vault-0 vault 2025-04-11T06:52:03.052Z [INFO] core: post-unseal setup complete
vault-0 vault 2025-04-11T06:52:03.052Z [INFO] core: vault is unsealed
vault-0 vault 2025-04-11T07:33:25.271Z [INFO] core: enabled credential backend: path=k8s-auth-mount/ type=kubernetes version="v0.21.0+builtin"
vault-0 vault 2025-04-11T07:33:36.419Z [ERROR] secrets.system.system_6c9bd623: error occurred during enable credential: path=k8s-auth-mount/ error="path is already in use at k8s-auth-mount/"
vault-0 vault 2025-04-11T07:33:47.599Z [ERROR] secrets.system.system_6c9bd623: error occurred during enable credential: path=k8s-auth-mount/ error="path is already in use at k8s-auth-mount/"
vault-0 vault 2025-04-11T07:34:17.460Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:34:33.433Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:35:03.000Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:36:01.455Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:37:39.773Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:40:18.149Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:41:51.553Z [INFO] secrets.database.database_22a52598: initializing database rotation queue
vault-0 vault 2025-04-11T07:41:51.554Z [INFO] core: successful mount: namespace="" path=demo-db/ type=database version="v1.19.0+builtin.vault"
vault-0 vault 2025-04-11T07:41:51.565Z [INFO] secrets.database.database_22a52598: populating role rotation queue
vault-0 vault 2025-04-11T07:41:51.566Z [INFO] secrets.database.database_22a52598: starting periodic ticker
vault-0 vault 2025-04-11T07:44:26.602Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:44:46.490Z [INFO] core: successful mount: namespace="" path=demo-transit/ type=transit version="v1.19.0+builtin.vault"
vault-0 vault 2025-04-11T07:48:26.729Z [ERROR] core: login attempts exceeded, user is locked out: request_path=auth/approle/login
vault-0 vault 2025-04-11T07:55:47.253Z [INFO] expiration: revoked lease: lease_id=auth/approle/login/h5389c0ab267a3887a96d9a199dc2c4c9c616cd2746a61627e316e51bce498333
vault-0 vault 2025-04-11T07:57:23.210Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/8ozUkFrQ10RJ0zmzIvXuVRwh
vault-0 vault 2025-04-11T07:57:23.471Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/0HFcmVcXxtDkaOJ2fRuqFOkB
vault-0 vault 2025-04-11T07:58:04.905Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/gPlKN05NCn6TqG7ALPbspmVk
vault-0 vault 2025-04-11T07:58:44.664Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/mAOO2TTlZdTLI1mWvslCdak4
vault-0 vault 2025-04-11T07:59:27.999Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/3FsgMe9msEHmC60j3JPe8kwA
vault-0 vault 2025-04-11T08:00:11.563Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/LGyhgqPakIcMJyGkbUgzOosv
vault-0 vault 2025-04-11T08:00:55.151Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/LPilSJxrbB3qjcqdFK784rc9
vault-0 vault 2025-04-11T08:01:38.338Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/PBzFA36MGRHdl9tLcLAfE2q3
vault-0 vault 2025-04-11T08:02:24.100Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/AMnQDWq8bVPKDPSYTKXPG9oQ
vault-0 vault 2025-04-11T08:03:05.878Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/QKtzcoOh78fKpWqI1fvR1Kdk
vault-0 vault 2025-04-11T08:03:48.409Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/ClVArkbXTd4cEusGbbyY1tnC
vault-0 vault 2025-04-11T08:04:34.717Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/QW89tAm8B3zBGsfkYtUO9jaQ
vault-0 vault 2025-04-11T08:05:18.441Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/2sxDNw5q1oRg8xRNiXnU34fp
vault-0 vault 2025-04-11T08:06:01.323Z [INFO] expiration: revoked lease: lease_id=demo-db/creds/dev-postgres/jl13xLjckRBhSktO7IDVyKr8
# vault-secrets-operator 가 clientCachePersistenceModel 설정 적용 정보 확인 : 참고로 해당 파드가 재시작되지는 않음.
kubectl stern -n vault-secrets-operator-system -l app.kubernetes.io/name=vault-secrets-operator
+ vault-secrets-operator-controller-manager-7f67cd89fd-htprm › manager
+ vault-secrets-operator-controller-manager-7f67cd89fd-htprm › kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","logger":"initCachingClientFactory","msg":"Initializing the CachingClientFactory"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","logger":"clientCallbackHandler","msg":"Starting client callback handler"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","logger":"setup","msg":"Starting manager","gitVersion":"0.10.0","gitCommit":"aebf0c1c59485059a9ea6c58340fd406afe4cbef","gitTreeState":"clean","buildDate":"2025-03-04T22:22:24+0000","goVersion":"go1.23.6","platform":"linux/arm64","clientCachePersistenceModel":"direct-encrypted","clientCacheSize":10000,"backoffMultiplier":1.5,"backoffMaxInterval":60,"backoffMaxElapsedTime":0,"backoffInitialInterval":5,"backoffRandomizationFactor":0.5,"globalTransformationOptions":"","globalVaultAuthOptions":"allow-default-globals"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy W0411 07:17:46.984244 1 options.go:150]
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy ==== Deprecation Warning ======================
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy Insecure listen address will be removed.
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy Using --insecure-listen-address won't be possible!
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy The ability to run kube-rbac-proxy without TLS certificates will be removed.
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy Not using --tls-cert-file and --tls-private-key-file won't be possible!
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","logger":"controller-runtime.metrics","msg":"Starting metrics server"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","logger":"controller-runtime.metrics","msg":"Serving metrics server","bindAddress":"127.0.0.1:8080","secure":false}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy For more information, please go to https://github.com/brancz/kube-rbac-proxy/issues/187
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"starting server","name":"health probe","addr":"[::]:8081"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy ===============================================
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy W0411 07:17:46.984393 1 deprecated.go:66]
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager I0411 07:17:56.580456 1 leaderelection.go:257] attempting to acquire leader lease vault-secrets-operator-system/b0d477c0.hashicorp.com...
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager I0411 07:17:56.583737 1 leaderelection.go:271] successfully acquired lease vault-secrets-operator-system/b0d477c0.hashicorp.com
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultpkisecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultPKISecret","source":"kind source: *v1.PartialObjectMetadata"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret","source":"channel source: 0x400024ce70"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultpkisecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultPKISecret","source":"kind source: *v1beta1.VaultPKISecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultconnection","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultConnection","source":"kind source: *v1beta1.VaultConnection"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultpkisecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultPKISecret","source":"kind source: *v1beta1.SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret","source":"kind source: *v1beta1.VaultStaticSecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret","source":"kind source: *v1beta1.SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret","source":"kind source: *v1.PartialObjectMetadata"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuth","source":"kind source: *v1beta1.VaultAuthGlobal"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"hcpauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPAuth","source":"kind source: *v1beta1.HCPAuth"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret","source":"channel source: 0x400024cee0"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuth","source":"kind source: *v1beta1.VaultAuth"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"secrettransformation","controllerGroup":"secrets.hashicorp.com","controllerKind":"SecretTransformation","source":"kind source: *v1beta1.SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"hcpvaultsecretsapp","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPVaultSecretsApp","source":"kind source: *v1.PartialObjectMetadata"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret","source":"kind source: *v1beta1.SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret","source":"kind source: *v1.PartialObjectMetadata"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"hcpvaultsecretsapp","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPVaultSecretsApp","source":"kind source: *v1beta1.HCPVaultSecretsApp"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"hcpvaultsecretsapp","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPVaultSecretsApp","source":"kind source: *v1beta1.SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret","source":"kind source: *v1beta1.VaultDynamicSecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting EventSource","controller":"vaultauthglobal","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuthGlobal","source":"kind source: *v1beta1.VaultAuthGlobal"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"secrettransformation","controllerGroup":"secrets.hashicorp.com","controllerKind":"SecretTransformation"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultconnection","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultConnection"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy ==== Removed Flag Warning ======================
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"secrettransformation","controllerGroup":"secrets.hashicorp.com","controllerKind":"SecretTransformation","worker count":1}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy logtostderr is removed in the k8s upstream and has no effect any more.
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy ===============================================
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy I0411 07:17:46.984604 1 kube-rbac-proxy.go:232] Valid token audiences:
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy I0411 07:17:46.985315 1 kube-rbac-proxy.go:326] Generating self signed cert as no cert is provided
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy I0411 07:17:47.400205 1 kube-rbac-proxy.go:390] Starting TCP socket on 0.0.0.0:8443
vault-secrets-operator-controller-manager-7f67cd89fd-htprm kube-rbac-proxy I0411 07:17:47.400487 1 kube-rbac-proxy.go:397] Listening securely on 0.0.0.0:8443
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultconnection","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultConnection","worker count":1}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuth"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuth","worker count":1}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"hcpauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPAuth"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"hcpauth","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPAuth","worker count":1}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultstaticsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultStaticSecret","worker count":100}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultauthglobal","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuthGlobal"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultauthglobal","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultAuthGlobal","worker count":1}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"hcpvaultsecretsapp","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPVaultSecretsApp"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"hcpvaultsecretsapp","controllerGroup":"secrets.hashicorp.com","controllerKind":"HCPVaultSecretsApp","worker count":100}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultdynamicsecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultDynamicSecret","worker count":100}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting Controller","controller":"vaultpkisecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultPKISecret"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:17:56Z","msg":"Starting workers","controller":"vaultpkisecret","controllerGroup":"secrets.hashicorp.com","controllerKind":"VaultPKISecret","worker count":100}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:56:23Z","logger":"lifetimeWatcher","msg":"Starting","id":"98dab696-a202-4f11-a995-8163b389efa6","entityID":"e15ab976-671e-afc8-614d-875fa192ec93","clientID":"36b9ab822375356b25e915d756d8ce6083894e25d0518911c022670f05d2f2d0","cacheKey":"kubernetes-ad55540ae5d3cf51f94232"}
vault-secrets-operator-controller-manager-7f67cd89fd-htprm manager {"level":"info","ts":"2025-04-11T07:56:23Z","logger":"lifetimeWatcher","msg":"Starting","id":"cba45aa7-b6d0-4335-978e-474ead1cb1d5","entityID":"2f5b0f00-d094-754e-1758-e0df06f4e0ee","clientID":"736b9671e3d02cdeb4c5f5ccf3f9b71420d7b537c63e4fa2f724191ae57a06f3","cacheKey":"kubernetes-0fcd6d53bcef79a3934f85"}
# 암호화된 캐시 저장소 확인 : vso-cc-<auth method>
kubectl get secret -n vault-secrets-operator-system -l app.kubernetes.io/component=client-cache-storage
NAME TYPE DATA AGE
vso-cc-kubernetes-0fcd6d53bcef79a3934f85 Opaque 2 11m
kubectl get secret -n vault-secrets-operator-system -l app.kubernetes.io/component=client-cache-storage -o yaml
apiVersion: v1
items:
- apiVersion: v1
data:
messageMAC: BVR67aukUNSLI6GBiYW8LumYHhUCLw2KLpG6vFn5G+0=
secret: eyJjaXBoZXJ0ZXh0IjoidmF1bHQ6djE6eDlYTmRWSkRNSDh4RGpzSng3Sml0UDU2RDBXVUQ1YnhVU1lNK0I3RzBYU2IrMHpmOUdOVzBFU1Z5OFB5N1pQenFwak9qSEVmR2FZRmtCSG5nUkxhSWRNaE9SSVhXRFBSNk5tYWpxS2ZiR3VvdjFYM3cyd2pDVHNaSkltOVFtZnFDaS9BVXJkeTJiTFVCOVdESUJFY09xUmZsaEFla1ZSNG1PckRUeG1qbmUyWFVrT1lmMVhETEhkNC83QW9zNk4yS2xDVHNVMVNmek5zREJvNFNid04vL21zWVU2QW1VSHBzR3ZNRk9IbWFCeFIrYlZ2amROYXVzOGRkMU43TnN3M0Y4RkQ4NS9DcUkvNzZJQ0xzdURVenI4WTY2QTZqYVpUd1Y5ZHVQUG9qQUR4NVBsL2tGdGxaSXVJT2tPYWVnR2VrODZXZkhTTFJRT2w5OGY1ayszdWd2WWpMaXJUZUN3VWRNOFk4WWN0NU5jbHZaVkFzTFNXNlg5c1hMUEt6eFNoS0MxWjZZV0poLzZBd3BVKysxQU5RQ2VtcDR2b29RU0xzR3VWM29acE5PamNKYkJKMjcvc1ZpdFJJL0JuQ1kxZkRGeWdBVDdzUEZCWmVPenUvQ3lTdHJsWGh6S1phdm5KY0ZyYUQ1YjhVZEY0VGxIZ3VSbjJldWc1RjViUmpwVEt2R1krd3p1SFphdU83SVhkem5UUkI1WTJUdFE3c3FaY1pORHhGUVdtMWQ0c3YzMUtYTTlCNmJJNFlEWCtISjFmQndocUp2dUtGNmV5L3N1WU83M3R2UEwwZ2V6OG1vcktpbVBHdEUzQnJiYVJ2VVRQVlVSd1FBaE11cm5PSDB2U0N5U2RmRDFCOWxrekpvWVpKTXlWOCtKdEpXVExrZ1o4b095ejFXZ2VBYmZGRlU2L3l4TTVHc0IvV3FYNW02UFVIeVhIKzJKTEt2MWlZWnRCcHNpd2hzZlhYTlhjNHRVL1JabXNwcXplZlRvQ2pxVUhSbFA2dGlPQ1k0SGV0SjhaWDZOeGFXUVZhQ2RDVUdGcnZPaUVIRUM2VzFqMTBJS08xZmhvT3owNGExNCtDZHlBT2EydVlxelpidUx0VWMzZXc3L0tWWU1aODh4N2wwRnlhVUZnS3BEQkV2b043d1IzSmdZcW41ZExwS1RBeHpSeDMxcDR2MkNXOTY4QWJMcUhoTmI0L21SVG1aMjlzTStWUjBWSlhPTGZBSXQzb1ppdHRrTkZFZ3VhY3AwbHlncHNkRngxY2F5MmhQQmhraHlITjFWS25mRlVZRGxnY2VrOWtrM0w5K2dUV09IeDNRbTlkSHM4Mzh1N3M3QStUbEVwUEthUlVlYWZicC9NMERBWmhPYzVqYnNRNmZKN3NCb1ZrSmthOVM0STFOQUdOTk1aeU8wPSIsImtleV92ZXJzaW9uIjoxfQ==
immutable: true
kind: Secret
metadata:
creationTimestamp: "2025-04-11T07:56:23Z"
labels:
app.kubernetes.io/component: client-cache-storage
app.kubernetes.io/managed-by: vso
app.kubernetes.io/name: vault-secrets-operator
auth/UID: 18d135b3-427e-4035-accd-c69d343faad9
auth/generation: "1"
auth/namespace: demo-ns
cacheKey: kubernetes-0fcd6d53bcef79a3934f85
connection/UID: 618370ab-737c-4b84-8a6d-1dcb551eea8d
connection/generation: "1"
connection/namespace: vault-secrets-operator-system
encrypted: "true"
provider/UID: bd812bed-70a9-489c-87f4-c0c876de3687
provider/namespace: demo-ns
vaultTransitRef: vault-secrets-operator-default-transit-auth
name: vso-cc-kubernetes-0fcd6d53bcef79a3934f85
namespace: vault-secrets-operator-system
resourceVersion: "54126"
uid: eeb8135d-5ee9-49dc-80db-547ea39fc562
type: Opaque
kind: List
metadata:
resourceVersion: ""