Kubernetes Secrets 관리

Kubernetes Secret은 base64 인코딩일 뿐 암호화가 아닙니다. Git에 Secret YAML을 그대로 커밋하면 평문 패스워드가 이력에 영구적으로 남고, GitOps 워크플로에서는 Secret을 Git에 넣지 않으면 자동 배포가 불가능한 딜레마가 생깁니다.

이 글에서는 Kubernetes Secret의 보안 한계를 짚고, Sealed Secrets로 Git에 안전하게 암호화된 Secret을 커밋하는 방법, External Secrets Operator(ESO)로 AWS Secrets Manager·Vault 같은 외부 저장소와 동기화하는 패턴, 그리고 두 도구의 선택 기준까지 실무 관점으로 정리합니다.

1. Kubernetes Secret의 보안 한계

기본 Secret이 왜 위험한지 세 가지 관점으로 정리합니다.

문제 상세 영향
base64 ≠ 암호화 echo "cGFzc3dvcmQ=" | base64 -d로 즉시 복호화 Git 커밋에 평문 노출
etcd 평문 저장 기본 설정에서 etcd에 암호화 없이 저장 etcd 접근 권한 = 전체 Secret 탈취
RBAC 미설정 시 전체 노출 기본 ServiceAccount로 모든 Secret 조회 가능 한 Pod 침해 시 네임스페이스 전체 Secret 유출

etcd 암호화(EncryptionConfiguration)를 켜더라도 Git 커밋 문제는 해결되지 않습니다. GitOps 환경에서는 Sealed Secrets이나 External Secrets Operator 같은 추가 도구가 필수입니다.

2. Sealed Secrets: Git에 커밋 가능한 암호화된 Secret

Bitnami의 Sealed Secrets는 클러스터 내 컨트롤러만 복호화할 수 있는 비대칭 암호화를 적용합니다. 암호화된 SealedSecret 리소스는 Git에 안전하게 커밋할 수 있습니다.

설치

# 컨트롤러 설치 (Helm)
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets 
  --namespace kube-system

# CLI 도구 설치 (kubeseal)
brew install kubeseal  # macOS
# 또는 GitHub Releases에서 바이너리 다운로드

사용 흐름

# 1. 일반 Secret 생성 (로컬, 절대 Git에 커밋하지 않음)
kubectl create secret generic db-credentials 
  --from-literal=username=admin 
  --from-literal=password=s3cur3P@ss 
  --dry-run=client -o yaml > secret.yaml

# 2. kubeseal로 암호화 → SealedSecret 생성
kubeseal --format yaml  sealed-secret.yaml

# 3. sealed-secret.yaml을 Git에 커밋 (안전)
git add sealed-secret.yaml
git commit -m "add db-credentials sealed secret"

# 4. 클러스터에 적용 → 컨트롤러가 자동 복호화 → 일반 Secret 생성
kubectl apply -f sealed-secret.yaml
# sealed-secret.yaml 내용 (암호화됨, Git 커밋 가능)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-credentials
  namespace: default
spec:
  encryptedData:
    username: AgBy3i4OJSWK+PiTySYZ... # 공개키로 암호화된 값
    password: AgCtr2KJFS8dj3kF9sKd... # 클러스터 컨트롤러만 복호화 가능

핵심 포인트: SealedSecret은 특정 클러스터의 공개키로 암호화됩니다. 다른 클러스터에서는 복호화할 수 없으므로, 클러스터마다 별도로 seal해야 합니다.

3. External Secrets Operator: 외부 비밀 저장소와 동기화

External Secrets Operator(ESO)는 AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager 같은 외부 저장소에서 값을 가져와 Kubernetes Secret을 자동 생성·동기화합니다.

설치

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 연동 예시

# 1. SecretStore: 외부 저장소 연결 설정
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secrets
  namespace: my-app
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-credentials
            key: access-key-id
          secretAccessKeySecretRef:
            name: aws-credentials
            key: secret-access-key

---
# 2. ExternalSecret: 어떤 값을 어떤 Secret으로 매핑할지 정의
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: my-app
spec:
  refreshInterval: 1h  # 1시간마다 동기화
  secretStoreRef:
    name: aws-secrets
    kind: SecretStore
  target:
    name: db-credentials  # 생성될 K8s Secret 이름
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: production/db-credentials
        property: username
    - secretKey: password
      remoteRef:
        key: production/db-credentials
        property: password

refreshInterval로 외부 저장소의 값 변경이 자동으로 Kubernetes Secret에 반영됩니다. 패스워드 로테이션 시 앱을 재배포하지 않아도 Secret이 업데이트되는 것이 최대 장점입니다.

HashiCorp Vault 연동

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-store
spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "my-app"
          serviceAccountRef:
            name: my-app-sa

4. Sealed Secrets vs External Secrets Operator 선택 기준

기준 Sealed Secrets External Secrets Operator
비밀 저장 위치 Git (암호화된 형태) 외부 저장소 (AWS SM, Vault 등)
초기 구축 비용 낮음 (컨트롤러 + kubeseal만) 중간 (외부 저장소 설정 필요)
자동 로테이션 미지원 (수동 re-seal 필요) 지원 (refreshInterval로 자동 동기화)
멀티 클러스터 클러스터마다 별도 seal 필요 ClusterSecretStore로 통합 관리
감사 추적 Git 이력으로 추적 외부 저장소 감사 로그 활용
적합한 환경 소규모, 외부 저장소 없는 팀 중·대규모, 이미 Vault/AWS SM 사용 중인 팀

소규모 팀이나 사이드 프로젝트에서는 Sealed Secrets로 시작하고, 조직이 커지거나 패스워드 자동 로테이션이 필요해지면 ESO로 전환하는 것이 현실적인 경로입니다.

5. etcd 암호화: 클러스터 레벨 보안 강화

어떤 도구를 쓰든 최종적으로 Kubernetes Secret은 etcd에 저장됩니다. etcd 자체를 암호화하면 디스크 탈취 시에도 Secret이 보호됩니다.

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: 
      - identity: {}  # 기존 암호화 안 된 Secret 읽기용
# kube-apiserver에 플래그 추가
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml

# 기존 Secret 재암호화
kubectl get secrets --all-namespaces -o json | 
  kubectl replace -f -

identity 프로바이더를 마지막에 두면 기존에 암호화 없이 저장된 Secret도 읽을 수 있습니다. 모든 Secret을 재암호화한 후에는 identity를 제거하세요.

6. 운영에서 자주 하는 실수 5가지

  1. Secret YAML을 Git에 그대로 커밋 — base64는 암호화가 아닙니다. 커밋 이력에서 삭제해도 Git reflog에 남습니다. 이미 커밋했다면 패스워드를 즉시 로테이션하세요.
  2. Sealed Secrets 백업 키 미보관 — 컨트롤러가 삭제되면 기존 SealedSecret을 복호화할 수 없습니다. kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key로 키를 백업하세요.
  3. ESO refreshInterval을 너무 짧게 설정 — 1분마다 동기화하면 외부 저장소 API 호출 비용이 증가하고 rate limit에 걸릴 수 있습니다. 대부분 1시간이면 충분합니다.
  4. 네임스페이스 간 Secret 공유 시도 — Secret은 네임스페이스 범위입니다. ESO의 ClusterExternalSecret이나 Reflector 같은 도구로 복제하세요.
  5. 환경변수로만 Secret 주입 — 환경변수는 /proc/<pid>/environ으로 노출되고 로그에 찍힐 수 있습니다. 민감한 값은 Volume 마운트를 선호하세요.

마무리

Kubernetes Secret 관리는 base64 인코딩의 한계를 인식하는 것에서 시작합니다. Sealed Secrets로 Git 커밋 가능한 암호화를 적용하거나, External Secrets Operator로 외부 비밀 저장소와 자동 동기화하면 GitOps 워크플로에서도 안전하게 Secret을 관리할 수 있습니다. etcd 암호화까지 적용하면 클러스터 레벨의 보안 계층이 완성됩니다.

Kubernetes 보안과 운영을 더 깊이 다루고 싶다면, Kubernetes RBAC 심화 가이드Prometheus + Grafana 모니터링 실전 가이드도 함께 참고해보세요.

Sealed Secrets + ESO 설정 템플릿이 필요하신가요?
이 글에서 다룬 kubeseal 워크플로, ExternalSecret YAML, etcd EncryptionConfiguration을 바로 적용할 수 있는 템플릿 세트를 준비했습니다. 아래 댓글로 “시크릿 템플릿”이라고 남겨주시면 보내드립니다.

📥 관련 무료 이북

쿠버네티스 입문 가이드 — 실전 가이드 무료 제공

무료로 받기 →

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux