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

사례4건

4건 중 1~4번째

  1. 증상

    프로덕션 EKS 클러스터에서 원인을 바로 알기 어려운 서비스 에러가 간헐적으로 났다. RDS 나 Redis 같은 외부 서비스를 호출할 때 연결이 가끔 실패했다. DNS 요청이 몰릴 때는 도메인 조회 응답이 늦어지거나 조회가 아예 실패했다.

    촉발

    모든 CoreDNS 파드가 같은 노드에 배치되었고, 그 노드의 메모리 사용률이 급증해 메모리가 고갈됐다.

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

    글은 전면 장애를 어떻게 알아챘는지 적지 않았다. 그 전의 DNS 문제는 원인을 알기 어려운 서비스 에러가 간헐적으로 나면서 드러났다. 팀은 RDS 와 Redis 호출이 가끔 실패하는 현상을 추적하다가 DNS 이름 해석 실패가 근본 원인이라는 것을 확인했다.

    조치
    • CoreDNS 앞에서 DNS 질의를 받아 노드마다 캐시하는 NodeLocalDNS Cache 를 데몬셋으로 배포해 CoreDNS 부하를 줄였다.
    • CoreDNS 에 maxUnavailable: 1 인 PodDisruptionBudget 과 topology.kubernetes.io/zone 기준의 topologySpreadConstraints 를 적용해 파드가 한 곳에 몰리지 않게 했다.
    • Deployment 의 dnsConfig 로 ndots 값을 5 에서 2 로 낮춰 불필요한 DNS 조회를 줄였다.
    교훈

    쿠버네티스의 ndots:5 기본값은 점이 적은 외부 도메인을 조회할 때마다 질의를 여러 번 만든다. 이 부하는 트래픽이 큰 프로덕션 환경에서야 드러난다. CoreDNS 를 파드 2개의 기본 구성으로 두면 클러스터 전체의 단일 장애점이 된다. CoreDNS 파드는 노드와 가용 영역에 흩어 둔다. 별도 노드 그룹이나 Fargate 로 분리하면 다른 워크로드와 자원을 다투지 않는다. Affinity 와 PriorityClassName 으로 우선순위를 주면 더 안정적이다. CoreDNS 의 캐시와 bufsize 조정은 증상을 잠깐 줄였을 뿐이다. ndots 값은 여러 자료가 1이나 2를 권하지만 각 환경에 맞춰 정해야 한다.

  2. 증상

    2024-01-24 23:48 CET, FR-PAR 리전에서 Kapsule 과 Kosmos 고객 클러스터의 일부 노드가 NotReady 로 바뀌었다. 같은 시각 API Gateway 로 들어오는 요청이 크게 치솟았다.

    촉발

    FR-PAR 에서 동시에 몰린 배포가 Scaleway Kubernetes API 의 메모리를 바닥냈다.

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

    23:48 에 API Gateway 부하가 늘어난 것이 감지됐고, 00:00:10 에 내부 에스컬레이션을 거쳐 당직 엔지니어가 맡았다.

    조치
    • 관리형 Kubernetes 서비스의 메모리 한도와 가비지 컬렉션 임계값을 곧바로 올렸다.
    • 늘어난 부하를 받도록 주요 서비스에 복제본을 추가로 배포했다.
    • 레지스트리 캐시를 비우고, 클러스터가 안정되는 동안 지켜봤다.
    • 장애 뒤에도 계속 모니터링하며 서비스 설정을 조정했다.
    후속 조치
    • 로컬 인증 캐시를 구현한다.
    • 노드 인증 방식을 더 개선한다.
    • 모니터링을 강화하고 레이트 리밋 전략을 조정했으며 장애 대응 절차를 개선했다.
    교훈

    탄탄한 모니터링과 빠른 대응 체계가 중요하다. Kubernetes API 가 노드 인증까지 맡고 있어서 API 의 메모리 부족이 곧장 노드 NotReady 로 번졌다. Scaleway 는 이를 막으려고 로컬 인증 캐시와 노드 인증 개선을 계획했다.

  3. 증상

    어느 월요일 아침, 엔지니어가 쿠버네티스 클러스터 경고를 보려고 Prometheus 대시보드를 열었는데 접속되지 않았다. Prometheus 서버 파드는 CrashLoopBackOff 상태였다.

    촉발

    Prometheus 가 시작한 지 5분 만에 시계열 수가 2,162,256 까지 급증해 메모리 8GB 호스트의 메모리를 거의 다 썼다.

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

    월요일 아침 엔지니어가 클러스터 경고를 확인하려고 Prometheus 대시보드를 열었다가 접속되지 않는 것을 보고 알았다.

    조치
    • Prometheus configMap 에서 불필요한 설정 대부분을 지워 컨테이너가 더 이상 비정상 종료되지 않게 했다.
    후속 조치
    • Prometheus 파드의 requests 와 limits 를 알맞게 고친다. 지금 문제를 완전히 풀지는 못해도 비슷한 문제를 막아 해결 시간을 줄인다.
    • 불필요한 수집 지표를 줄이도록 수집 대상이나 수집 간격을 조정한다.
    • Prometheus 에 필요한 메모리를 예측해 새 호스트를 마련하고 deploy-topology: Prometheus 같은 노드 레이블을 붙인 뒤, 매니페스트에 nodeSelector 를 넣어 Prometheus 파드가 그 호스트에만 배치되게 한다.
    교훈

    원인은 둘이었다. 첫째, Prometheus 파드의 requests 와 limits 를 잘못 잡아 Prometheus 서버 컨테이너가 높은 oom_score_adj 를 받았다. 둘째, 대규모 클러스터에서 Prometheus 가 쓸 메모리를 미리 예측하지 않았다. 쿠버네티스에서 파드의 QoS 클래스는 메모리가 모자랄 때 어느 컨테이너가 먼저 죽는지에 영향을 준다. 커널의 OOM Killer 는 메모리 사용량과 oom_score_adj 로 점수를 매기고, kubelet 은 QoS 클래스에 따라 oom_score_adj 를 정한다.

  4. 증상

    팀은 여러 서비스가 이상하게 동작한다는 보고를 받았다. 가끔 오류 페이지가 뜨고, 응답이 느리고, 타임아웃이 났다.

    촉발

    장애 직전에 팀원 한 명이 ElastAlert 에 새 알림 규칙을 명령줄로 배포했다. Cloudfront-* 인덱스에 일정 시간 새 문서가 들어오지 않으면 울리는 규칙이었다.

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

    여러 서비스에서 오류 페이지, 느린 응답, 타임아웃이 난다는 보고가 팀에 들어왔다. 알림은 하나도 울리지 않았다. 팀은 Prometheus 와 Grafana 가 안정적인 노드로 옮겨 간 뒤 파드 메모리 사용량 대시보드에서 원인을 찾았다.

    조치
    • NotReady 노드를 하나씩 종료해 오토스케일링 그룹이 새 노드를 띄우게 했다. 새 노드도 곧 NotReady 가 되어 이것만으로는 풀리지 않았다.
    • Prometheus 와 Grafana 가 안정적인 노드에 다시 스케줄된 뒤 파드 메모리 대시보드를 보고 ElastAlert 파드가 원인임을 찾아냈다.
    • 원인인 ElastAlert 문제를 고쳤다.
    후속 조치
    • CPU, 메모리, 디스크 공간 같은 자원 사용량에 알림 규칙을 정의한다.
    • 여러 출처를 함께 쓰는 알림 전략을 계속 연구한다. 지금은 Elasticsearch, 아직 설정하지 않은 Prometheus alertmanager, APM 용 New Relic 이 있다.
    • 지표를 클러스터 밖으로 내보내고 Grafana 도 클러스터 밖으로 옮기는 방안을 검토한다. 옮길 곳은 EC2 나 별도 쿠버네티스 클러스터가 될 수 있다.
    • 중요한 지표를 ELK 에서 시각화하거나 Prometheus 와 Grafana 의 가용성을 높인다. 지표 전략도 개선한다.
    • ElastAlert 의 자원 한도를 Helm values 로 지정한다.
    • 네임스페이스에 메모리 요청값의 기본값과 한도를 설정한다.
    • 고객 대면 워크로드를 빌드, 로깅, 모니터링 워크로드와 떼어 놓는다. 먼저 운영 클러스터 안의 전용 노드 그룹으로 옮기고, 경험에 따라 별도 도구 클러스터도 검토한다.
    • 모든 배포를 Jenkins 파이프라인 같은 자동화로 하고, 새 버전 배포에 GitOps 방식을 검토한다.
    • 배포 뒤 스모크 테스트 단계가 있는 파이프라인으로 배포한다.
    • 쿠버네티스와 클라우드 인프라 작업을 팀 스프린트에 넣어 모든 팀원이 경험 많은 팀원과 짝을 지어 맡게 하고, 주제별 심화 워크숍을 연다.
    교훈

    근본 원인 하나만 탓하는 포스트모템은 장애로 이어진 문제의 15% 정도만 다룬다. 이번에도 ElastAlert 를 고친 것은 일부일 뿐이었다. 알림이 없었고, 모니터링이 같은 클러스터 안에 있었고, Helm 차트의 자원 한도에 기본값이 없었다. 운영 도구와 고객 워크로드가 자원을 나눠 썼고, 손으로 한 배포를 팀이 몰랐고, 스모크 테스트가 없었고, 운영 지식이 일부에게만 있었다. 이렇게 배우려면 장애 건수나 해결 시간만 보지 않고 비난 없는 포스트모템을 허용하는 문화가 필요하다.

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

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

원인별2