장애회고 17

autovacuum이 돌고 있는 줄 알았다

autovacuum이 돌고 있는 줄 알았다지난주에 PostgreSQL 디스크가 갑자기 부풀어오르는 사건이 있었다. 정확히는 이미 며칠 전부터 부풀고 있었는데, 우리가 늦게 알아챈 거다.처음에는 단순히 "데이터가 많아져서 그렇겠지" 생각했다. 그런데 dead tuple 비율을 찍어보니 40%를 넘기고 있었다. 어떤 테이블은 60%. 라이브 row보다 죽은 row가 더 많은 상태였다. autovacuum 로그를 뒤져보니 마지막 vacuum이 4일 전에 멈춰 있었다. 그리고 그 사이에 누가 무엇을 했는지 추적이 시작됐다.pg_stat_activity가 말해준 것pg_stat_activity 뷰를 열어보니 한 세션이 4일째 살아 있었다. state는 idle in transaction. xact_start는 월..

IT/DB 운영 2026.06.22

KEDA로 SQS 워커 스케일링 했다가 메시지 절반이 사라진 이야기

우리가 깐 구성지난주 화요일 새벽에 알림이 울렸다. 정확히는 알림이 안 울려서 문제였다. 이미지 변환 워커가 SQS 큐의 메시지를 잘 먹고 있는 줄 알았는데, 다음 날 아침에 보니 "어제 업로드한 썸네일이 안 나와요"라는 CS 티켓이 17건 쌓여 있었다. SQS DLQ에 들어간 것도 아니고 그냥 큐 어디에도 없었다. 처리는 안 됐는데 사라졌다는 게 가장 큰 문제였다.원인은 KEDA였다. 정확히는 KEDA가 잘못한 건 아닌데, scaleToZero를 너무 공격적으로 설정한 우리 팀이 잘못했다. 이 글은 그 이야기다.배경부터 정리하면, 우리 팀은 이미지 변환 파이프라인을 KEDA + SQS로 운영하고 있다. 사용자가 이미지를 업로드하면 S3 트리거가 SQS로 메시지를 보내고, 워커 파드가 그걸 받아서 리사이..

IT/Kubernets 2026.06.07

PgBouncer transaction mode에 prepared statement 켰다가 새벽에 깬 이야기

지난주 일요일 새벽 2시쯤 알림이 왔다. 결제 API 쪽에서 prepared statement "S_3" does not exist 에러가 분당 수백 건씩 찍히고 있었다. 그 전날 PgBouncer를 1.25.1로 올린 게 화근이었다. 안 그래도 PG16.11에 PgBouncer 1.25.1 조합에서 prepared statement 관련 버그 리포트가 올라온 게 있었는데, 우리도 그 케이스에 정확히 걸려든 거였다.이번 글은 그날 새벽 내가 뭘 보고 뭘 했고, 최종적으로 어떻게 마무리됐는지에 대한 기록이다. 깔끔한 해결책 같은 건 아직 없다. 워크어라운드로 일단 막아둔 상태.배경: 왜 transaction mode + prepared statement를 켰나작년에 우리 팀은 PgBouncer를 1.21로..

IT/DB 운영 2026.05.25

matchLabelKeys 안 썼다가 롤링 업데이트 중 한 노드에 트래픽 70% 쏠린 사건

지난주 화요일 새벽 2시. 슬랙 알림 한 통에 잠이 깼다. P99 레이턴시가 800ms를 찍었고, 한 가용영역의 한 노드만 CPU가 95%를 치고 있었다. 다른 두 노드는 30%. 분명히 우리는 topologySpreadConstraints 를 걸어뒀는데, 왜 한 쪽으로만 쏠렸을까.결론부터 말하면, matchLabelKeys 를 안 써서 그렇다. 그게 무슨 소리인지 정리해보겠다.우리 환경EKS 1.32, 노드 12대(3 AZ × 4대), Deployment replicas 18. 매니페스트의 spread 설정은 이렇게 생겼었다.topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisf..

IT/Kubernets 2026.05.23

Karpenter consolidation, 새벽에 한꺼번에 다 날아간 이야기

새벽 3시 47분. 핸드폰이 미친 듯이 울렸다.PagerDuty가 동시에 네 건. P99 레이턴시, 5xx 비율, 큐 적체, 그리고 결제 워커 alive 체크 실패까지 줄줄이 빨간색. 잠이 깰 새도 없었다. 노트북을 열고 Grafana부터 켰는데, 노드 수가 떡 하니 23대에서 6대로 떨어져 있었다. 누가 그랬을까. 범인은 나였다. 정확히는, 일주일 전 내가 만진 Karpenter 설정이.무슨 짓을 했길래배경부터. 우리 팀은 EKS에서 Karpenter로 노드를 굴린다. NodePool 두 개 — 일반 워크로드용 default, 그리고 결제/주문 같은 stability-sensitive 워크로드용 payments. 한 달 전쯤 FinOps 압박이 들어왔다. "비용 너무 많이 나온다, 야간에 트래픽 적은 ..

IT/Kubernets 2026.05.22

ArgoCD app-of-apps에서 sync-wave 잘못 짜서 새벽에 깬 이야기

지난주 화요일 새벽 3시쯤. 휴대폰이 울렸다. 온콜 알림이었다. prod의 메인 API가 503을 뱉고 있다는. 솔직히 그날따라 몸이 너무 무거워서 한 5분쯤은 침대에서 멍하니 알림을 봤다. 그 5분이 정말 길었다.원인을 미리 말하자면, 전날 머지된 PR에서 ArgoCD argocd.argoproj.io/sync-wave 값을 한 줄 바꾼 게 문제였다. app-of-apps 패턴을 쓰는 우리 클러스터에서, 그 한 줄이 컨트롤 플레인 컴포넌트보다 워크로드를 먼저 띄우게 만들었다. 결과적으로 cert-manager가 뜨기 전에 ingress webhook이 호출돼서 발급이 꼬였고, 그게 ALB target health check를 흔들었고, 503이 떴다.새벽 3시반에 침대에서 일어나면서 든 생각: "syn..

IT/CI CD 2026.05.17

Sealed Secrets 마스터 키 백업 안 해놓고 클러스터 옮겼다가 시크릿 47개 복구한 이야기

지난주 금요일 오후 4시. 평화롭던 사무실에 메신저 알림이 떴다. "스테이징 클러스터 새로 만든 거 거의 다 됐는데, ArgoCD가 SealedSecret 못 푼다고 에러 토하는 중인데 좀 봐주실 수 있어요?" 그 메시지를 본 순간 명치가 싸늘해졌다.왜냐면 그 이전 클러스터의 sealed-secrets controller에서 발급된 master key를 백업해뒀는지 기억이 안 났거든. 결론부터 말하면 안 해놨다. 그래서 그날 퇴근은 새벽 1시였다.무슨 일이 벌어진 건가상황을 좀 정리해보자. 우리 팀은 EKS 1.28 → 1.31 업그레이드를 in-place로 안 하고 새 클러스터를 만들어서 옮기는 방식으로 진행하고 있었다. 스테이징부터. 매니페스트는 ArgoCD GitOps로 관리되니까 그냥 ArgoCD..

IT/DevSecOps 2026.05.03