IT/DevSecOps

External Secrets Operator refreshInterval 15초로 뒀다가 청구서 두 번 놀란 이야기

gfrog 2026. 8. 28. 12:13

지난주에 인프라 비용 리뷰가 있었다. 평소 같으면 EC2랑 NAT Gateway 위주로 훑고 지나갔을 자리인데, 이번엔 AWS Secrets Manager 라인이 유난히 눈에 띄었다. 전월 대비 4배. 절대 금액이 큰 건 아닌데(정확히는 $180 정도), 갑자기 4배가 뛴 게 이상해서 파보다가 며칠 날렸다.

결론부터 말하면 범인은 External Secrets Operator였다. 정확히는 ExternalSecret 리소스에 박아둔 refreshInterval: 15s.

왜 15초로 뒀었나

원래 이 값은 팀에서 붙인 게 아니고, 초창기에 ESO를 도입한 사람이 "빠르게 반영되면 좋겠지" 하고 넣어둔 걸 아무도 안 건드린 채 굴러왔다. 몇 년 지나면서 ExternalSecret 개수도 슬금슬금 늘어서 지금 확인해보니 클러스터 세 개 합쳐서 대충 380개.

380개가 15초마다 각자 Secrets Manager를 부른다. 계산해보면 하루 220만 콜. AWS Secrets Manager는 만 콜당 $0.05인데, 그럼 한 달에 대충 $330 정도 나와야 하는데 실제로는 그보단 낮게 찍혔다. 캐시가 붙어서 GetSecretValue 실제 호출이 좀 덜 되는 것 같은데, 정확히 얼마나 캐시되는지는 아직 확인 못 했다.

처음엔 다른 데를 의심했다

솔직히 처음엔 ESO가 원인일 거라고는 상상도 못 했다. 새로 붙인 서비스가 GetSecretValue를 폭주시키는 건가 싶어서 CloudTrail을 뒤졌다. 근데 이상하게 특정 서비스가 튀는 게 아니라 전 사용자에서 골고루 콜이 나가고 있었다.

한참 헤매다가 userAgent가 external-secrets/v0.19.x로 다 찍혀 있는 걸 봤다. 그때 아 이거구나 싶었다. Prometheus에 externalsecrets_sync_calls_total 같은 메트릭이 있어서 그거 확인하면 됐을 텐데, ESO 메트릭을 스크레이프 안 하고 있었다. 이것도 이번에 알게 된 부끄러운 사실.

얼마로 바꿔야 하나

ESO 공식 FAQ랑 최근 블로그들 뒤져보니 "1시간이 대부분의 경우 충분하다"가 정설이었다. AWS Secrets Manager는 자동 rotation 붙여놨을 때 최소 rotation 주기가 시간 단위라서, 초 단위로 refresh해봤자 의미가 없다. 그리고 이런 공식이 자주 인용된다:

refreshInterval < rotation_window / 4

Rotation을 24시간에 한 번 돌리면 refresh는 6시간, rotation을 7일에 한 번 돌리면 refresh는 하루 반. 이 기준으로 정리하면 우리 클러스터의 대부분 secret은 1시간~6시간 사이가 맞다.

문제는 이걸 380개 전부에 하나하나 손댈 순 없고, 등급을 나눠서 처리해야 한다는 거였다.

실제로 한 작업

일단 급한 대로 클러스터 전체에 defaultRefreshInterval을 1h로 걸었다. ESO 최신 버전(0.19대 이상)에서는 ClusterExternalSecret 레벨이나 controller flag로 기본값을 밀어넣을 수 있어서 다행이었다. 예전 버전이었으면 380개 다 kubectl patch로 돌렸어야 했을 텐데.

그다음에 secret을 세 등급으로 나눴다.

  • 자주 rotation 되는 DB 크레덴셜: 30분 (rotation 주기가 2시간이라)
  • 일반 API 키: 6시간
  • 상수에 가까운 값들(외부 서비스의 안 변하는 토큰): 24시간

이렇게 나눈 뒤 kustomize overlay로 등급별 refreshInterval을 주입하도록 바꿨다. 라벨링은 secret 이름 패턴이랑 네임스페이스 컨벤션으로 자동화했다. 아직 손이 안 간 몇 십 개는 시간 날 때 처리할 예정.

작업하고 이틀 뒤 청구서 예상액이 다시 원래 수준으로 내려왔다. 하드한 검증은 한 달 뒤 실제 청구서 봐야 하지만, 대충 맞을 것 같다.

마지막에 남은 찜찜함

두 가지 남았다.

첫째, 15초 refresh 시절에도 특별히 문제가 없었다는 것. 즉 팀이 이걸 몇 년간 몰랐다는 게 문제다. Secrets Manager 콜 수 자체를 모니터링에 포함시켜야 했다. 지금은 CloudWatch에서 API call 수 알람 걸어놨다.

둘째, 이번에 우리 팀은 ESO를 썼지만 다른 팀들은 SecretsManagerCSIDriver를 쓰거나, 직접 애플리케이션에서 SDK 호출하는 곳도 있다. 그쪽도 비슷한 함정이 있을 텐데 아직 다 확인 못 했다. 아마 다음 리뷰 때는 그쪽에서 뭐가 하나 터질 것 같다.

혹시 refreshInterval 이슈로 비슷한 경험 있으신 분 있으면 어떻게 관리하시는지 궁금하다. 특히 500개 넘어가는 규모에서 어떻게 오퍼레이팅 하는지.

#DevSecOps #ExternalSecrets #kubernetes #AWS #SecretsManager #실무팁