본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout

내비게이션

  • Tech
  • Projects
  • Books
  • About
  • Tags

카테고리

  • AI / ML
  • 웹 개발
  • 프로그래밍
  • 개발 도구

연결

  • GitHub
  • Email
  • RSS
© 2026 Kreath Archive. All rights reserved.Built with Next.js + MDX
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 8장: 시크릿 관리
2026년 3월 21일·인프라·

8장: 시크릿 관리

쿠버네티스 Secrets의 한계를 이해하고, HashiCorp Vault, External Secrets Operator, Sealed Secrets로 안전한 시크릿 관리 체계를 구축합니다.

14분775자10개 섹션
securitykubernetesdevopsinfrastructure
공유
container-security8 / 10
12345678910
이전7장: 네트워크 정책과 서비스 메시다음9장: 공급망 공격 방어와 제로 트러스트

학습 목표

  • 쿠버네티스 Secrets의 동작 방식과 보안 한계를 이해합니다.
  • HashiCorp Vault와 쿠버네티스 통합 방법을 실습합니다.
  • **External Secrets Operator(ESO)**로 외부 시크릿 관리 도구를 연동합니다.
  • 시크릿 로테이션 전략과 환경 변수 vs 볼륨 마운트의 차이를 파악합니다.

쿠버네티스 Secrets의 한계

쿠버네티스 Secret은 민감한 데이터를 저장하기 위한 기본 리소스입니다. 그러나 기본 설정에서는 여러 보안 한계가 있습니다.

Base64는 암호화가 아니다

k8s-secret-example.yaml
yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: production
type: Opaque
data:
  username: YWRtaW4=      # base64("admin")
  password: cDRzc3cwcmQ=  # base64("p4ssw0rd")
Base64 디코딩
bash
echo "cDRzc3cwcmQ=" | base64 --decode
# 출력: p4ssw0rd

Base64 인코딩은 암호화가 아닙니다. 누구든 디코딩할 수 있습니다. kubectl get secret -o yaml 명령으로 클러스터에 접근할 수 있는 사람이라면 모든 시크릿을 읽을 수 있습니다.

etcd 저장소 문제

기본 설정에서 시크릿은 etcd에 평문(또는 Base64)으로 저장됩니다. etcd 백업 파일이 유출되면 모든 시크릿이 노출됩니다.

접근 제어 부족

RBAC이 충분히 세밀하게 설정되지 않으면, 하나의 네임스페이스에 접근 권한을 가진 사용자가 해당 네임스페이스의 모든 시크릿을 읽을 수 있습니다.

Warning

쿠버네티스 기본 Secrets를 "안전한 시크릿 관리 도구"로 생각해서는 안 됩니다. 기본 Secrets는 민감 데이터와 일반 설정을 분리하는 논리적 구분일 뿐, 암호화나 접근 제어가 충분하지 않습니다.


etcd 암호화 설정

가장 기본적인 조치로, etcd에 저장되는 시크릿을 **Encryption at Rest(저장 시 암호화)**로 보호할 수 있습니다.

encryption-config.yaml
yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}  # 복호화 폴백

이 설정을 API 서버에 적용하면 etcd에 저장되는 시크릿이 AES-CBC로 암호화됩니다. 그러나 이것만으로는 불충분합니다. 암호화 키 자체를 누가 관리하는가의 문제가 남습니다.

클라우드 환경에서는 KMS(Key Management Service) 제공자를 사용하는 것이 권장됩니다.

encryption-config-kms.yaml
yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - kms:
          apiVersion: v2
          name: aws-kms
          endpoint: unix:///var/run/kmsplugin/socket.sock
      - identity: {}

HashiCorp Vault 통합

HashiCorp Vault는 시크릿 관리의 사실상 표준입니다. 중앙화된 시크릿 저장소, 동적 시크릿 생성, 감사 로그, 세밀한 접근 제어를 제공합니다.

Vault 아키텍처

쿠버네티스 인증 설정

Vault는 쿠버네티스 서비스 계정을 기반으로 인증할 수 있습니다.

Vault 쿠버네티스 인증 설정
bash
# 쿠버네티스 인증 백엔드 활성화
vault auth enable kubernetes
 
# 쿠버네티스 API 서버 연결 설정
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443"
 
# 역할 생성 (특정 서비스 계정 + 네임스페이스에 바인딩)
vault write auth/kubernetes/role/webapp \
  bound_service_account_names=webapp-sa \
  bound_service_account_namespaces=production \
  policies=webapp-policy \
  ttl=1h

정책 설정

vault-policy-webapp.hcl
hcl
# webapp 서비스가 접근할 수 있는 시크릿 경로
path "secret/data/production/webapp/*" {
  capabilities = ["read"]
}
 
# 데이터베이스 동적 자격증명
path "database/creds/webapp-role" {
  capabilities = ["read"]
}
 
# 다른 경로는 모두 차단 (암묵적 거부)

Vault Agent Sidecar Injector

Vault Agent Injector는 파드에 사이드카를 자동 주입하여 Vault에서 시크릿을 가져옵니다.

vault-sidecar-injection.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
  name: webapp
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "webapp"
    vault.hashicorp.com/agent-inject-secret-db-creds: "secret/data/production/webapp/db"
    vault.hashicorp.com/agent-inject-template-db-creds: |
      {{- with secret "secret/data/production/webapp/db" -}}
      export DB_HOST="{{ .Data.data.host }}"
      export DB_USER="{{ .Data.data.username }}"
      export DB_PASS="{{ .Data.data.password }}"
      {{- end -}}
spec:
  serviceAccountName: webapp-sa
  containers:
    - name: webapp
      image: myapp:latest
      command: ["/bin/sh", "-c", "source /vault/secrets/db-creds && ./start.sh"]

Vault Agent가 사이드카로 주입되어 /vault/secrets/db-creds 파일에 시크릿을 렌더링합니다. 애플리케이션은 이 파일을 읽어 사용합니다.

Info

Vault의 동적 시크릿(Dynamic Secrets) 기능을 사용하면, 데이터베이스 자격증명을 요청할 때마다 새로운 임시 계정이 생성되고 TTL 만료 시 자동 삭제됩니다. 자격증명 유출의 영향 범위를 최소화하는 강력한 기능입니다.


External Secrets Operator

**External Secrets Operator(ESO)**는 외부 시크릿 관리 도구(Vault, AWS Secrets Manager, GCP Secret Manager 등)의 시크릿을 쿠버네티스 Secret으로 자동 동기화하는 오퍼레이터입니다.

ESO 설치 및 설정

ESO 설치
bash
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
  --namespace external-secrets \
  --create-namespace

AWS Secrets Manager 연동 예시

eso-secret-store.yaml
yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secret-store
  namespace: production
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: eso-service-account
eso-external-secret.yaml
yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: production
spec:
  refreshInterval: 5m
  secretStoreRef:
    name: aws-secret-store
    kind: SecretStore
  target:
    name: db-credentials
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: production/webapp/db
        property: username
    - secretKey: password
      remoteRef:
        key: production/webapp/db
        property: password

ESO가 5분마다 AWS Secrets Manager에서 값을 가져와 쿠버네티스 Secret을 업데이트합니다. 외부에서 시크릿을 변경하면 자동으로 클러스터에 반영됩니다.


Sealed Secrets

Sealed Secrets는 Bitnami에서 개발한 도구로, 시크릿을 암호화하여 Git 저장소에 안전하게 저장할 수 있게 합니다.

Sealed Secrets 사용법
bash
# 시크릿 매니페스트 생성
kubectl create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password=s3cr3t \
  --dry-run=client -o yaml > secret.yaml
 
# SealedSecret으로 암호화
kubeseal --format=yaml < secret.yaml > sealed-secret.yaml
 
# Git에 커밋 (암호화되어 안전)
git add sealed-secret.yaml
git commit -m "feat: DB 시크릿 추가"
sealed-secret.yaml
yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-creds
  namespace: production
spec:
  encryptedData:
    username: AgBy3i4OJSWK+PiTySYZZA9r...
    password: AgCtr85w2GOjP4sHLiS3D2O...

SealedSecret 리소스는 암호화되어 있으므로 Git에 안전하게 저장할 수 있습니다. 클러스터의 Sealed Secrets Controller만이 이를 복호화할 수 있습니다.

Tip

GitOps 워크플로우를 사용하는 팀에게 Sealed Secrets는 가장 간단한 시크릿 관리 방법입니다. 별도의 외부 시크릿 관리 도구가 필요 없고, Git이 시크릿의 단일 진실 공급원(Single Source of Truth)이 됩니다.


CSI Secret Store

Secrets Store CSI Driver는 시크릿을 파드의 볼륨으로 직접 마운트하는 CSI(Container Storage Interface) 드라이버입니다.

secret-provider-class.yaml
yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: vault-db-creds
  namespace: production
spec:
  provider: vault
  parameters:
    vaultAddress: "https://vault.example.com:8200"
    roleName: "webapp"
    objects: |
      - objectName: "db-username"
        secretPath: "secret/data/production/webapp/db"
        secretKey: "username"
      - objectName: "db-password"
        secretPath: "secret/data/production/webapp/db"
        secretKey: "password"
  secretObjects:
    - secretName: db-creds-synced
      type: Opaque
      data:
        - objectName: db-username
          key: username
        - objectName: db-password
          key: password
pod-with-csi-secret.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
    - name: webapp
      image: myapp:latest
      volumeMounts:
        - name: secrets
          mountPath: /mnt/secrets
          readOnly: true
  volumes:
    - name: secrets
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: vault-db-creds

시크릿 주입 방식 비교

환경 변수 vs 볼륨 마운트

항목환경 변수볼륨 마운트
접근 방식process.env.DB_PASS파일 읽기
로테이션파드 재시작 필요파일 변경으로 자동 반영 가능
메모리 노출/proc/[pid]/environ에 노출파일시스템만 접근 가능
디버깅env 명령으로 확인 가능cat 명령으로 확인 가능
보안 수준낮음 (프로세스 환경 노출)높음 (파일 권한 제어 가능)
Warning

환경 변수로 주입된 시크릿은 /proc/[pid]/environ 파일을 통해 노출될 수 있고, 크래시 덤프나 로그에 포함될 위험이 있습니다. 가능하면 볼륨 마운트 방식을 사용하세요.


시크릿 로테이션

시크릿은 주기적으로 교체(로테이션)해야 합니다. 유출 시 피해를 최소화하기 위함입니다.

자동 로테이션 전략

Vault의 동적 시크릿은 TTL이 만료되면 자동으로 새 자격증명이 생성됩니다. ESO는 refreshInterval에 따라 주기적으로 외부 시크릿을 동기화합니다.

애플리케이션 측에서는 시크릿 파일의 변경을 감지하여 자동으로 연결을 갱신하는 로직이 필요합니다.

secret-watcher.go
go
package main
 
import (
    "os"
    "time"
    "log"
)
 
func watchSecret(path string, onChange func([]byte)) {
    var lastMod time.Time
    for {
        info, err := os.Stat(path)
        if err != nil {
            log.Printf("시크릿 파일 확인 실패: %v", err)
            time.Sleep(5 * time.Second)
            continue
        }
        if info.ModTime().After(lastMod) {
            data, _ := os.ReadFile(path)
            onChange(data)
            lastMod = info.ModTime()
        }
        time.Sleep(5 * time.Second)
    }
}

정리

이번 장에서는 컨테이너 환경의 시크릿 관리를 다루었습니다.

  • 쿠버네티스 기본 Secrets는 Base64 인코딩일 뿐이며, etcd 암호화와 RBAC을 추가로 설정해야 합니다.
  • HashiCorp Vault는 중앙화된 시크릿 관리, 동적 시크릿, 감사 로그를 제공하는 가장 종합적인 솔루션입니다.
  • External Secrets Operator는 다양한 외부 시크릿 관리 도구를 쿠버네티스와 연동합니다.
  • Sealed Secrets는 GitOps 워크플로우에서 시크릿을 Git에 안전하게 저장할 수 있게 합니다.
  • 시크릿은 환경 변수보다 볼륨 마운트로 주입하는 것이 보안상 유리합니다.

다음 장에서는 이 시리즈의 핵심 주제인 공급망 공격 방어와 제로 트러스트를 다룹니다. 의존성 혼동, 타이포스쿼팅 등 공급망 공격 유형과 SLSA 프레임워크 기반의 방어 전략을 실습합니다.

이 글이 도움이 되셨나요?

관련 주제 더 보기

#security#kubernetes#devops#infrastructure

관련 글

인프라

9장: 공급망 공격 방어와 제로 트러스트

의존성 혼동, 타이포스쿼팅, CI 침투 등 공급망 공격 유형을 분석하고, SLSA 프레임워크와 어드미션 컨트롤러 기반의 제로 트러스트 방어 전략을 구축합니다.

2026년 3월 23일·16분
인프라

7장: 네트워크 정책과 서비스 메시

쿠버네티스 NetworkPolicy로 기본 거부 정책을 구현하고, Calico/Cilium 네트워크 정책과 Istio mTLS로 컨테이너 간 통신을 안전하게 제어합니다.

2026년 3월 19일·14분
인프라

10장: 실전 프로젝트 — 컨테이너 보안 파이프라인 구축

빌드, 스캔, 서명, 배포, 런타임 모니터링까지 전체 컨테이너 보안 파이프라인을 GitHub Actions와 쿠버네티스 기반으로 통합 구축하는 실전 프로젝트입니다.

2026년 3월 25일·18분
이전 글7장: 네트워크 정책과 서비스 메시
다음 글9장: 공급망 공격 방어와 제로 트러스트

댓글

목차

약 14분 남음
  • 학습 목표
  • 쿠버네티스 Secrets의 한계
    • Base64는 암호화가 아니다
    • etcd 저장소 문제
    • 접근 제어 부족
  • etcd 암호화 설정
  • HashiCorp Vault 통합
    • Vault 아키텍처
    • 쿠버네티스 인증 설정
    • 정책 설정
    • Vault Agent Sidecar Injector
  • External Secrets Operator
    • ESO 설치 및 설정
    • AWS Secrets Manager 연동 예시
  • Sealed Secrets
  • CSI Secret Store
  • 시크릿 주입 방식 비교
    • 환경 변수 vs 볼륨 마운트
  • 시크릿 로테이션
    • 자동 로테이션 전략
  • 정리