[AEWS] #10μ£Όμ°¨ K8s Vault μ€μ΅
25λ λ AWS EKS Hands-on Study μ€ν°λ μ 리 λ΄μ©μ λλ€.
λ³Έ μ€μ΅ μ°Έκ³ νμ΄μ§ : https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/blue-green-upgrade/
μ€μ΅ νκ²½ ꡬμ±
μ ν¨μ€
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
docker compose ps
# Jenkins μ΄κΈ° μνΈ νμΈ
docker compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
09a21116f3ce4f27a0ede79372febfb1
# Jenkins μΉ μ μ
open "http://127.0.0.1:8080"
docker compose logs jenkins -f
μ ν¨μ€μ μ μνμ¬ μ΄κΈ° μΈν μ ν΄μ€ ν μ΄κΈ° νλ¬κ·ΈμΈμ μ€μΉνλ€.
μ΄ν μ μμ μΌλ‘ μλ£λμμΌλ©΄ κ³μ μΈν μ μ§νν΄μ£Όκ³ Jenkins κ΄λ¦¬ > νλ¬κ·ΈμΈ > available pluginsμμ hashicorp vaultλ₯Ό λ€μ΄λ°λλ€.
kind ν΄λ¬μ€ν° ꡬμ±
cat > kind-3node.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "127.0.0.1" # $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
argocd
kubectl create ns argocd
cat <<EOF > argocd-values.yaml
dex:
enabled: false
server:
service:
type: NodePort
nodePortHttps: 30002
extraArgs:
- --insecure
EOF
# μ€μΉ
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 7.8.13 -f argocd-values.yaml --namespace argocd
Vault
μΈμ¦κ³Ό μΈκ°
μΈμ¦ (Authentication) : "μ¬μ©μκ° λꡬμΈμ§ μ¦λͺ νλ μ μ°¨"
- μ¬μ©μκ° μ£Όμ₯νλ μ μμ νμΈνλ κ³Όμ μ΄λ€.
- μΌλ°μ μΌλ‘ IDμ λΉλ°λ²νΈ, μΈμ¦μ, OTP, μ체 μ 보 λ±μ μ¬μ©νλ€.
- μμ
- λ‘κ·ΈμΈν λ ID/PWλ₯Ό μ λ ₯ν΄μ λ΄κ° μ§μ§ νΉμ μ¬λμ΄λΌλ κ±Έ νμΈλ°λ κ²
- OAuthμμ κ΅¬κΈ κ³μ μΌλ‘ λ‘κ·ΈμΈνκΈ°
μΈκ° (Authorization) : "μ¬μ©μκ° λ¬΄μμ ν μ μλμ§ κ²°μ νλ μ μ°¨"
- μΈμ¦μ΄ λλ μ¬μ©μμκ² μ΄λ€ κΆνμ΄ μλμ§ νλ¨νλ κ³Όμ μ΄λ€.
- μ΄λ€ 리μμ€μ μ κ·Ό κ°λ₯νμ§, μ΄λ€ μμ μ μνν μ μλμ§λ₯Ό κ²°μ νλ€.
- μμ
- λ‘κ·ΈμΈν μ¬μ©μκ° κ΄λ¦¬μ νμ΄μ§μ μ κ·Όν μ μλμ§ νμΈ
- νμΌ μμ€ν μμ μ½κΈ°/μ°κΈ° κΆνμ΄ μλμ§ μ²΄ν¬
vault μ€μ΅ νκ²½ ꡬμ±
helmμΌλ‘ ν¨ν€μ§ μ€μΉ
helm repo add hashicorp https://helm.releases.hashicorp.com
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
# 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
disable_mlock = true
cluster_name = "vault-local"
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_disable = 1
}
storage "raft" {
path = "/vault/data"
node_id = "vault-dev-node-1"
}
service:
enabled: true
type: NodePort
port: 8200
targetPort: 8200
nodePort: 30000
injector:
enabled: true
ui:
enabled: true
serviceType: "NodePort"
EOF
μ΄ νκ²½μ μ€μ΅μ© ꡬμ±μ΄λ―λ‘ μ€ν λμΌλ‘ μ λ¨μΌ λ Έλ ννλ‘ κ΅¬μ±μ΄ μ§νλλ€. μ€μ μ΄μ νκ²½μμλ κΆμ₯λμ§ μλ νκ²½ ꡬμ±μΈ μ μ μ£Όμνλ€.
k get pods,svc,pvc
NAME READY STATUS RESTARTS AGE
pod/vault-0 0/1 ContainerCreating 0 14s
pod/vault-agent-injector-56459c7545-bqgk2 0/1 Running 0 14s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/vault NodePort 10.96.228.133 <none> 8200:30000/TCP,8201:32730/TCP 14s
service/vault-agent-injector-svc ClusterIP 10.96.147.40 <none> 443/TCP 14s
service/vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 14s
service/vault-ui NodePort 10.96.51.20 <none> 8200:31005/TCP 14s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/data-vault-0 Bound pvc-6df6d70b-9815-4f4c-b8fc-8c05efe570a5 10Gi RWO standard <unset> 14s
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 raft
Removed From Cluster false
HA Enabled true
command terminated with exit code 2
vault unseal
Vaultλ 'κΈκ³ 'λΌλ λ»μ κ°μ§κ³ μλλ§νΌ κΈ°λ³Έ μνμμλ 'μ κΈ΄ μ±'λ‘ μμνλ€.
- Initialize: Vaultκ° μνλ₯Ό μ μ₯ν backend(μ: Consul, file λ±)μ μ΅μ΄ λ°μ΄ν°λ₯Ό ꡬμ±νκ³ , λ§μ€ν° ν€μ ν€ μμ΄λ₯Ό μμ±νλ€.
- Unseal: Vaultλ μ΄κΈ°ν μ΄νμλ μ€μ λΉλ° μ μ₯μλ₯Ό μ¬μ©ν μ μλλ‘ λ΄μΈ(seal)λμ΄ μλ€. μ΅μ 3κ° μ€ 2κ° μ΄μμ ν€ μμ΄λ₯Ό μ λ ₯ν΄μΌ λ΄μΈμ ν΄μ ν μ μλ€.
μ¦, Vaultλ μ€μΉνλ©΄ μ¦μ μ¬μ© κ°λ₯ μνκ° μλλ€. μλμΌλ‘ μ΄κΈ°ννκ³ λ΄μΈμ ν΄μ ν΄μΌ 본격μ μΈ λμμ μμνλ€.
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
kubectl exec -ti vault-0 -- vault status
Key Value
--- -----
Seal Type shamir
Initialized true
unseal μ΄ν vault-root-token.txtλ₯Ό μ¬μ©νμ¬ μ μν μ μλ€.
vault cli
brew tap hashicorp/tap
brew install hashicorp/tap/vault
export VAULT_ADDR='http://localhost:30000'
vault status
vault login
vault μν¬λ¦Ώμμ§ νμ±ν
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-12T16:10:07.147938837Z
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-12T16:10:07.147938837Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password p@ssw0rd
username demo
vault sidecar μ€μ΅
AppRole λ°©μ μΈμ¦ ꡬμ±
AppRole μΈμ¦ νμ±ν
vault auth enable approle || echo "AppRole already enabled"
vault auth list
Success! Enabled approle auth method at: approle/
Path Type Accessor Description Version
---- ---- -------- ----------- -------
approle/ approle auth_approle_e9721a41 n/a n/a
token/ token auth_token_363206bd token based credentials n/a
μ κ·Ό μ μ± (Policy) μμ±
vault policy write sampleapp-policy - <<EOF
path "secret/data/sampleapp/*" {
capabilities = ["read"]
}
EOF
Success! Uploaded policy: sampleapp-policy
sampleapp-policyλΌλ μ΄λ¦μ μ μ± μ μμ±νλ€.
ν΄λΉ μ μ± μ secret/data/sampleapp/* κ²½λ‘μ KV λ°μ΄ν°λ₯Ό μ½κΈ°(read) ν μ μλ κΆνμ λΆμ¬νλ€.
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
vault policy writeλ μ μ± μ΄λ¦κ³Ό λ΄μ©μ Vaultμ λ±λ‘νλ€.
μ΄ Roleμ μ¬μ©νλ μ ν리μΌμ΄μ μ sampleapp-policyμ μ μλ 리μμ€μ μ κ·Όν μ μλ ν ν°μ μ»μ μ μλ€.
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)
mkdir -p approle-creds
echo "$ROLE_ID" > approle-creds/role_id.txt
echo "$SECRET_ID" > approle-creds/secret_id.txt
ROLE_IDλ AppRole μ체μ μλ³μλ‘ κ³ μ κ°μ΄λ©° 곡κ°μ μΌλ‘ μ λ¬ν΄λ μμ νλ€.
SECRET_IDλ μΌνμ© μν¬λ¦Ώ ν€λ‘, μ€μ μΈμ¦ μ Role IDμ ν¨κ» μ¬μ©λμ΄ Vault μ κ·Όμ νμ©νλ€.
μ΄ λ κ°μ μ‘°ν©ν΄μ AppRole μΈμ¦ ν ν°μ λ°κΈλ°μ μ μλ€.
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μ μ κ·ΌνκΈ° μν μ격μ¦λͺ μΌλ‘ μ¬μ©ν μ μλ€.
vault agent sidecar μ°λ
vault-agent-config.hcl
cat <<EOF | kubectl create configmap vault-agent-config -n vault --from-file=agent-config.hcl=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -
vault {
address = "http://vault.vault.svc:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/etc/vault/approle/role_id"
secret_id_file_path = "/etc/vault/approle/secret_id"
remove_secret_id_file_after_reading = false
}
}
sink "file" {
config = {
path = "/etc/vault-agent-token/token"
}
}
}
template_config {
static_secret_render_interval = "20s"
}
template {
destination = "/etc/secrets/index.html"
contents = <<EOH
<html>
<body>
<p>username: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.username }}{{ end }}</p>
<p>password: {{ with secret "secret/data/sampleapp/config" }}{{ .Data.data.password }}{{ end }}</p>
</body>
</html>
EOH
}
EOF
Vault Agentλ₯Ό Kubernetes νκ²½μμ μ¬μ©νκΈ° μν ConfigMap μμ± κ³Όμ μ λ΄κ³ μμΌλ©°, Vault Agentλ Vaultμμ μΈμ¦, ν ν° κ΄λ¦¬, μν¬λ¦Ώ ν νλ¦Ώ λ λλ§μ μλμΌλ‘ μ²λ¦¬ν΄μ£Όλ λꡬμ΄λ€.
Nginx + Vault Agent λ°°ν¬
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
svc μμ±
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
kubectl get pod -l app=nginx-vault-demo
NAME READY STATUS RESTARTS AGE
nginx-vault-demo-7776649597-tcm4l 2/2 Running 0 3m14s
μ κ· ν¨μ€μλ
vault + jenkins
ArgoCD + vault plugin
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: λ‘€
AVP_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
# kustomize edit fix
kubens argocd
kubectl kustomize .
kubectl apply -n argocd -k .
μ ν리μΌμ΄μ λ°°ν¬
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
λνλ‘μ΄λ¨ΌνΈμ μ μ©λ envκ°μ΄ λ³κ²½λ ν¨μ€μλλ‘ μ μ©λΌμλ κ²μ νμΈν μ μλ€.
Vault Secret Operator
# 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"]
κΆν μ€μ
kubectl exec --stdin=true --tty=true vault-0 -n vault -- /bin/sh
vault login
# Kubernetes μΈμ¦ λ©μλ νμ±ν
vault auth enable -path k8s-auth-mount 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)"
# vault k8s auth role
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
vault secrets enable -path=demo-db database
# 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"
# DB μ¬μ©μ λμ μμ± Role λ±λ‘
# ν΄λΉ Role μ¬μ© μ Vaultκ° λμ μΌλ‘ μ¬μ©μ κ³μ κ³Ό λΉλ°λ²νΈλ₯Ό μμ± κ°λ₯
# TTLμ μμ±λ μ격μ¦λͺ
μ μ ν¨ μκ° (30μ΄~10λΆ)
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"
# 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
vault secrets enable -path=demo-transit transit
# vso-client-cacheλΌλ ν€λ₯Ό μμ±
# μ΄ ν€λ VSOκ° μ볡νΈν μ μ¬μ©ν μνΈν ν€ μν
vault write -force demo-transit/keys/vso-client-cache
# 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
# 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
vault read auth/k8s-auth-mount/role/auth-role-operator
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: Sun Apr 13 02:35:06 2025
NAMESPACE: vault-secrets-operator-system
STATUS: deployed
REVISION: 1
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
vault-auth-dynamic.yaml
---
# 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
vault-dynamic-secret.yaml
---
# 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-secret.yaml
---
# app-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: vso-db-demo
namespace: demo-ns
app-secret-deploy.yaml
---
# 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
k 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
μ€μ΅ 리μμ€ μμ
docker compose down --volumes --remove-orphans
[+] Running 3/3
β Container jenkins Removed 0.5s
β Volume cicd-labs_jenkins_home Removed 0.2s
β Network cicd-labs_cicd-network Removed 0.2s
kind delete cluster --name myk8s
Deleting cluster "myk8s" ...
Deleted nodes: ["myk8s-worker2" "myk8s-worker" "myk8s-control-plane"]