IT 363

새벽 두 시에 깨운 Karpenter, disruption budget 시간 윈도우로 막은 이야기

지난주 화요일 새벽 두 시, 휴대폰이 울렸다. P0 알람. 결제 API의 P99 레이턴시가 1.2초를 넘기고 있었고, 50x 비율이 3분 동안 8%까지 올라갔다 떨어졌다. 잠이 확 깼다.대시보드를 열어보니 노드가 한꺼번에 세 대가 빠지고 있었다. 우리 클러스터는 노드 24대 규모인데, Karpenter consolidation이 동시에 세 대를 cordoning + draining 중이었다. Pod Disruption Budget도 걸어뒀고, terminationGracePeriodSeconds도 충분히 잡아뒀는데도 결제 서비스 두 개 인스턴스가 같은 노드에 몰려 있던 게 문제였다. 새벽 2시는 트래픽이 낮긴 해도 결제는 0이 아니다. 일본/동남아 유저들이 깨어 있다.왜 새벽에 한꺼번에 빠졌나Karpen..

IT/Kubernets 2026.06.29

PgBouncer transaction vs session 모드, 뭘 쓸까

Postgres 앞에 PgBouncer를 두는 건 거의 관습처럼 되어 있다. 그런데 막상 처음 도입할 때 보면 pool_mode 선택지가 세 개 있고, 그중 실제로 쓰는 건 거의 둘 — transaction과 session이다. 둘 다 써본 입장에서 정리해본다. 어느 쪽이 정답이라기보다, 트레이드오프가 꽤 명확하다.참고로 PgBouncer 1.21 이후 transaction 모드에서도 prepared statements가 지원되기 시작했다. 이게 의외로 선택 기준을 흔든다. 예전에는 ORM/드라이버 호환성 때문에 어쩔 수 없이 session 모드를 골랐던 케이스들이 다시 transaction으로 돌아갈 만한 여지가 생겼다.session 모드 — 가장 안전하지만 풀링 효과가 약하다pool_mode = se..

IT/DB 운영 2026.06.29

ingress-nginx EOL 통보를 받고 Gateway API로 옮긴 두 달의 기록

지난 4월쯤이었다. 슬랙에 누가 링크 하나를 던졌다. ingress-nginx 메인테이너들이 더 이상 best-effort 유지보수도 못한다고 공지를 올렸다는 거였다. 처음에는 "에이, 그래도 굴러는 가겠지" 했다. 우리 클러스터 8개에 다 깔려 있고, ingress 리소스만 200개가 넘는데. 근데 그 주에 보안팀에서 CVE 패치 일정을 묻는 메일이 왔고, 그제서야 정신이 들었다. 사실상 EOL 된 컨트롤러를 들고 가는 건 시간 문제일 뿐이라는 걸.그래서 Gateway API로 가기로 했다. 5월 초부터 6월 말까지, 약 두 달 동안 삽질한 이야기를 적어둔다. 누군가는 비슷한 상황일 테니까.처음에 안일하게 생각했던 것Gateway API가 v1.5까지 나왔고 standard로 거의 다 올라왔다는 글을 ..

IT/Kubernets 2026.06.28

OpenTofu state 암호화, fallback 빼먹으면 일 난다

OpenTofu 1.7에서 state 암호화 기본 기능이 들어온 지도 꽤 됐다. 근데 막상 켜본 분들 중에 method 블록만 설정하고 fallback은 그냥 비워두는 경우가 많더라. 우리 팀도 처음에 그랬다. 결론부터 말하면, fallback 빼면 마이그레이션 순간에 무조건 한 번은 깨진다.무슨 상황에서 깨지나평문 state 파일이 있는 워크스페이스에 처음 암호화를 켤 때가 문제다. OpenTofu는 terraform.encryption 블록에서 지정한 method로 state를 읽으려고 시도하는데, 기존 파일은 평문이라 못 푼다. Error: Failed to decrypt state 한 줄 던지고 끝.키 로테이션도 마찬가지다. PBKDF2 패스프레이즈를 바꿨다? 새 키로 옛날 state는 못 연다...

IT/IaC 2026.06.28

Dockerfile COPY --link, 다들 쓴다는데 진짜 좋을까

COPY --link 얘기는 한 2년 전부터 컨퍼런스마다 단골 메뉴였다. "그냥 다 붙여라, 캐시 효율이 미친다"는 식의 글도 많고. 우리 팀도 어느 순간부터 거의 자동 반사처럼 모든 COPY 앞에 --link를 박아 넣고 있었다. 근데 최근에 좀 다른 얘기가 돌더라.올해 2월에 Depot 블로그에서 "왜 COPY --link 쓰지 말아야 하는지"라는 글이 올라와서 한 번 더 시끌시끌했다. 한 줄로 요약하면 "BuildKit이 --link 레이어를 다루는 방식 때문에 오히려 빌드가 느려지는 케이스가 꽤 있다"는 거. 우리 팀에서도 비슷한 케이스를 한 번 만난 적이 있어서 정리해둔다.--link가 손해 보는 케이스가장 흔한 패턴이 이거다.FROM node:20-alpine AS buildWORKDIR /a..

IT/컨테이너 2026.06.28

SLO는 깨졌는데 burn rate 알림은 안 울렸다

지난 화요일 오전, 한 사용자한테 문의가 들어왔다. "결제 콜백이 가끔 실패한다"고. PM이 슬랙에 던진 메시지였는데, 솔직히 그때까지 우리는 아무 알림도 못 받은 상태였다. SLO 대시보드를 켰다. 99.5% 목표인 가용성 SLI가 99.1%까지 떨어져 있었다. error budget이 이미 절반 가까이 타들어간 상태였다.근데 burn rate 알림은 조용했다. 한 번도 안 울렸다.우리가 깔아둔 알림 구성Google SRE 워크북에 나오는 multi-window multi-burn-rate 패턴 그대로였다. 페이지(긴급) 알림은 1시간 윈도우 + 5분 윈도우 둘 다 14.4배 burn rate를 넘기면 발사. 티켓(완만) 알림은 6시간 + 30분 윈도우에 6배 burn rate. 표준 구성이다.- al..

IT/SRE 2026.06.27

Velero restic에서 Kopia로 옮기는 법

쓰던 Velero 백업 파이프라인이 restic 기반이면 슬슬 갈아탈 때가 됐다. v1.15에서 restic이 deprecated로 마킹된 게 작년 말이고, v1.16에서는 새로운 file system backup의 기본 업로더가 Kopia다. 거기다 PV 백업 흐름 자체도 CSI snapshot data movement 쪽으로 무게추가 옮겨가는 중이라, 운영 환경을 그대로 두면 1~2년 안에 업그레이드 경로에서 발이 묶일 수 있다.이 글은 EKS 클러스터에서 돌아가는 restic 기반 Velero를 Kopia + CSI data mover 조합으로 옮기는 실전 절차다. 우리 팀이 노드 50대짜리 프로덕션 클러스터에서 한 달에 걸쳐 진행한 작업을 정리한 거라, 가능한 단계마다 함정도 같이 적었다.왜 지금..

IT/Kubernets 2026.06.27

GitHub Actions secrets: inherit, 한 줄이 일으키는 의외의 일들

재사용 워크플로우(reusable workflow) 쓰다 보면 거의 반사적으로 secrets: inherit 한 줄 박아두게 된다. 편하니까. 근데 이게 동작 방식을 정확히 모르고 쓰면 디버깅하다가 한 시간씩 날려먹는 포인트가 몇 개 있다. 오늘은 그 중 자주 걸리는 것들만 짧게 정리.inherit는 "직접 호출한 워크플로우"까지만 간다체인 호출에서 제일 많이 헷갈리는 부분이다. A → B → C 구조라고 하자. A에서 B를 부르면서 secrets: inherit을 줬다. B에서 C를 부르는데 거기에 secrets: inherit을 또 안 적으면, C는 시크릿을 못 본다. inherit는 한 단계만 전파된다.# A.ymljobs: call-b: uses: ./.github/workflows/B.y..

IT/CI CD 2026.06.27

kubectl events, 아직도 get events 쓰세요?

오늘 후배가 kubectl get events --sort-by='.metadata.creationTimestamp' -n prod 를 또 한참 두드리고 있길래 옆에서 한마디 했다. "그거 그냥 kubectl events -n prod 하면 돼요." 진짜 표정이 굳더라. 의외로 모르는 분 꽤 많아서 짧게 정리한다.kubectl events, 그게 뭔데kubectl events 는 events.k8s.io/v1 API 가 v1.19에서 들어오면서 별도로 추가된 명령어다. 처음에는 alpha였는데 이제는 우리가 운영하는 1.32 정도 클러스터에서는 그냥 당연히 쓸 수 있다. kubectl get events 가 events.k8s.io/v1 와 core/v1 둘 다 보여주는 만능 명령이라면, kubectl ..

IT/Kubernets 2026.06.26

ndots:5 한 줄이 클러스터를 무릎 꿇린 새벽

지난주 화요일 새벽 2시 47분, 슬랙 알림이 무더기로 떴다. P99 레이턴시 그래프가 평소 80ms 근처에서 600ms 위로 튕겨 올라가더니, API 5xx 비율이 0.1%에서 4%까지 치솟았다. 결제 트래픽이 한창 몰리는 시간대였다.처음엔 또 어디서 메모리가 새는 건가 싶었다. 근데 컨테이너 메모리는 멀쩡했고, CPU도 평소 수준이었다. 그러다 어떤 마이크로서비스 로그를 까보니 거의 모든 요청에 dial tcp: lookup api.stripe.com on 10.96.0.10:53: i/o timeout 같은 줄이 박혀 있었다. DNS였다.첫 의심: CoreDNS 파드가 죽었나당연한 수순으로 kubectl -n kube-system get pods -l k8s-app=kube-dns 부터 쳐봤다. 다..

IT/Kubernets 2026.06.26