Incident Library
적용된 필터 구성 요소컨테이너 CPU 한도모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례5건

5건 중 1~5번째

  1. 증상

    운영 중인 이커머스 플랫폼의 응답이 갑자기 느려졌다. 상품 조회 페이지가 특히 심했고, 사용자들에게서 "페이지가 안 열린다"는 문의가 들어왔다.

    촉발

    외부 커뮤니티인 뽐뿌에 플랫폼 링크가 담긴 게시글이 올라와 짧은 시간에 많은 사용자가 몰렸고, 이 사용자들이 상품 조회 API 를 집중적으로 호출했다.

    원인
    구성 요소
    기여 요인
    감지

    사용자에게서 "페이지가 안 열린다"는 문의가 들어와 장애를 알았다. 대시보드의 파드 상태는 정상이었고, 네임스페이스 CPU 사용량과 CPU 메트릭을 직접 보고서야 CPU 스로틀링을 확인했다.

    조치
    • HPA 의 minReplicas 를 5에서 10으로 늘렸다.
    • Deployment 의 CPU limit 을 1코어에서 2코어로 올렸다.
    후속 조치
    • CPU limit 을 무작정 높이면 노드 자원을 과하게 차지할 수 있으므로, 모니터링하면서 적정 수준으로 계속 조정한다.
    교훈

    글쓴이는 예측 가능한 이벤트성 트래픽까지는 받아낼 수 있게 설정해 뒀다고 생각했다. 그러나 외부 커뮤니티 게시글 하나로 트래픽이 폭증하자 그동안 문제없던 리소스 설정이 순식간에 병목이 됐다. CPU 스로틀링은 파드 상태와 로그에 드러나지 않아서 파드 목록이 아니라 CPU 메트릭을 봐야 찾을 수 있었다. 글쓴이는 대규모 트래픽에 미리 대비한 경험이 부족했다고 돌아보고, 트래픽 패턴이 바뀔 때의 대비와 리소스 설정을 더 고민하기로 했다.

  2. 증상

    자체 호스팅한 Temporal Server 의 History 서비스에서 요청 지연이 일정하지 않았다. 대시보드에서 history 파드의 CPU 사용률은 60% 아래로 나왔지만 파드는 CPU 스로틀링을 받고 있었다.

    촉발

    노드는 8코어였고 history 파드의 CPU 한도는 2코어였는데, Go 로 작성된 Temporal Server 는 GOMAXPROCS 기본값대로 노드의 코어 8개를 모두 쓸 수 있다고 보고 동작했다.

    원인
    구성 요소
    기여 요인
    감지

    kube-prometheus 대시보드에서 history 파드의 CPU 사용률은 60% 아래였지만 스로틀링 비율은 0보다 컸다. 15초 이상 간격으로 수집하는 CPU 사용률 지표로는 0.1초 단위로 일어나는 스로틀링이 보이지 않으므로, 스로틀링 지표를 따로 보고서야 문제를 찾았다.

    조치
    • history 파드 배포에 GOMAXPROCS 환경 변수를 CPU 한도와 같은 2로 설정했다.
    후속 조치
    • Temporal 1.21.0 부터는 CPU 한도가 있고 GOMAXPROCS 환경 변수가 따로 설정되지 않았으면 서버가 GOMAXPROCS 를 CPU 한도에 맞춰 자동으로 설정한다.
    교훈

    CPU 사용률이 낮게 나와도 스로틀링은 일어날 수 있으므로 스로틀링 지표를 따로 관찰해야 한다. Go 서비스에서는 GOMAXPROCS 를 CPU 한도의 정수 코어 수에 맞춘다. GOMAXPROCS 는 CPU 요청값으로는 자동 설정되지 않으므로, CPU 한도를 쓰지 않는다면 CPU 요청값과 같거나 조금 큰 값으로 직접 설정한다. 가능하면 CPU 한도를 쓰지 말고 CPU 요청값을 적절히 잡은 뒤 노드 CPU 사용량을 지켜본다. 노드 CPU 가 자주 바닥나면 파드가 요청값을 넘어 자주 버스트한다는 뜻이므로 요청값을 다시 잡는다.

  3. 증상

    DevOps 팀이 아직 운영 트래픽을 받지 않는 notification-preferences 마이크로서비스의 `resources.requests.cpu` 를 2에서 1로 줄였다. 작업을 마치고 몇 분 뒤 메모리 사용량이 90% 를 넘었다는 경보가 왔다. 메모리 할당량이나 JVM 의 GC 관련 인자는 건드리지 않은 상태였다.

    촉발

    리소스 최적화 작업 중 notification-preferences 디플로이먼트의 `resources.requests.cpu` 를 2에서 1로 줄였다. CPU limit 은 설정하지 않은 상태였다.

    원인
    구성 요소
    기여 요인
    감지

    CPU requests 를 줄이고 몇 분 뒤 메모리 사용량이 90% 를 넘었다는 경보가 울렸다.

    조치
    • JVM 옵션에 `-XX:ActiveProcessorCount=1` 을 넣어 JVM 이 쓸 CPU 수를 강제로 지정했다. 자원을 다시 늘리거나, CPU limit 을 걸거나, requests 를 1001m 이나 999m 으로 두는 방법은 각각 문제가 있어 고르지 않았다.
    후속 조치
    • 이 문제를 사내 공지로 알렸다.
    교훈

    cgroup v1 환경에서 JVM 은 `cpu.shares` 값이 정확히 1024 일 때 이를 설정 없음으로 보고 노드의 CPU 수를 쓴다. CPU limit 없이 requests 만 1로 준 JVM 파드는 노드가 클수록 스레드를 많이 띄우고 메모리를 더 쓴다. 이 문제는 쓸 수 있는 CPU 수로 스레드 수를 정하는 WebFlux 같은 프레임워크에서 특히 크게 드러난다. 이런 설정이라면 `-XX:ActiveProcessorCount` 나 CPU limit 으로 CPU 수를 명시해야 한다. Hyperconnect 는 원래 운영 JVM 애플리케이션에 CPU requests 를 2 이상 주었고, 마이크로서비스가 늘어 자원을 아끼려다 이 문제를 만났다.

  4. 증상

    Buffer 엔지니어가 컨테이너의 스로틀링 지표를 살펴보니, CPU 사용량이 한도 근처에도 가지 않은 컨테이너가 많이 스로틀링되고 있었다.

    촉발

    Buffer 는 노드를 지키려고 컨테이너에 CPU 한도를 걸어 두었는데, 노드 커널에는 CPU 한도가 걸린 컨테이너를 필요 없이 스로틀링하는 버그가 남아 있었다.

    원인
    구성 요소
    기여 요인
    감지

    엔지니어가 컨테이너의 스로틀링 지표를 살피다가, CPU 사용량이 한도보다 훨씬 낮은 컨테이너도 많이 스로틀링되는 것을 보고 알았다.

    조치
    • 사용자에게 직접 또는 간접으로 닿는 경로에 있는 모든 서비스에서 CPU 한도를 없앴다.
    • 한도를 없앤 서비스에 톨러레이션을 더해 테인트를 건 노드에서만 돌게 하고, 한도가 있는 서비스와 떼어 놓았다.
    • 서비스마다 몇 달 치 사용량을 분석해 최대 CPU 사용량에 20% 넘는 여유를 더한 값을 CPU 요청값으로 정했고, 메모리 요청값도 같은 방식으로 정했다.
    후속 조치
    • 커널 수정이 들어간 노드 이미지로 올린다. Buffer 는 kops 1.18 이상에서 기본 이미지가 되는 Ubuntu 20.04 를 기다리고 있다.
    • 수정된 커널로 올린 뒤 스로틀링이 정말 사라졌는지 확인하고, 그 결과로 글을 고친다.
    교훈

    리눅스에서 컨테이너를 돌리면 쿠버네티스든 Mesos 든 Swarm 이든 스로틀링 때문에 컨테이너가 제 성능을 내지 못할 수 있다. 먼저 커널을 수정된 버전으로 올리고 스로틀링 지표를 지켜보는 편이 낫다. CPU 한도를 없애면 지연 시간은 줄지만 위험하다. 한도를 없앤다면 CPU 요청값을 제대로 잡고, 노드의 CPU 와 메모리 사용량을 꼼꼼히 모니터링한다. 사용량이 높으면 Horizontal Pod Autoscaler 로 파드를 늘려 여유 있는 노드에 배치되게 한다. 클러스터에 여유가 없으면 알림을 받거나 노드 오토스케일러로 노드를 늘린다.

  5. 증상

    Omio 는 6개월 동안 원인을 알 수 없는 멈춤을 겪었다. 애플리케이션이 멈추거나 헬스 체크에 응답하지 않았고, 네트워크 연결이 끊겼다.

    촉발

    쿠버네티스는 CPU limit 을 커널 CFS 의 쿼터로 구현한다. 주기는 100ms 이고, limit 2코어는 주기마다 CPU 시간 200ms 가 된다. 스레드 10개가 동시에 돌면 20ms 만에 쿼터를 다 쓰고, 남은 80ms 동안 파드의 모든 스레드가 멈춘다. 여기에 커널 CFS 스케줄러의 알려진 버그가 불필요한 스로틀링을 일으켜, 컨테이너가 허용된 쿼터를 다 쓰기도 전에 스로틀링됐다.

    원인
    구성 요소
    기여 요인
    감지

    팀은 6개월 동안 애플리케이션이 멈추거나 헬스 체크에 응답하지 않는 현상을 겪었지만, 쿠버네티스가 cgroup 지표를 내보내지 않아 스로틀링을 바로 알아채지 못했다. 파드 안에서 /sys/fs/cgroup/cpu/cpu.stat 의 nr_throttled 와 throttled_time 을 읽어 스로틀링 비율을 확인했다.

    조치
    • 버그를 고친 최신 커널이 모든 클러스터에 배포될 때까지 CPU limit 을 껐다.
    후속 조치
    • CFS 쿼터 버그를 고친 최신 커널을 모든 클러스터에 배포한다.
    • 사용률, 포화도, 오류를 보는 USE 지표와 함께 API 지연과 오류율을 지켜보며 결과가 기대한 대로인지 확인한다.
    교훈

    CFS 쿼터 버그가 고쳐지지 않은 커널을 쓴다면 쿠버네티스에서 CPU limit 을 없애거나 kubelet 에서 CFS 쿼터를 끄는 편이 낫다. CPU request 와 limit 은 설정이 비슷해 보여도 구현이 전혀 다르다. CPU 스로틀링은 쿠버네티스 기본 지표에 드러나지 않으므로 cpu.stat 을 직접 확인해야 한다. limit 을 끄면 최적화되지 않은 애플리케이션이 노드의 CPU 를 독차지할 수 있으니, JVM, Go, Node 런타임을 미리 튜닝해 둬야 한다.

내 클러스터에도 있는지 확인하기

이 5건에서 가장 많이 나오는 구성 요소: 컨테이너 CPU 한도, 언어 런타임 설정. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별2