이 글에서 다루는 것

AWS IAM 키 회전과 SealedSecret 재암호화를 스크립트로 표준화하고, GitOps 자동 반영까지 이어지는 반자동 SecretOps 체계를 구축하는 과정을 다룹니다.

선수지식


이 단계에서 해결하려는 문제

MLOps에서는 모델보다 먼저 ‘비밀’이 무너진다. AWS 키처럼 주기적으로 교체해야 하는 값은 자동화가 필요하지만, JWT·Slack Webhook처럼 교체 시 영향이 큰 값은 운영자가 직접 결정해야 한다. 자동화할 것과 사람이 확인해야 할 것을 구분한 SecretOps 체계를 확립한다.


🎯 핵심 요약

  • AWS IAM Access Key 주기 회전 → Airflow / FastAPI / MLflow에 GitOps 자동 반영
  • **SealedSecrets 재암호화(Re-Seal)**로 컨트롤러 키 교체에도 무중단 운영
  • “보안 리스크는 자동화, 변경 영향 큰 건 수동"의 균형 운영
  • Rotation/Re-Seal 스크립트 실행 후 → Git Commit/Push → Argo CD Sync로 이어지는 반자동 보안 GitOps 루틴

1️⃣ 전체 구조 요약

mermaid-09.png


2️⃣ AWS Credentials Rotation (반자동)

실행 예시

# dev 환경
bash ops/rotate/rotate-aws-credentials.sh dev

# prod 환경
bash ops/rotate/rotate-aws-credentials.sh prod

동작 흐름

  1. 현재 IAM 사용자/기존 키 확인
  2. 새 AccessKey/Secret 생성 → /root/backup에 0600로 백업
  3. envs/<env>/sealed-secrets/{airflow,fastapi,mlflow}/sealed-aws-credentials-<env>-secret.yaml 갱신
  4. git add/commit/push → Argo CD Auto Sync
  5. 정상성 검증 후 이전 키 Inactive → Delete

3️⃣ SealedSecret Re-Seal (컨트롤러 키 변경 대응)

평문은 건드리지 않고, 기존 암호문만 클러스터의 최신 공개키로 재암호화합니다.

실행 예시

# 변경만 미리 확인 (파일 diff만 생성)
DRY_RUN=1 bash ops/seal/re-seal.sh dev

# 실제 반영
bash ops/seal/re-seal.sh dev

동작 흐름

  1. 현재 컨트롤러 공개키 fingerprint 확인
  2. kubeseal --re-encrypt로 모든 SealedSecret 재암호화
  3. 레포 파일 교체 git commit/push & Argo CD Auto Sync로 무중단 적용

안전 장치

  • 컨트롤러 이름/네임스페이스 확인: -controller-name sealed-secrets --controller-namespace kube-system
  • 대상 디렉터리 화이트리스트: envs/<env>/sealed-secrets/**
  • 작업 전/후 git clean/safe-state 확인

4️⃣ 컨트롤러 키 자체 교체 (필요 시)

rotate-controller-key.sh로 sealed-secrets 컨트롤러 키를 재발급/교체하고, 즉시 Re-Seal까지 연동합니다.

# 교체 → 전체 재암호화 → 커밋/푸시까지 원샷 (환경별)
bash ops/seal/rotate-controller-key.sh dev

권장 순서

  1. 백업: 기존 컨트롤러 시크릿 dump
  2. 교체: sealed-secrets 컨트롤러 키 재발급
  3. 검증: 새 공개키 fingerprint 출력
  4. Re-Seal 호출: ops/seal/re-seal.sh <env> 자동 호출
  5. GitOps: 커밋/푸시 → Argo CD Auto Sync
  6. 관찰: 대상 앱 OutOfSync/에러 없음 확인

컨트롤러 키 교체는 드물지만 큰 변경입니다. 가급적 근무 시간 + Slack 알림 활성화 상태에서 수행하세요.


5️⃣ 기타 시크릿 운영 방침(수동 루틴 유지)

항목회전 방식이유
Slack Webhook수동잘못 교체 시 관제 단절 위험
FastAPI JWT Secret수동토큰 무효화 영향 큼
Git SSH Key수동git-sync 인증 실패 리스크
DB Password수동변경 주기 낮고 영향 범위 큼

원칙: 자주 바뀌고 위험한 건 자동화, 가끔 바뀌고 영향 큰 건 수동 검증.


6️⃣ 향후 확장 가능

목표방법
K8s-native 외부 비밀 연동External Secrets Operator(ESO)
관리형 스토어 사용AWS Secrets Manager + IAM Role
완전 무중단동일 Secret 이름 유지 + 공급자만 교체

지금의 GitOps/Argo CD는 그대로 두고 비밀 공급자만 교체하는 식으로 자연스럽게 승급 가능.


7️⃣ 체크리스트

  • rotate-aws-credentials.sh 실행 후 Secret 리소스 버전 증가(describe/events)
  • 서비스 S3/레지스트리 접근 정상(403 없음)
  • 구 Access Key Inactive → Delete 완료
  • 컨트롤러 교체/업그레이드 후 반드시 re-seal.sh 수행
  • Argo CD Auto Sync 정상 + Drift 없음
  • (선택) Helm에 checksum/secret 반영해 자동 롤아웃 확인

🧩 팁

증상원인해결
“Max 2 keys” 에러IAM 키 2개 초과오래된 키 삭제 후 재시도
OutOfSync 반복SealedSecret만 수정, 롤아웃 미발생체크섬 어노테이션 또는 수동 rollout restart
403 접근 오류Pod에 구 키 남아있음롤아웃 트리거/재배포
복호화 실패컨트롤러 키 변경 후 Re-Seal 미수행bash ops/seal/re-seal.sh <env> 실행

8️⃣ GitOps 연동 관점 보강

  • 디렉터리 표준화: envs/<env>/sealed-secrets/<app>/sealed-*.yaml
  • Sync Wave/Order: Secret/Config는 sync-wave: "-1", 워크로드는 sync-wave: "0"~"1"

설계 판단 (Why This Way?)

AWS 키처럼 유출 시 즉각 비용이 발생하는 시크릿만 자동 회전하고, 영향 범위가 큰 JWT/Webhook은 수동 유지하여 운영 안전성을 확보했습니다. SealedSecret re-encrypt로 평문 노출 없이 키 갱신이 가능하고, 시크릿 교체는 운영자가 실행 시점을 결정하는 반자동 방식을 택했습니다.


다음에 읽을 글

Airflow 6단계: KubernetesExecutor 선택 이유 — CeleryExecutor 대비 장단점 분석