2026년 Kubernetes 시크릿 관리 완벽 가이드: External Secrets, Vault, 면접 대비

Kubernetes 시크릿 관리의 모든 것을 다룹니다. External Secrets Operator, HashiCorp Vault 연동, 프로덕션 환경 모범 사례, 기술 면접 빈출 질문까지 상세히 설명합니다.

Kubernetes Secrets Management with External Secrets Operator and HashiCorp Vault architecture diagram

Kubernetes 시크릿 관리는 컨테이너 오케스트레이션에서 가장 중요한 보안 과제 중 하나입니다. 네이티브 Kubernetes Secret은 민감한 데이터를 base64 인코딩으로 저장하지만, 기본적으로 저장 시 암호화를 제공하지 않습니다. 이러한 취약점은 DevOps 채용 면접에서 자주 다뤄지는 보안 위험을 야기합니다.

면접 즉답 포인트

Kubernetes 시크릿 보안에 대해 질문받을 때: 네이티브 Secret은 base64 인코딩이며 암호화가 아닙니다. 프로덕션 환경에서는 HashiCorp Vault 또는 AWS Secrets Manager와 같은 외부 시크릿 관리자가 필요하며, External Secrets Operator(ESO)를 통해 동기화합니다. 이러한 분리를 통해 시크릿이 Git 저장소에 존재하지 않도록 보장합니다.

네이티브 Kubernetes Secret의 한계

내장 Secret 리소스는 etcd에 base64 인코딩으로 데이터를 저장합니다. 이 인코딩은 단일 명령으로 복원할 수 있습니다:

bash
# decoding-secret.sh
# Kubernetes 시크릿 값을 즉시 디코딩
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d

base64는 암호화가 아닙니다. 클러스터 접근 권한이 있는 사람이라면 누구나 시크릿 값을 읽을 수 있습니다. Kubernetes 문서에서는 Secret이 "기본적으로 암호화되지 않는다"고 명시하며, 저장 시 암호화를 활성화할 것을 권장합니다.

프로덕션 배포에 영향을 미치는 세 가지 주요 제한 사항이 있습니다:

  1. 감사 추적 부재: 네이티브 Secret은 누가 언제 어떤 값에 접근했는지에 대한 로그를 제공하지 않습니다
  2. 로테이션 메커니즘 부재: 시크릿 변경에는 수동 개입과 Pod 재시작이 필요합니다
  3. GitOps 비호환성: 암호화된 시크릿을 Git에 저장해도 암호화 키 관리 문제가 남습니다

External Secrets Operator 아키텍처

External Secrets Operator(ESO)는 Kubernetes와 외부 시크릿 관리 시스템을 연결합니다. 2023년 CNCF Sandbox 프로젝트로 출시되어 2026년에 v0.10에 도달했습니다. ESO는 AWS Secrets Manager, HashiCorp Vault, Google Secret Manager, Azure Key Vault 및 15개 이상의 백엔드를 지원합니다.

아키텍처는 세 가지 커스텀 리소스로 구성됩니다:

yaml
# secret-store.yaml
# ClusterSecretStore는 Vault로의 연결을 정의
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.internal:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"
          serviceAccountRef:
            name: "external-secrets"
            namespace: "external-secrets"

이 ClusterSecretStore는 Kubernetes 서비스 계정 토큰을 사용하여 Vault에서 인증하도록 ESO를 구성합니다. kubernetes 인증 방식은 클러스터의 TokenReview API에 대해 서비스 계정 JWT를 검증합니다.

yaml
# external-secret.yaml
# ExternalSecret은 실제 시크릿 데이터를 가져와 동기화
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: db-secret
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: secret/data/production/database
        property: username
    - secretKey: password
      remoteRef:
        key: secret/data/production/database
        property: password

ESO는 1시간마다 Vault를 폴링하고(refreshInterval: 1h), Kubernetes Secret을 자동으로 업데이트합니다. creationPolicy: Owner는 ExternalSecret이 삭제될 때 Secret도 삭제되도록 보장합니다.

HashiCorp Vault 연동 패턴

Vault는 동적 시크릿, 자동 로테이션, 포괄적인 감사 로깅을 제공합니다. Vault Kubernetes 인증 문서에 설명된 Kubernetes 인증 방식을 통해 장기 자격 증명을 배포하지 않고도 Pod가 인증할 수 있습니다.

Vault 인증 설정에는 세 가지 단계가 필요합니다:

bash
# vault-k8s-auth.sh
# Vault에서 Kubernetes 인증 방식 활성화
vault auth enable kubernetes

# Kubernetes API에 대해 토큰을 검증하도록 Vault 구성
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443" \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

# 서비스 계정을 정책에 바인딩하는 역할 생성
vault write auth/kubernetes/role/external-secrets \
  bound_service_account_names=external-secrets \
  bound_service_account_namespaces=external-secrets \
  policies=readonly-secrets \
  ttl=1h

이 구성은 external-secrets 서비스 계정을 Vault 정책에 바인딩합니다. TTL은 토큰 유효 기간을 제한하여 재인증을 강제하고, 손상된 토큰의 영향 범위를 줄입니다.

프로덕션 배포에서는 최소 권한 원칙을 따르는 정책이 필요합니다:

hcl
# readonly-secrets.hcl
# 특정 경로에 대한 읽기 전용 접근을 부여하는 Vault 정책
path "secret/data/production/*" {
  capabilities = ["read"]
}

path "secret/metadata/production/*" {
  capabilities = ["list"]
}

이 정책은 프로덕션 시크릿 경로에 대한 읽기 접근만 부여합니다. 다른 환경을 관리하는 팀은 해당 경로 제한이 있는 별도의 정책을 받습니다.

다운타임 없는 시크릿 로테이션

자동 로테이션은 시크릿이 노후화된 공격 벡터가 되는 것을 방지합니다. ESO는 Kubernetes 측을 처리하지만, 애플리케이션은 재시작 없이 시크릿을 다시 로드해야 합니다.

제로 다운타임 로테이션을 위한 두 가지 접근 방식이 있습니다:

파일 감시를 통한 볼륨 마운트 시크릿:

yaml
# deployment-volume-secrets.yaml
# 자동으로 업데이트되는 파일로 시크릿 마운트
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  template:
    spec:
      containers:
        - name: api
          image: api:v2.1.0
          volumeMounts:
            - name: secrets
              mountPath: /etc/secrets
              readOnly: true
      volumes:
        - name: secrets
          secret:
            secretName: db-secret

Kubernetes는 kubelet 동기화 기간 내(기본 1분)에 마운트된 시크릿 파일을 업데이트합니다. 애플리케이션은 각 데이터베이스 연결 시 /etc/secrets/password에서 자격 증명을 읽어 재시작 없이 새 값을 가져옵니다.

환경 변수 시크릿을 위한 Reloader:

환경 변수를 사용하는 애플리케이션에는 Pod 재시작이 필요합니다. Stakater Reloader가 이를 자동화합니다:

yaml
# deployment-with-reloader.yaml
# 어노테이션이 시크릿 변경 시 롤링 재시작을 트리거
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  annotations:
    reloader.stakater.com/auto: "true"
spec:
  template:
    spec:
      containers:
        - name: api
          envFrom:
            - secretRef:
                name: db-secret

Reloader는 Secret 업데이트를 감시하고 롤링 재시작을 수행하여 로테이션 중 가용성을 유지합니다.

DevOps 면접 준비가 되셨나요?

인터랙티브 시뮬레이터, flashcards, 기술 테스트로 연습하세요.

Kubernetes 시크릿 면접 질문

DevOps 면접에서는 시크릿 관리에 대한 이해를 일관되게 테스트합니다. 이러한 질문은 주니어부터 시니어 레벨까지 출제됩니다:

Q: Kubernetes Secret이 사용하는 인코딩은 무엇이며, 왜 보안에 불충분합니까?

Secret은 base64 인코딩을 사용하는데, 이는 가역 변환이지 암호화가 아닙니다. Secret에 대한 get 권한이 있는 모든 사용자가 값을 디코딩할 수 있습니다. 보안을 위해서는 저장 시 암호화(etcd 암호화 활성화)와 RBAC 권한 제한이 필요합니다. 더 깊은 Kubernetes 개념에 대해서는 Kubernetes 면접 기초를 참조하십시오.

Q: GitOps를 사용할 때 시크릿이 Git 저장소에 나타나지 않도록 하려면 어떻게 해야 합니까?

External Secrets Operator는 값 자체가 아닌 시크릿에 대한 참조만 Git에 저장합니다. ExternalSecret 매니페스트에는 Vault 또는 AWS Secrets Manager의 시크릿 경로가 포함되어 있으며, 실제 시크릿은 저장소에 절대 접촉하지 않습니다. Bitnami의 Sealed Secrets는 비대칭 암호화를 사용하는 대안적 접근 방식을 제공합니다.

Q: SecretStore와 ClusterSecretStore의 차이점을 설명하십시오.

SecretStore는 네임스페이스 범위입니다: 동일한 네임스페이스의 ExternalSecrets가 이를 참조할 수 있습니다. ClusterSecretStore는 클러스터 전체 범위입니다: 모든 네임스페이스에서 참조할 수 있습니다. 여러 팀이 단일 Vault 인스턴스를 공유할 때는 ClusterSecretStore를 사용하고, 각 네임스페이스가 격리된 시크릿 백엔드를 가질 때는 SecretStore를 사용합니다.

Q: 배포 후 Pod가 시크릿에 접근할 수 없습니다. 어떻게 트러블슈팅하시겠습니까?

ExternalSecret 상태부터 시작합니다:

bash
# troubleshoot-secrets.sh
# ExternalSecret 동기화 상태 및 조건 확인
kubectl get externalsecret database-credentials -o yaml

# Secret이 생성되었는지 확인
kubectl get secret db-secret -o yaml

# 인증 오류에 대해 ESO 컨트롤러 로그 확인
kubectl logs -n external-secrets deployment/external-secrets

일반적인 실패 원인으로는 만료된 Vault 토큰, 잘못된 시크릿 경로, ClusterSecretStore의 RBAC 구성 오류가 있습니다.

Q: 프로덕션 환경에서 데이터베이스 자격 증명의 시크릿 로테이션을 어떻게 처리하시겠습니까?

Vault의 데이터베이스 시크릿 엔진은 동적이고 수명이 짧은 자격 증명을 생성합니다. 자격 증명 TTL보다 짧은 refreshInterval로 ESO를 구성합니다. 로테이션이 필요한 정적 자격 증명의 경우, Vault의 로테이션 API와 Reloader를 결합하여 업데이트 후 Pod를 재시작합니다. 애플리케이션은 로테이션 기간 동안 연결 실패를 우아하게 처리해야 합니다.

AWS Secrets Manager와 ESO

AWS Secrets Manager 연동에는 서비스 계정용 IAM 역할(IRSA)이 필요합니다. 이 패턴은 정적 자격 증명을 완전히 제거합니다:

yaml
# aws-secret-store.yaml
# IRSA를 사용한 AWS Secrets Manager용 ClusterSecretStore
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
            namespace: external-secrets

서비스 계정 어노테이션이 IAM 역할에 연결됩니다:

yaml
# service-account-irsa.yaml
# IAM 역할 어노테이션이 있는 서비스 계정
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-secrets-sa
  namespace: external-secrets
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/external-secrets

AWS는 Lambda 함수를 사용하여 Secrets Manager에서 생성된 시크릿을 자동으로 로테이션합니다. ESO의 리프레시 간격과 결합하면, 구성된 폴링 기간 내에 시크릿이 Kubernetes로 전파됩니다.

멀티 클러스터 시크릿 동기화

여러 클러스터를 운영하는 조직에는 일관된 시크릿 배포가 필요합니다. 이 요구 사항을 해결하는 두 가지 패턴이 있습니다:

ClusterSecretStore를 사용한 허브 앤 스포크:

모든 클러스터가 중앙 Vault 인스턴스에 연결됩니다. 각 클러스터의 ESO 설치가 동일한 시크릿을 참조하고, Vault가 네임스페이스 기반 정책을 통해 접근 제어를 처리합니다.

Vault Enterprise를 통한 복제:

Vault Enterprise는 리전 간 성능 복제를 지원합니다. 각 클러스터가 로컬 Vault 복제본에 연결하여 일관성을 유지하면서 지연 시간을 줄입니다. Vault 복제 문서에서 재해 복구 및 성능 복제 모드를 다룹니다.

ArgoCD를 사용하는 팀의 경우, GitOps 배포 패턴 문서에서 여러 클러스터에 ExternalSecrets를 배포하는 ApplicationSets를 설명합니다.

시크릿 접근을 위한 RBAC 강화

기본 클러스터 역할은 과도한 시크릿 접근을 부여합니다. 최소한의 역할을 생성하여 RBAC를 강화합니다:

yaml
# restricted-role.yaml
# 특정 네임스페이스에서만 시크릿 접근을 허용하는 역할
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
    resourceNames: ["db-secret", "api-key"]

resourceNames 필드는 명시적으로 나열된 시크릿에 대한 접근을 제한합니다. 이 필드가 없으면 역할은 네임스페이스의 모든 시크릿에 대한 접근을 부여합니다.

결론

Kubernetes 시크릿 관리는 base64 인코딩의 한계를 이해하는 것에서 시작합니다. 프로덕션 환경에서는 External Secrets Operator를 통한 HashiCorp Vault 또는 AWS Secrets Manager와 같은 외부 시크릿 관리자가 필요합니다.

핵심 사항은 다음과 같습니다: 네이티브 Secret은 암호화를 제공하지 않습니다, ESO는 외부 백엔드와의 동기화를 자동화합니다, Vault는 동적 시크릿과 감사 로깅을 제공합니다, 그리고 RBAC는 최소 권한 원칙에 따라 강화해야 합니다. 이러한 개념은 DevOps 면접에서 정기적으로 테스트되며, 클라우드 네이티브 환경에서 시크릿 관리의 모범 사례를 형성합니다.

오늘의 챌린지

DevOps 코드의 버그를 찾을 수 있나요

실제 코드 한 조각, 숨은 버그 하나, 하루 한 번. 계정 없이 바로 도전할 수 있습니다.

Anthony Fillion-Maillet

작성자

Anthony Fillion-Maillet

SharpSkill 창업자

10년 이상 풀스택 개발을 해왔습니다. SharpSkill을 운영하며 이곳에 게시되는 모든 내용에 책임을 집니다.

2026년 9월 2일 업데이트

태그

#kubernetes
#secrets
#vault
#devops
#security

공유

관련 기사