과금 지표 vs 파드 런타임 상태

Kubernetes3분조회

브라우저로 접속해 쓰는 원격 개발 환경 서비스를 운영합니다. EKS 위에 올려서 환경 하나가 파드 하나고, 작업하던 파일이 남아야 하니 EBS 볼륨을 PVC 로 붙여 줍니다. 안 쓸 때는 파드를 내렸다가 다시 들어오면 같은 볼륨을 붙여 띄웁니다.

과금은 컨테이너를 띄워 둔 시간으로 매기는데, 쿠버네티스에는 그 시간을 집계하는 기능이 없습니다. 그래서 컨테이너를 띄우고 내릴 때마다 애플리케이션이 자체 DB 에 행을 남기고, 그 행으로 사용량을 계산합니다.

컨테이너가 안 뜬다는 제보를 받고 DB 를 확인했습니다. 해당 사용자 행은 state = active. 그런데 파드는 안 떠 있었습니다.

그 지표의 정체 — 파드 상태가 아님

이 값이 어긋난 원인은 state 가 과금 집계용 컬럼이기 때문입니다. 사용자가 환경 생성을 요청한 시점에 active 로 기록되면서 거기서 과금 시작 시각이 잡히는 값이라, 파드가 실제로 Ready 까지 갔는지는 반영되지 않습니다. 즉 파드가 ContainerCreating 이나 Pending 에서 멈춰 있어도 요청 자체는 접수된 상태이므로 사용량 DB 에는 active 로 남아 있게 됩니다.

두 신호는 이렇게 다릅니다.

신호 실제로 뜻하는 것
사용량 DB state=active 실행을 요청했다
파드 Running + Ready 컨테이너가 떠 있다

앞의 값으로 뒤의 상태를 판단할 수 없습니다.

실제 상태 — 볼륨 attach 실패로 멈춘 파드

파드 이벤트를 보니 볼륨 Attach 가 실패하고 재시도를 반복하는 중이었습니다.

Warning  FailedAttachVolume  ...  AttachVolume.Attach failed for volume "pvc-..."

여기까지는 “볼륨이 안 붙는다” 뿐이고 왜 안 붙는지가 없어서, 같은 시각의 CloudTrail AttachVolume 이벤트에서 errorCode 를 찾았습니다.

errorCode: Client.InvalidVolume.NotFound

붙이려던 EBS 볼륨이 이미 없어진 상태였고, 볼륨이 사라진 이상 Attach 는 몇 번을 재시도해도 실패하니 파드는 ContainerCreating 에서 못 벗어납니다. 그동안에도 사용량 DB 는 active 라 과금은 계속 붙고 있었습니다.

신호별 상태 확인처 구분

“돌고 있나?” 를 어디에 물어보느냐는 신호마다 다릅니다.

  • 비즈니스/과금 지표 — 요청·계약·정산을 재는 값입니다. 사용자가 뭘 요청했는지는 알지만, 그게 인프라에서 실제로 떠 있는지는 모릅니다.
  • 실제 런타임 상태 — K8s 이벤트, 파드 phase 와 컨디션, 그리고 원인까지 가려면 클라우드 API 의 에러코드(위의 AttachVolume errorCode 처럼)입니다.

과금 로그로 파드 헬스를 판단하는 순간, 멈춘 파드가 “정상” 으로 보입니다. 반대로 실제 상태만 보고 과금을 판단하면 요청은 됐는데 정산이 빠질 수 있습니다. 둘을 섞으면 양쪽 다 틀립니다.

active는 실행 상태가 아니라 요청 접수

지표 이름만 보고 그 값이 무엇을 재는지 넘겨짚으면 안 됩니다. active, running 같은 이름이 붙어 있어도 런타임 상태라는 보장이 없고, 이 경우엔 요청을 접수한 시각을 남기는 값이었습니다.

그래서 같은 제보를 다시 받으면 순서를 이렇게 잡습니다. 과금·사용량 지표는 “사용자가 무엇을 요청했나” 까지만 답해 주니 거기서 멈추고, 실제로 떠 있는지는 파드 상태와 이벤트를 보고, 왜 못 떴는지는 클라우드 API 의 에러코드까지 내려가서 확인합니다.

돌아보면 이번 건에서 잃은 시간은 전부 “지표가 정상이라고 했으니 딴 데 문제겠지” 라고 믿은 데서 나왔습니다. 지표는 거짓말을 한 게 아니라 자기가 재는 걸 정확히 답했을 뿐이고, 제가 그 값을 다른 질문의 답으로 읽은 것뿐입니다.

그래서 요즘은 대시보드나 DB 에 새 지표가 하나 생기면, 이름 말고 그 값이 언제 어떤 코드에서 쓰이는지를 먼저 봅니다. 장애가 났을 때 그 한 줄이 확인 순서를 정해 줍니다.

  1. 불러오는 중