SealSecret vs AWS Secret Manager

2026. 1. 2. 23:02·Network

시작하며

최근에 개발 환경을 Dev와 Prod로 나누면서 비밀키 관리에 대해서 진지하게 고민하게 됐습니다. 특히 ArgoCD를 사용하면서 이 문제가 더 두드러졌는데요, 오늘은 그 과정에서 시도했던 여러 방법들과 최종적으로 선택한 방식에 대해 공유해보려고 합니다.

문제 상황

Dev 환경에서는 로컬 PC에 K8s를 올려서 작업했기 때문에, 비밀키를 어떻게 관리할지가 큰 고민이었습니다. ArgoCD가 GitOps 방식으로 동작하다 보니, 결국 비밀키 값들이 GitHub에 올라가야 하거나, 아니면 별도로 CLI를 통해 통신해서 비밀키를 가져와야 하는 상황이었거든요.

이 문제를 해결하기 위해 여러 방법들을 찾아보기 시작했습니다.

방법 1: SealedSecret을 이용한 Dev 환경 구성

여러 방법을 살펴보다가 SealedSecret이라는 방법을 발견했습니다.

SealedSecret이란?

SealedSecret은 Bitnami에서 만든 Kubernetes용 암호화 솔루션입니다. 일반적인 Secret을 암호화해서 안전하게 Git에 저장할 수 있게 해주는 도구인데요, 작동 방식은 이렇습니다:

  1. 비밀키를 SealedSecret으로 암호화
  2. 암호화된 내용을 Git에 안전하게 커밋
  3. 클러스터 내의 SealedSecret Controller가 자동으로 복호화
  4. 일반 Kubernetes Secret으로 변환

이 방식 덕분에 Dev 환경에서는 비교적 쉽게 비밀키를 관리할 수 있었습니다.

실제 적용 예시

---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: wealist-argocd-secret
  namespace: wealist-dev
spec:
  encryptedData:
    GIT_ACCESS: AgCSRfSkYobhxGeN2QzjF+fVUviSzaaHZCcxEmjN33zrx14/av+t+/fWUEGVq6pgKGU19LNowTmqXIDNTqV222KHaVCCR0+oc0droPOo6wjqKj+kaHqo2e764Qc6eOH0nfOjRcibRVZOYnzgN9dkpO0lh4WL0pS24GNQI5xCCoXzoHsgEFs7nFRgwmiVoIwfjsWwvac7sHKGYnvMciQnYEjxEqBoOhGQHAy9HrssSeAE4Qj+4AHD8uTbhB9Qjq1nTPLB+Q1zO6SLMwMy/aVTCmiJbd6u2O5HhT2TLAiARbsrn1ss9A/OuznVrGTqgE1Mqt3iCO2Ag9J4BJUol1oQqgBJEGgijqJ/OlY571OLxg21m4gGG3LAnH+4CocQSm3H4AqQSuqq8wWOmgFujAqxkXv6yPcp9qxrwLiqq18NtOk10BV4Sijj5j5u8bOaqDd5DahMLHZg4EbEZryYDWNzEtmGiwNoMDQX9NSlq+3gj2NKBdZELu4C8VrOdm+eTr0FbuD5RxqWZzTA/x5WyrsTRDxmW3W9z/xri3LeSIgreQUh35z4YdlhJjooHXetS3fQQD25frocoXLwH13r/ZRTUKONtASEDS4mBTCNdcxkGHEu44ORNKEGvHKwFa508yRYVwNXdq4S04oubq+5vtvh+lYCSw57qLynPRHXbkK8mS961EH4f0sCcsKaqpCF7WwbjYQxzU5SJ1gnyP1EmHIm05eK4Vxr3MDcY3+WJQlZGk/9z8gkPwg/71r7
    GIT_NAME: AgAeeNuIs+nLwg/r1CoX3lGLG8LMbNiGQ99822RmBkVVM1Mi5cVP3I4yro8ajCAkpf3eREP50yoxCkqhLRCmE9nXBt0YoC9O6UrLAdWNcqfYkBbmj3kFCbxHBMZrkCn6X9qcaxsBjvvi2K+DqiP/Jvvsxnlp1XP3twG2BCfAzcEIQVL0L4SbInpRtujNRlZ/ulSivfZmHVM/eC2P0WpLqx7DsRg7RkpHG2TsgBhrHFYQSqE48kFPH88XrIcecSZHh33tDOo3KukzY3tdDm00rdawKy7ssRMPBtHCYxeB3cVTCuhpisY2BIc1lOIydN4XEFwDmlUrrUuOPD05pnQ31vSyXfQNzRW/3jK8IW9eqK5sILyf+0MGCsgLLPBECtJtn+ltjIIlR7HL2DuwdwNIMnMDQ9+mKwPc9+mBWb/zP5AE0BKvZhdj1B2DqlKHSvHwqB7mQJIAHTV7Z3Wf73f6YxPgj6x1PWTKpPjAEeostf1nPWSfYU7Yr3XMjbPmBVQp2T8SZLPrGrtQQxF22Hfj9t7U4+/ZtfmL3fre+cZ3aDb19Zo0mL3teWsepVl5dVte5szbbf8QkuQvVK8GIrBMytT7O8AttGcMn9hzCwfEfdvRKwnCotClF/cmep7bXh78Oo2BXX9Og8VpudQ/tBDb3OJz5S0pz/5eXdqLgO6Iy3gCHs1Bq4uep777JkPrhDyPpAw8TloiQ10Q
    GOOGLE_CLIENT_ID: AgBeS9Ql7W1Nw6N1bmASkdfHmrMRajE5tcW0JOHg8Mm6GtcIjqNqi+1GH+31uN8lhOo3zsoW0ZZZUly6Nb/aob9B8eF62r0pQeE5nwgPy441rpbhRHjXO+qfnKV16c9dYb0YtJaAVXENNKJZ9pxVQg6y4cL96BWXedeSgxj8f1sLC6GT+ynzOcGRtkzs1YpqzCC9q6XubUJF9hgSLeyJN5L80C+TkYEe2Qv74U6TaWI5/hNOIRFsb0Hq6gEWheiQhZnD/UaBlBF88/87u/Ct2rClCmznckAnbKMOIXNn9ucmuiC41rL3VZT3gBV1fvnPh9gDtTz9v8BTHFzgY2Q0xonHwwN3S8hj0WsL5eL8j49wW+yova8ubR4+/9PRzcLA72PFBZcc64zdrklnDzL7ulyDELXe1TVVulp7mtByKujhDoT2kxzo9vxhgO2do7L5lOv4MM/HsPrJsK9X5XgAJwoARaFC/OyzeEhXdJMp24rgQEO2uniTUTg7AVhRWU4WkP03C0SPZPb6X1A0bkCw+6goyHBqSMol538+nEBo2wkFKL46wxQFLLzSZtMbIqLJbAKT18/lKdxJ+EGmUv8qj6c7ngfvtjSLR6UlkHj+OPTwXRUUqqNGySygH3dSvJacHd1RLnTFJMv487yXce9mAev54kWDknKBFMt+V0YMOImG8MignUfq57hBE5PmVcjdGaBKj1cdvBu8oqyoYI9s6JkfC/sV6hISpG8beO3yLLyRkUVavzSVESaAIUfq8Ep1c8yfVZH/S6Yfp1eGjbhALA4fXA7bdpn7QQk=
    GOOGLE_CLIENT_SECRET: AgBGzv2TpkzR07mPh61R+1T4moGRcFGwxOdel9/gTG4g/+jIbRgOq81hKL0zcE5kIdB3susOprj6jtXuunkDtKcK4i1zuDLePVrZuXoV1ehJSUfrDAi8RZ1CcFwiYz29b+QqB2oHK4kXVTYu5eXLlTLm+j1i80Isu8IVAGQg+ybBy9DQD46HgivDeYOobB1B4BVBvSaBJYf8zhBYpFggQj8usqKsGlpV35BWr0KFC52UTqIHEsLYDDwjR0S0spJFRbQKA/qB0ADzlH+ckYNRoBF+XjMH97NAlTitEW5LK2J0dxrp2xdQkcEepAcWEWSZ/DRkiNd7ZVRIkjZvczagIYkGKmdOjXfay82zqhvBpU1d6CoC9PgqwQFuS/Fyf6sHm7vDKALtk0lN+jSnbEDBptyeG7Kgt7TQD/+xDjxZZPSAwYBxD0qRV4w/miCEUT4PTEDddwbdiumlq3XOZupDvaLXcsI0UxF9EmhHRHaWc64MfdO8vxECMMxukUlqWHUdOCaUqZ3kGVah+VrG/j/cnUlodJbXEhFyV5aiu4bpYNDfGXhhfuIMx+D2VSozK1EllJZdNgQJ/LubQSkb/A8E52Hf6Deap6mEDlmlNfaSBIODS8wBHDdJICXDo5ZDFDVnAJcYsqKeIhIYdsK4fe32jsRtDgsbOtOuEo4N4yoB5IJ1BBiWpSIKgQ2CPbk0Moso5ak7VuutEgpreRp29Tju6rC5PLLSTdY0m9CHXlXquOajiBx4Ag==
    JWT_SECRET: AgBD8v0MwnnnPUNYGRBXngmN/e0GM41pFrf+RqEzOdVumWZ33UbaSE34nHqRM5VKTobaIZbDdm0ACUDCf6TT0M6oEeNsiWwH/WV4Ta+KqL0rxZuNY6uFLziRfnFf5721KzQSyUVUojK2c9zvgHw3vo2ONwbm6pvuvpflVpHQSOgpUQZv1S4MhYtTXY9+a/dteFDCJTAPYnPlO8zBRvpIbAyxeIgomAcCC7ekIzp+qjczdE3VEYby9Sy45pzSKebeHupM1Y8fBgZAB0XL7uSLDMpU3B4omev/1M43L6UjAtWFn/7ODvfpBBPnZicW1ICu1FImsOIHGOriwaB1YYsV55KH4LzL3MBvg6T/Z/WDZuuuIc4yanN7FJibRhfJy7sIIymCe7zdbof6w/vkGDCMbCUJCPKSCM7qg7WCEuNg6SEeFR1FNSIOBFDXYo2kOGClMpPisHgkjr4B82lOrfibEm+0ZHleUt55oR9bu9yyNps716iyCLHCqr4rZANuMCBvxukhCogxuQie61Ey7VYQjqFFthVXMjjlJGeMgWO8qekPV++iKKZNZxZ7SFvteI59+G8Kqh7K5NW8Adbu7xW/z0Tn2NtymadTHqb+iEN1OqMcnrrVoaVa3aD/MFUHpAejJKb4bXQhuGfF8zV2hrlBr5DqaiHff2pIR4frQ9Rqxx9LhDo3E5bP3UDHBLo8Hzx4zb5P1NkPUHW0kUxTSzO1P/cXy7dDM5r6wqX+oAWQ4pXooTqAMm172G9crUzCoNQ0tzzJVX094xgU5xDKLLy42/K5r+t3FMy0lpRufyZXJ5yjqw==
  template:
    metadata:
      labels:
        app.kubernetes.io/component: shared-secret
        app.kubernetes.io/name: wealist-argocd-secrets
      name: wealist-argocd-secret
      namespace: wealist-dev
    type: Opaque

보시다시피 encryptedData 부분에 암호화된 값들이 들어가 있고, 이걸 그대로 Git에 올려도 안전합니다. 클러스터 내부의 컨트롤러만 복호화할 수 있거든요.

SealedSecret의 장점

  • Git에 안전하게 비밀키를 저장 가능
  • GitOps 워크플로우와 완벽하게 호환
  • 로컬 환경이나 Dev 환경에서 사용하기 간편
  • 별도의 외부 서비스 의존성 없음

SealedSecret의 한계

하지만 Prod 환경을 구성하면서 몇 가지 한계를 느꼈습니다:

  • 비밀키 로테이션이 번거로움
  • 중앙화된 비밀키 관리가 어려움
  • 감사 로그(Audit Log) 기능 부재
  • 여러 클러스터나 환경 간 비밀키 공유가 복잡함

방법 2: External Secrets Operator + AWS Secrets Manager

Prod 환경을 구성할 때는 좀 더 프로덕션 레벨의 솔루션이 필요했습니다. AWS 환경을 사용하고 있었기 때문에, AWS의 네이티브 서비스를 활용하는 것이 더 합리적이라고 판단했고, **External Secrets Operator(ESO)**와 AWS Secrets Manager를 조합해서 사용하기로 결정했습니다.

External Secrets Operator란?

ESO는 외부 비밀키 저장소(AWS Secrets Manager, HashiCorp Vault, Azure Key Vault 등)에서 비밀키를 가져와 Kubernetes Secret으로 동기화해주는 오퍼레이터입니다.

작동 방식:

  1. ClusterSecretStore를 설정 (AWS Secrets Manager 연결 정보)
  2. ExternalSecret 리소스로 필요한 비밀키 정의
  3. ESO가 자동으로 AWS에서 값을 가져와 K8s Secret 생성
  4. 주기적으로 동기화 (refreshInterval 설정 가능)

실제 구현 예시

# =============================================================================
# External Secrets - ClusterSecretStore + ExternalSecret
# =============================================================================
# AWS Secrets Manager에서 시크릿을 가져와 K8s Secret으로 생성
# Terraform에서 생성된 시크릿들을 참조

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: external-secrets-config-prod
  namespace: argocd
  annotations:
    argocd.argoproj.io/sync-wave: "1"
spec:
  project: wealist-prod
  source:
    repoURL: https://github.com/OrangesCloud/wealist-project-advanced-k8s.git
    targetRevision: k8s-deploy-prod
    path: k8s/argocd/base/external-secrets
  destination:
    server: https://kubernetes.default.svc
    namespace: wealist-prod
  # ESO가 자동으로 추가하는 기본값 필드 무시
  ignoreDifferences:
    - group: external-secrets.io
      kind: ExternalSecret
      jqPathExpressions:
        - .spec.data[].remoteRef.conversionStrategy
        - .spec.data[].remoteRef.decodingStrategy
        - .spec.data[].remoteRef.metadataPolicy
        - .spec.target.deletionPolicy
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      
========================ESO가 AWS Secret에 연결 후 알아서 가져오기 떄문에 따로 작성할 필요 없음=============

Terrform으로 ESO 생성 후 aws Secrets Manager에 연결

AWS Secrets Manager + ESO의 장점

이 방식을 선택하면서 얻게 된 장점들:

1. 중앙화된 비밀키 관리

  • AWS Secrets Manager 콘솔에서 모든 비밀키를 한 곳에서 관리
  • 여러 환경, 여러 클러스터에서 동일한 비밀키 저장소 사용 가능

2. 자동 로테이션

  • AWS Secrets Manager의 자동 로테이션 기능 활용
  • RDS, ElastiCache 등의 비밀키를 자동으로 갱신 가능

3. 세밀한 접근 제어

  • IAM 정책을 통한 세밀한 권한 관리
  • 누가, 언제, 어떤 비밀키에 접근했는지 CloudTrail로 추적

4. Terraform과의 통합

  • Infrastructure as Code로 비밀키 생명주기 관리
  • 자동으로 생성되는 비밀키(JWT_SECRET, DB 패스워드 등)와 수동으로 업데이트하는 비밀키(OAuth 자격증명 등) 구분 가능

5. 어노테이션과 라벨을 통한 효율적인 관리

  • Kubernetes 네이티브한 방식으로 비밀키 접근
  • 환경별, 서비스별로 필요한 비밀키만 선택적으로 마운트

구현 시 주의사항

실제로 구현하면서 주의했던 점들:

1. IAM 권한 설정

# ServiceAccount에 IRSA(IAM Roles for Service Accounts) 설정 필요
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-secrets-sa
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/external-secrets-role

2. refreshInterval 조정

  • 너무 짧으면 AWS API 호출 비용 증가
  • 너무 길면 비밀키 변경사항 반영이 느림
  • 1시간 정도가 적당했음

3. 비밀키 네이밍 컨벤션

{service}/{env}/{category}/{specific-name}
예: wealist/prod/database/endpoint

방법 3: HashiCorp Vault (고려했지만 선택하지 않음)

HashiCorp Vault도 검토했었습니다. Vault는 매우 강력한 비밀키 관리 플랫폼이지만, 우리 상황에서는 AWS Secrets Manager를 선택했습니다.

Vault의 장점

  • 동적 비밀키 생성 (Dynamic Secrets)
  • 강력한 암호화 as a Service 기능
  • 다양한 인증 백엔드 지원
  • 플랫폼 중립적 (멀티 클라우드 지원)

왜 AWS Secrets Manager를 선택했나?

1. 운영 복잡도

  • Vault는 별도의 클러스터 운영이 필요
  • HA 구성, 백업, 업그레이드 등 관리 포인트 증가

2. AWS 생태계와의 통합

  • 이미 AWS를 사용 중이므로 네이티브 통합이 자연스러움
  • RDS, ElastiCache 등과의 자동 로테이션이 쉬움
  • IAM, CloudTrail 등 기존 AWS 보안 인프라 활용

3. 비용

  • Vault 클러스터 운영 비용 vs AWS Secrets Manager 사용료
  • 우리 규모에서는 AWS Secrets Manager가 더 경제적

4. 학습 곡선

  • 팀원들이 이미 AWS에 익숙함
  • Vault는 새로운 개념과 운영 노하우 필요

결국 **"필요한 기능을 충분히 제공하면서, 운영 부담이 적은 솔루션"**을 선택하는 것이 중요하다고 판단했습니다.

환경별 선택 가이드

제 경험을 바탕으로 정리한 가이드입니다:

Dev/로컬 환경

추천: SealedSecret

  • 빠른 셋업
  • Git으로 관리 가능
  • 외부 의존성 없음
  • 팀원 간 쉬운 공유

Staging 환경

추천: ESO + AWS Secrets Manager (또는 Vault)

  • Prod과 동일한 구조로 테스트
  • 운영 프로세스 검증
  • 하지만 별도의 AWS 계정/네임스페이스 사용

Production 환경

추천: ESO + AWS Secrets Manager (또는 Vault)

  • 엔터프라이즈급 보안
  • 감사 로깅
  • 자동 로테이션
  • 중앙화된 관리

멀티 클라우드 환경

추천: HashiCorp Vault

  • 플랫폼 중립적
  • 일관된 비밀키 관리 경험
  • 하지만 운영 복잡도 증가는 감수해야 함

배운 점

이번 작업을 통해 배운 가장 큰 교훈은:

"모든 환경에 맞는 완벽한 솔루션은 없다"

각 환경의 특성, 팀의 역량, 인프라 상황에 따라 가장 적합한 도구를 선택하는 것이 중요합니다.

  • Dev 환경에서는 빠른 이터레이션과 간편함이 중요
  • Prod 환경에서는 보안, 감사, 안정성이 최우선
  • 팀의 기존 기술 스택과 잘 통합되는지도 중요한 고려사항

처음에는 "가장 좋은" 솔루션을 찾으려고 했지만, 결국 "우리 상황에 가장 적합한" 솔루션을 찾는 것이 더 현명한 선택이었습니다.

마치며

비밀키 관리는 DevOps에서 피할 수 없는 주제입니다. 이번 경험을 통해 여러 방법들을 직접 사용해보면서, 각 도구의 장단점을 몸소 체험할 수 있었습니다.

여러분도 환경을 구성하실 때, 이 글이 조금이나마 도움이 되길 바랍니다. 궁금한 점이나 다른 경험이 있으시면 댓글로 공유해주세요!

참고 자료

  • SealedSecrets GitHub
  • https://devocean.sk.com/blog/techBoardDetail.do?ID=167563&boardType=techBlog

'Network' 카테고리의 다른 글

Istio로 대규모 트래픽 관리하기: 실전 적용 사례와 확장 전략  (2) 2026.01.10
EKS에서 ArgoCD로 GitOps 구축하기: 순환 의존성 해결부터 Single Sync까지  (0) 2026.01.05
실전 Kubernetes 보안: 4C 모델을 프로덕션 클러스터에 적용하며 배운 것들  (0) 2026.01.04
GitHub Actions Docker CI 파이프라인 구조 이해하기: 멀티 아키텍처 빌드부터 캐시 전략  (1) 2026.01.03
Prometheus 디스코드 웹훅  (0) 2025.10.02
'Network' 카테고리의 다른 글
  • EKS에서 ArgoCD로 GitOps 구축하기: 순환 의존성 해결부터 Single Sync까지
  • 실전 Kubernetes 보안: 4C 모델을 프로덕션 클러스터에 적용하며 배운 것들
  • GitHub Actions Docker CI 파이프라인 구조 이해하기: 멀티 아키텍처 빌드부터 캐시 전략
  • Prometheus 디스코드 웹훅
Ry-
Ry-
  • Ry-
    developer_Ryu
    Ry-
  • 전체
    오늘
    어제
    • 분류 전체보기 (97) N
      • AI (14)
      • DB (3)
      • Book (6)
      • Development Environment (2)
        • Mac (2)
      • Frontend (8)
        • Flutter (6)
        • React (1)
        • React-Native (1)
      • Backend (19)
        • Spring (14)
        • Java (1)
        • Node.js (4)
      • Computer Science (27)
        • PS (20)
        • CS (7)
      • Network (12)
      • 이것저것 (3) N
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      티스토리챌린지
      Baekjoon
      최대 힙
      java
      스프링
      종만북
      mysql
      flutter
      spring
      백준
      redis
      database
      mongodb
      node.js
      오블완
      chatgpt api
      몽고디비
      BOGGLE
      aop
      Kakao
      구글 로그인
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.6
    Ry-
    SealSecret vs AWS Secret Manager
    상단으로

    티스토리툴바