SRE 54

Chaos Mesh vs Litmus, 1년 둘 다 굴려보고 내린 결론

작년 이맘때쯤 우리 팀에 Chaos Engineering 도입 미션이 떨어졌다. SRE 본부에서 "장애 대응 훈련을 코드로 돌릴 수 있게 만들자"라는 좀 추상적인 OKR이 내려왔고, 첫 분기는 Chaos Mesh, 두 번째 분기부터는 Litmus로 갈아탔다가, 결국 둘을 섞어서 쓰고 있다. 1년이 지나서 다시 정리해보니 둘 중 뭘 골라야 하느냐는 질문이 잘못된 질문이었다는 결론이 났다. 어느 팀이 어느 부분을 책임지냐에 따라 답이 달라진다.Litmus는 작년 가을 3.0으로 메이저 버전이 올라가면서 UI가 Harness UIcore 기반으로 싹 바뀌었고, Chaos Workflow가 Chaos Experiments로, Chaos Experiments가 Chaos Faults로 용어가 재정의됐다. 올해 1..

IT/SRE 2026.06.02

OTel Collector head sampling vs tail sampling, 우리 팀은 결국 뭘 골랐나

작년 말부터 트레이스 양이 폭증했다. 서비스가 늘어난 것도 있고, 한 요청이 마이크로서비스 7~8개를 거치다 보니 한 트랜잭션에 span이 200개 가까이 붙는 케이스도 생겼다. 그대로 Tempo에 다 밀어 넣었더니 스토리지 비용이 분기마다 1.6배씩 뛰었다. 샘플링을 손봐야 한다는 결론은 너무 자명했는데, 막상 head냐 tail이냐를 고르는 자리에선 팀 안에서도 의견이 갈렸다.결론부터 말하면 우리는 두 개를 섞었다. 그래서 이 글은 어느 한쪽이 정답이라는 얘기가 아니다. 각각의 결을 보고, 어디서 어떤 걸 골랐는지 정리한다.Head sampling — 빠르고 가난한 선택지Head sampling은 트레이스가 시작되는 시점, 그러니까 SDK가 root span을 만들 때 보낼지 말지를 결정한다. Par..

IT/모니터링 2026.05.27

OpenTelemetry Collector가 자꾸 OOM 나서, 결국 memory_limiter와 GOMEMLIMIT을 다시 봤다

지난주 새벽에 페이지가 울렸다. OTel Collector DaemonSet이 또 OOMKilled. 이번 분기에만 세 번째다. 솔직히 처음 두 번은 "그냥 limit을 올리지" 하고 넘어갔는데, 이번엔 메모리를 2Gi → 4Gi로 올렸는데도 또 죽으니까 멘탈이 살짝 나갔다.근본 원인을 보려고 새벽 3시에 노트북을 열었다. 결론부터 말하면 memory_limiter 설정과 GOMEMLIMIT이 둘 다 잘못 잡혀 있었고, batch processor의 순서까지 어긋나 있었다. 우리 팀은 1년 전에 OTel Collector를 처음 도입했을 때 공식 예제 그대로 복붙해 놓고 그동안 트래픽이 4배가 늘었는데도 손을 안 댔던 거다. 부끄럽다.일단 무슨 일이 일어났던 건가우리 클러스터는 노드 80대 정도 되고 각..

IT/모니터링 2026.05.26

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

HPA behavior 필드 잘못 만지다가 P99 튀어버린 이야기

지난주에 HPA behavior 필드를 손댄 적이 있다. 정확히 말하면 손댄 게 아니라, 누군가 친절하게 PR로 올려준 "스케일 다운 빠르게 하자"는 변경을 별생각 없이 머지한 게 시작이었다. 그날 오후부터 P99 레이턴시가 평소 80ms에서 320ms를 찍었고, 새벽 1시쯤 알람이 한 번 더 울리고 나서야 우리 팀은 이게 비용 최적화가 아니라 자해였다는 걸 인정했다.이 글은 그 삽질 회고다. 비슷한 PR 들어오면 한 번만 더 생각해 보시라는 의미에서 적어둔다.사건의 시작서비스는 API 트래픽이 출퇴근 시간대에 몰리는 전형적인 패턴이다. 노드 12대짜리 EKS 클러스터에서 Deployment 3개가 HPA로 묶여 있었고, 평소 replica가 8~30 사이를 왔다 갔다 했다. 비용을 줄이려면 트래픽이 빠..

IT/Kubernets 2026.05.16

Prometheus remote_write 큐가 메모리를 잡아먹은 새벽

지난 주말, 새벽 2시쯤 PagerDuty가 울렸다. central monitoring 클러스터의 Prometheus가 OOMKill로 재시작 루프를 돌고 있다는 알람이었다. 메모리 limit을 32Gi로 잡아둔 인스턴스인데, 이게 몇 분 만에 한계를 찍고 죽고 있었다. 멘탈이 좀 흔들렸다. 평소엔 14~16Gi 정도에서 안정적으로 돌던 녀석이었다.원인을 추적하다 보니 결국 remote_write 큐 동작에 대해 내가 잘못 알고 있었던 부분이 꽤 있었다. 이번 글은 그날 새벽 삽질의 기록이다.배경: 우리 팀의 metric pipeline우리는 Thanos 대신 Mimir로 1년 전쯤 옮겼고, 각 워크로드 클러스터의 Prometheus가 remote_write로 Mimir 게이트웨이에 메트릭을 밀어넣는 구..

IT/모니터링 2026.05.10

SLO multi-window burn rate, 우리 팀이 세 번 갈아엎은 이야기

SLO 알림 한 번 손봤다가 두 달을 끌었다. 이게 뭐 그리 복잡하다고. 처음엔 그렇게 생각했다.우리 팀은 작년 가을부터 핵심 API 다섯 개에 대해 SLO 기반 알림을 운영하고 있다. 가용성 99.9%, 레이턴시 P99 300ms 이하. 알림은 Prometheus + Alertmanager 조합. Google SRE Workbook에 나온 multi-window multi-burn-rate(MWMBR)를 그대로 베껴 쓰고 있었다. 처음엔 만족스러웠다. 그런데 올해 초부터 슬슬 문제가 보이기 시작했다.1차 시도: Workbook 그대로 베끼기처음 셋업할 때는 SRE Workbook 표를 그대로 옮겼다. 4개 티어, 각 티어마다 short/long 두 윈도우.- alert: HighErrorBudgetBu..

IT/SRE 2026.05.05

PDB 하나 때문에 노드 드레인이 4시간 멈췄던 이야기

지난주 화요일 새벽이었다. EKS 클러스터 1.32 → 1.33 업그레이드를 돌리는 중이었는데, 노드 드레인이 4시간째 안 끝나고 있다는 슬랙 알림을 받았다. 새벽 3시였고, 솔직히 처음엔 드레인이 원래 좀 오래 걸리니까 그러려니 했다. 4시간이라는 숫자를 본 순간 멘탈이 한 번 흔들렸다.평소 같으면 워커 노드 한 대 드레인하는 데 길어야 10분 정도였다. 그런데 이번엔 한 노드에 박혀서 안 빠지는 파드가 있었고, 그 파드 하나가 전체 업그레이드 파이프라인을 막고 있었다. 결국 원인은 PDB(PodDisruptionBudget) 하나였다. 짧게 말하면 그렇고, 길게 말하면 우리 팀의 PDB 관리 방식 전체가 문제였다.처음 발견한 증상노드를 cordon하고 drain을 돌렸는데 이런 메시지가 계속 떴다.e..

IT/Kubernets 2026.05.05

kubectl debug --target, 이거 모르는 분 꽤 많더라

오늘 알게 된 것도 아니고, 알고는 있는데 막상 새벽에 장애 터지면 까먹는 옵션 하나를 정리해두려고 한다. kubectl debug --target. 같이 일하는 주니어한테 알려주니까 "어 이게 되네요?" 하길래.흔한 상황운영 중인 Pod에서 네트워크가 이상하다. DNS는 되는데 특정 외부 IP로만 connect timeout. 컨테이너는 distroless라서 kubectl exec로 들어가도 쉘이 없다. 사이드카로 디버깅 컨테이너 박아서 재배포? 새벽 두 시에 그건 좀 그렇다.이럴 때 쓰는 게 ephemeral container, 그리고 kubectl debug다. K8s 1.25에서 GA된 후로 죽 안정적이다. 근데 의외로 --target 옵션을 안 쓰고 그냥 띄워서 "어 왜 안 보이지" 하는 경우..

IT/Kubernets 2026.05.02

NodeLocal DNSCache 없이 버티다 conntrack에 발목 잡힌 새벽

지난주 화요일 새벽 2시 17분에 페이저가 울렸다. 결제 API의 P99 레이턴시가 1.2초를 찍고 있었다. 보통 80ms대로 노는 애가 갑자기 15배가 됐는데, 이게 가끔 한 번씩 튀고 끝나는 게 아니라 5분 동안 꾸준히 그 모양이었다. 멘탈이 살짝 나갔다. 결제는 트래픽 자체는 크지 않은데 도미노가 한번 시작되면 SLO 까먹는 속도가 가차 없는 구간이라.결론부터 적자면, 그날 밤 범인은 애플리케이션도, DB도, 네트워크 장비도 아니었다. CoreDNS와 conntrack이었다. 며칠 뒤 NodeLocal DNSCache를 깐 후로는 같은 증상이 안 났는데, 이 일을 글로 정리해두고 싶었다. 비슷한 패턴은 의외로 흔한 것 같아서.처음에 의심한 것들알람 받자마자 떠오른 후보는 셋이었다. 결제 DB의 락,..

IT/기타 2026.04.26