상세 컨텐츠

본문 제목

10주차 - K8S 시크릿 관리 (2)

[AWS]/[EKS]

by scdo 2025. 4. 12. 23:34

본문

현재 Vault의 기본 구조와 설치, 그리고 Kubernetes 환경에서 Sidecar 패턴으로 Vault를 연동하는 부분까지 학습을 마쳤습니다.

이를 기반으로 이제 실제 CI/CD 파이프라인과 Kubernetes 환경에서 Vault를 활용하는 실습을 진행하려고 합니다.

 

최종적으로 Jenkins를 통한 CI, Argo CD를 통한 CD, 그리고 Vault Secrets Operator를 통한 Kubernetes 환경의 시크릿 관리까지 모두 Vault와 연계하여 일관성 있고 안전하게 시크릿을 다루는 체계를 마련하는 것이 목표입니다. 


1. Jenkins + Vault (AppRole) - CI

CI 파이프라인에서 필요한 민감 정보를 안전하게 관리하기 위해 Vault 의 KV Store 에 username 과 password 와 같은 정적 시크릿을 저장하고Jenkins 와 Vault 를 연동하여 파이프라인 실행 시 필요한 시크릿을 외부 Vault 로부터 안전하게 획득할 수 있도록 구성하여 사용하겠습니다.

워크플로우, 출처 - https://developer.hashicorp.com/vault/docs/auth/approle/approle-pattern#jenkins-ci-cd

 

① Jenkins에서 Vault Plugin 설치

설치 및 Jenkins 재시작

 

② Vault AppRole 정보 확인

Vault에서 발급된 ROLE_ID, SECRET_ID 이전에 생성한 role_id.txt, secret_id.txt 값을 참고하여 사용할  있습니다.

# Role ID
vault read auth/approle/role/<role-name>/role-id

# Secret ID
vault write -f auth/approle/role/<role-name>/secret-id

확인

 

 

③ Jenkins에서 Vault 설정 및 Credentials 추가

(1)
(2)
(3) 설정 후 저장

 

④ Jenkins Pipeline Job 생성

Jenkins UI → New Item → Pipeline 선택  jenkins-vault-kv 입력  생성

 

JekinsFile 작성

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}"
          }
        }
      }
    }
  }
}

Console Output

※ 참고 KV Version1은 경로에 data을 넣고 Version2는 경로에 data을 넣지 않습니다.(참고)
· Version 1 : secret/data/sampleapp/config
· Version 2 : secret/sampleapp/config

2. ArgoCD + Vault Plugin (Kubernetes Auth/AppRole) - CD

Argo CD Vault Plugin은 GitOps 환경에서 외부 시크릿 관리 도구를 손쉽게 통합할 수 있게 해주는 플러그인입니다.

Kubernetes Secret 뿐 아니라 다양한 리소스에 시크릿 데이터를 주입할 수 있고 설치 방법으로는 ConfigMap 방식과 사이드카 컨테이너 방식이 있으며, 보안성과 관리 효율성을 고려한다면 사이드카 컨테이너 방식을 우선적으로 검토하는 것이 좋습니다.사이드카 컨테이너를 활용한 방법은 Argo CD v2.4.0부터 도입된 최신 방식 입니다.

 

① ArgoCD Vault Plugin을 위한 Credentials 활성화(AppRole 인증)

 먼저 이전 실습에서 획득한 Role_ID Secret_ID 활용해서 Argo CD Vault 안전하게 접근하도록 만들겠습니다.

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: a0f91e0f-714e-2b23-788f-e728afa8582c #Role_ID
  AVP_SECRET_ID: db232aea-88ca-10f1-57ff-8ee14aaf1376 #Secret_ID
EOF

 

② ArgoCD Vault Plugin 설치

ArgoCD Helm 설치시 Plugin 활성화 방안

# GitHub 저장소에서 argocd-vault-plugin 예제 또는 배포용 파일 복제
git clone https://github.com/hyungwook0221/argocd-vault-plugin.git
cd argocd-vault-plugin/manifests/cmp-sidecar

# 예전 문법으로 적용된 부분을 edit fix 명령으로 현행화
# kustomize edit fix

# argocd 네임스페이스 설정
kubens argocd

# 생성될 메니페스트 파일에 대한 확인
kubectl kustomize .

# -k 옵션으로 kusomize 실행
kubectl apply -n argocd -k .
# vault-0 Pod 접속
kubectl exec -it -n vault vault-0 -- sh

# 접속 후 root token으로 로그인
vault login
Token (will be hidden): <토큰입력>
# 확인명령
vault read auth/kubernetes/role/argocd

확인

 

③ 샘플 Application 배포하여 Vault와 동기화

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값 확인

Argo CD 에서 Vault Plugin 을 사용할 때 Vault 설정 변경이나 인증 오류 발생 시 캐시된 정보 때문에 배포시 오류가 발생할 수 있기 때문에 Argo CD repo-server 와 Redis 를 재기동해서 캐시를 초기화한 다음 애플리케이션을 재배포 해주시면 됩니다.

3. Vault Secrets Operator (VSO)

Vault Secrets Operator는 Vault에 저장된 시크릿이나 HCP Vault 시크릿 앱의 데이터를 Kubernetes 네이티브 방식으로 Pod 에 주입하는 오퍼레이터 입니다.
VSO를 활용하면 Vault 에 있는 시크릿을 Kubernetes Secret 으로 자동으로 동기화해서 사용할 수 있고 애플리케이션은 Kubernetes Secret 만 바라보면 되기 때문에 Vault 와 직접적으로 통신할 필요가 없습니다.
즉, Vault 와 Kubernetes 사이의 시크릿 자동화 브릿지 역할을 하는 것입니다.

 

주요 특징과 동작 방식

  1. CRD 기반 자동 동기화
    • VSO는 Kubernetes 에 정의된 Custom Resource Definitions (CRD)을 감시합니다.
    • CRD 를 통해 어떤 Vault 시크릿을 Kubernetes Secret 으로 가져올지 정의할 수 있습니다.
    • 시크릿 소스가 변경되면 Kubernetes Secret 도 자동으로 업데이트합니다.
    • 결과적으로 애플리케이션은 Kubernetes Secret 만 참조하면 최신 시크릿을 사용할 수 있습니다.
  2. 지원하는 기능
    • 여러 Vault 시크릿 소스를 Kubernetes Secret 으로 동기화
    • 시크릿이 변조되거나 유효하지 않을 경우 자동으로 감지하고 복구
    • Deployment, ReplicaSet, StatefulSet 리소스에서 시크릿 변경 사항을 감지하고 자동으로 반영
    • Prometheus 계측을 통한 모니터링 지원
    • Helm chart 또는 Kustomize 를 통한 간편한 설치
    • 시크릿 데이터 변환 기능 지원
  3. 지원되는 Kubernetes 플랫폼
    • Amazon EKS
    • Google GKE
    • Microsoft AKS
    • Red Hat OpenShift (공식 인증)
  4. 비슷한 오픈소스 프로젝트
    • VSO 와 유사한 기능을 제공하는 오픈소스 프로젝트로는 [External Secrets Operator (ESO)] 가 있습니다.
    • ESO 역시 외부 시크릿을 Kubernetes Secret 으로 가져오는 오퍼레이터입니다.

VSO 구성도

구분 운영자 (Operator) 역할 개발자 (Developer) 역할
Vault 및 VSO 설치 Vault 서버 설치 및 VSO 배포 (Helm 또는 Kustomize) 사용자가 별도로 설치할 필요 없음
CRD 관리 SecretExternalResource 같은 VSO CRD 생성 및 관리 CRD 를 요청하거나 참고하지만, 직접 관리하지 않음
시크릿 정책 설정 Vault 정책 관리, 시크릿 동기화 대상 지정 애플리케이션이 참조할 Kubernetes Secret 이름만 인지
시크릿 접근 권한 Vault 인증 방식 (AppRole, Kubernetes Auth 등) 설정 및 접근 제어 별도 인증 로직 없이 Kubernetes Secret 만 참조
애플리케이션 연동 Kubernetes Secret 생성 및 유지보수 관리 애플리케이션에서 Kubernetes Secret 을 환경 변수나 마운트로 사용
모니터링 및 운영 Prometheus 등으로 VSO 상태 및 시크릿 동기화 모니터링 필요 시 알림을 받고 대응, 별도 모니터링 필요 없음
시크릿 변경 시 대응 Vault 또는 CRD 변경 시 Kubernetes Secret 자동 갱신 확인 애플리케이션은 변경된 Secret 을 자동으로 사용 (재배포 불필요)

 

VSO CRD 관계도

출처 - https://github.com/hashicorp/vault-secrets-operator/blob/main/docs/threat-model/README.md

 

주요 CRD 예시

① VaultConnection

# Vault 서버 연결 정보
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
  namespace: vso-example
  name: vault-connection
spec:
  address: http://vault.vault.svc.cluster.local:8200
  • address: Vault 서비스 주소 (클러스터 내부 DNS 사용)

 

② VaultAuth

# Vault 인증 정보 (주로 Kubernetes Auth)
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  namespace: vso-example
  name: vault-auth
spec:
  vaultConnectionRef: vault-connection
  method: kubernetes
  mount: kubernetes
  kubernetes:
    role: example
    serviceAccount: default
  • vaultConnectionRef: 연결할 VaultConnection 이름
  • method: 인증 방식 (Kubernetes)
  • role: Vault Kubernetes Auth 에서 정의한 Role
  • serviceAccount: 사용할 Kubernetes ServiceAccount

 

③ VaultAuthGlobal

# 전역 인증 정보 정의
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuthGlobal
metadata:
  namespace: vso-example
  name: vault-auth-global
spec:
  defaultAuthMethod: kubernetes
  kubernetes:
    audiences:
      - vault
    mount: kubernetes
    namespace: example-ns
    role: auth-role
    serviceAccount: default
    tokenExpirationSeconds: 600
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  namespace: vso-example
  name: vault-auth
spec:
  vaultAuthGlobalRef:
    name: vault-auth-global
  kubernetes:
    role: local-role

 

  • 여러 VaultAuth 가 공통으로 사용하는 전역 인증 정의

 

④ VaultStaticSecret

# Vault 의 정적 시크릿을 Kubernetes Secret 으로 동기화
# KV v1
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  namespace: vso-example
  name: vault-static-secret-v1
spec:
  vaultAuthRef: vault-auth
  mount: kvv1
  type: kv-v1
  path: eng/apikey/google
  refreshAfter: 60s
  destination:
    create: true
    name: static-secret1
---
# KV v2
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  namespace: vso-example
  name: vault-static-secret-v2
spec:
  vaultAuthRef: vault-auth
  mount: kvv2
  type: kv-v2
  path: eng/apikey/google
  version: 2
  refreshAfter: 60s
  destination:
    create: true
    name: static-secret2

 

  • refreshAfter: 주기적 동기화 간격

 

⑤ VaultDynamicSecret

# Vault 의 동적 시크릿 (DB, AWS IAM)
# DB Secret
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
  namespace: vso-example
  name: vault-dynamic-secret-db
spec:
  vaultAuthRef: vault-auth
  mount: db
  path: creds/my-postgresql-role
  destination:
    create: true
    name: dynamic-db
---
# AWS Secret
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
  namespace: vso-example
  name: vault-dynamic-secret-aws-iam
spec:
  vaultAuthRef: vault-auth
  mount: aws
  path: creds/my-iam-role
  destination:
    create: true
    name: dynamic-aws-iam

 

  • Vault 에서 동적으로 발급하는 인증 정보를 Kubernetes Secret 으로 동기화

 

⑥ VaultPKISecret

# Vault 의 PKI 시크릿을 Kubernetes Secret 으로 동기화
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultPKISecret
metadata:
  namespace: vso-example
  name: vault-pki
spec:
  vaultAuthRef: vault-auth
  mount: pki
  role: default
  commonName: example.com
  format: pem
  expiryOffset: 1s
  ttl: 60s
  namespace: tenant-1
  destination:
    create: true
    name: pki1
  • X.509 인증서 발급 자동화

Vault Secrets Operator 설치

VSO 배포를 위한 Chart Values 파일 작성

# 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"]

 

VSO 배포

helm install vault-secrets-operator hashicorp/vault-secrets-operator \
  -n vault-secrets-operator-system \
  --create-namespace \
  --values vault-operator-values.yaml

확인
확인

'[AWS] > [EKS]' 카테고리의 다른 글

11주차 - ML Infra(GPU) on EKS  (1) 2025.04.20
10주차 - K8S 시크릿 관리 (1)  (0) 2025.04.12
9주차 - EKS Upgrade  (0) 2025.04.03
8주차 - K8S CI/CD (3)  (0) 2025.03.30
8주차 - K8S CI/CD (1)  (1) 2025.03.30

관련글 더보기