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

사례17건

17건 중 5~9번째

  1. 증상

    2024년 9월 25일 22:25 UTC부터 SFO3 리전의 DigitalOcean 서비스 전반에서 네트워크 연결 문제가 생겼다. 리전 전체 서비스는 22:50에 회복됐지만 일부 Managed Kubernetes 클러스터는 그 뒤에도 연결이 불안정했다.

    촉발

    SFO3 코어 라우터 한 대에서 하드웨어 오류로 라인 카드 대부분이 동시에 재부팅됐다.

    원인
    구성 요소
    기여 요인
    –
    조치
    • 죽었던 라인 카드가 모두 빠르게 다시 올라와 네트워크 트래픽이 다시 흐르고 코어 라우터가 정상으로 돌아왔다.
    • SFO3 리전 DOKS 전체에서 영향받은 노드를 손으로 모두 재생성했다.
    후속 조치
    • 장비 벤더 지원팀과 함께 라인 카드가 죽은 근본 원인을 찾는다.
    • SFO3 리전 코어 라우터의 소프트웨어를 업그레이드한다.
    • 자동 복구 조치의 임계값을 높여 사람이 손으로 노드를 복구해야 하는 일을 줄인다.
    교훈

    네트워크가 몇 분 만에 돌아와도 게스트 네트워킹이 회복되지 않은 노드는 사람이 재생성할 때까지 비정상으로 남았다. 리전 전체 서비스는 25분 만에 돌아왔지만 DOKS 는 01:40까지 영향을 받았다. 자동 복구 조치가 이 경우를 처리하지 못해 SFO3 DOKS 전체에서 수동 작업이 필요했다.

  2. 증상

    트래픽이 급하게 오르내리는 환경에서 CoreDNS 에 부하가 몰렸다. 네트워크 문제가 생기고 응답 지연이 크게 늘었다.

    촉발

    트래픽이 급변하면서 수가 적은 CoreDNS 파드에 처리할 수 있는 양보다 많은 부하가 몰렸다.

    원인
    구성 요소
    기여 요인
    조치
    • 클러스터 크기에 맞춰 CoreDNS replica 를 늘리도록 CPA 를 설정하고, 인스턴스 타입에 맞게 nodesPerReplica, coresPerReplica, replica 최솟값과 최댓값을 조정했다.
    • CoreDNS 에 anti-affinity 대신 ScheduleAnyway 로 느슨하게 한 topologySpreadConstraints 를 걸어, Karpenter 의 Consolidation 과 Drift 가 CoreDNS 에 막히지 않게 했다.
    • CoreDNS 의 Error Rate, Panics, Request Duration, Request Rate 에 임곗값 알림을 걸었다.
    • NodeLocal DNSCache 를 적용해 노드마다 DNS 캐시를 두고 메인 CoreDNS 의 부하를 낮췄다.
    교훈

    CoreDNS 가 감당할 수 있는 양은 파드에 준 리소스에 따라 다르고, 그에 따라 평균 지연과 초당 질의 수인 QPS 도 달라진다. CoreDNS replica 를 무작정 늘리면 taint 와 topologySpreadConstraints 때문에 파드가 몇몇 노드에 몰려 Karpenter 의 Consolidation 을 막을 수 있다. 노드 하나가 드레인될 때 그 노드의 CoreDNS 가 한꺼번에 많이 종료되면 서비스에 영향이 갈 수 있다. NodeLocal DNSCache 를 쓰면 메인 CoreDNS 로 가는 DNS 질의가 크게 줄고 스파이크를 다루기 쉬워진다. 어느 노드에서 문제가 생겨도 메인 CoreDNS 는 영향을 받지 않는다. 그래서 서비스 전체 장애로 번질 일이 노드 하나의 문제로 그친다. 글쓴이는 CPA 와 NodeLocal DNSCache 를 함께 적용해 CoreDNS 부하 문제를 거의 없앴다고 보았다.

  3. 증상

    2023-03-14 18:00 UTC 쯤 한 서비스에서 통신 오류가 늘기 시작했다. 곧 모든 고객의 파이프라인이 늦게 시작하다가 끝내 작업이 돌지 않았고, 18:19 UTC 에 상태 페이지에 작업 시작 지연이 올라왔다.

    촉발

    3월 14일 17:40 UTC 쯤 인프라 팀이 전날 되돌렸던 구성 요소들을 다른 방식으로 다시 업그레이드했다. 전날 kube-proxy 를 되돌린 뒤로 iptables 동기화가 조금씩 실패하던 상태에서 업그레이드를 이어 가자 동기화 오류가 한꺼번에 치솟았다.

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

    팀은 3월 14일 18:00 UTC 에 한 서비스의 통신 오류가 늘어나는 것을 보고 장애를 알아챘다. 장애 통화에 사람이 더 들어오면서 영향이 여러 서비스로 퍼진 것을 확인했다. 3월 13일 롤백 뒤에 로그에 나온 소수의 Sync 실패 오류는 그때 알아채지 못했다.

    조치
    • 모든 노드를 차례로 재시작해 노드마다 iptables 규칙 집합을 새로 만들었고, 23:00 까지 모든 노드 교체를 마쳤다.
    • contexts 나 machine executor 를 쓰는 작업이 회복되지 않아 별도의 의존성 풀을 재시작했고, 3월 15일 01:15 UTC 에 모든 작업이 정상으로 돌았다.
    • 작업이 다시 돌기 시작하자 쌓인 작업을 처리하려고 용량을 늘렸다.
    • 망가진 큐 몇 개를 고치려고 RabbitMQ 노드를 재시작했다.
    후속 조치
    • 앞으로의 업그레이드에서 이런 위험을 크게 줄이도록 쿠버네티스 업그레이드 절차를 고친다.
    • 이번 장애 때 kube-proxy 가 낸 동기화 오류를 잡는 지표와 알림을 더했다.
    • RabbitMQ 인프라의 복원력을 높일 방법을 검토한다.
    교훈

    이번 장애를 촉발한 원인은 하나가 아니었다. 네트워크는 모든 것의 바탕이어서 쿠버네티스 업그레이드는 본래 위험하다. 여러 사건이 맞물려 터진 이번 경우에는 팀이 세워 둔 위험 완화 방법이 듣지 않았다.

  4. 증상

    2022-10-31 13:45 UTC 에 팀은 계획된 vpc-cni EKS 애드온 업그레이드를 배포 파이프라인으로 시작했다. 14:10 에 파이프라인이 업그레이드 중 타임아웃으로 실패했다. 45개 aws-node 파드 가운데 약 10개만 업그레이드됐다. 5개는 Terminating 에 멈췄고, 나머지 30개는 업그레이드를 시도하지도 못했다.

    촉발

    매일 도는 노드 롤오버가 2022-10-31 07:30 UTC 에 가장 최신 EKS 노드 AMI 인 v20221027 을 가져와 기존 노드를 이 AMI 로 만든 새 노드로 바꿨다. 이 AMI 는 나중에 커널 문제로 회수됐다.

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

    07:30 롤오버 뒤 14:10 에 vpc-cni 업그레이드 파이프라인이 타임아웃으로 실패했다. 팀은 롤오버 7시간 뒤인 14:30 에 노드가 NodeNotReady 를 오가는 것을 보고 이상을 알았다. 감지까지 7시간이 걸렸다. 알림은 NodeNotReady 이벤트와 소켓 증가를 잡지 못했다. 팀은 17:21 에 GitHub 에서 v20221027 의 PLEG 관련 이슈를 찾고 나서 원인을 알았다.

    조치
    • Terminating 에 멈춘 노드를 하나씩 cordon, drain, 삭제해 vpc-cni 업그레이드를 끝냈다. 모두 15대를 지웠다.
    • 특정 AMI 를 지정할 수 있도록 인프라 모듈의 terraform 을 고치고 테스트해 master 브랜치에 머지했다.
    • 파이프라인으로 EC2 Auto Scaling 그룹 launch configuration 의 AMI 를 이전의 정상 버전으로 되돌려 노드를 다시 만들었다.
    후속 조치
    • 각 팀에 readiness, liveness 프로브를 쓰자고 제안한다.
    • readiness, liveness 프로브 적용 현황을 보여 주는 대시보드를 만든다.
    • readiness, liveness 프로브와 그 쓸모를 설명하는 위키 글을 쓴다.
    • 인프라 모듈에서 특정 AMI 를 지정할 수 있게 고친다.
    • 최신 AMI 를 바로 받을지, 새 AMI 를 배포 전에 어떻게 시험할지 논의하는 자리를 잡는다.
    • 비정상적인 NodeNotReady 이벤트나 소켓 사용 증가를 잡는 알림을 만든다.
    • 팀 안에 Kubernetes 학습 과정을 만든다.
    • 노드 로그를 중앙에서 모은다.
    • 나와 있는 최신 AMI 를 조회하는 Prometheus exporter 를 만들고, 이를 쓰는 대시보드와 알림도 만든다.
    교훈

    새 AMI 를 배포한 날에는 다른 컴포넌트 업그레이드를 매우 조심해야 한다. 이번에는 새 노드 AMI 를 쓴 날 EKS 컴포넌트도 함께 올리면서 원인을 가리기 어려웠다. 장애나 문제가 생겼을 때 각 팀과 소통하는 경로도 개선해야 한다. 문제를 알린 팀에게서 자세한 내용을 받기 어려웠고, 팀별 당직 호출 경로도 없었다. 팀이 Kubernetes 컴포넌트를 깊이 이해하지 못했던 점도 장애에 영향을 준 요인이었다.

  5. 증상

    LINE 의 messaging-hub 는 일본 음식 배달 서비스 Demaecan 의 Merchant 앱과 Driver 앱에 웹소켓으로 메시지를 보낸다. 어느 날 최대 트래픽 시간이 아닌데도 웹소켓 연결 수 그래프가 순간적으로 크게 떨어졌다. 이 현상은 한 번으로 끝나지 않고 불규칙하게 계속 일어났다.

    촉발

    같은 L7 로드밸런서를 공유하는 다른 서비스 담당자가 자기 LB 설정을 배포하면 HAProxy 가 재로드됐다. hard-stop-after 로 정한 30분이 지나 이전 프로세스가 종료되면서 거기 붙어 있던 웹소켓 연결이 모두 끊겼다.

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

    웹소켓 연결 수 그래프에서 최대 트래픽 시간이 아닌데도 연결 수가 순간적으로 뚝 떨어지는 것을 보고 알았다. Nginx 패킷 드롭은 네트워크 모니터링으로 원인을 찾았다.

    조치
    • Merchant 팀이 토큰 발급 API 를 따로 떼어 배포해 토큰 요청이 몰려도 다른 Merchant API 가 지연되지 않게 했다.
    • Nginx 를 늘리고 파드 안티 어피니티와 레이블 셀렉터로 Nginx 파드가 서로 다른 노드에 뜨게 해서 NF_CONNTRACK 테이블 포화로 생기던 패킷 드롭을 없앴다.
    • Ingress Nginx 의 proxy-read-timeout 과 proxy-send-timeout 을 300s 에서 3600s 로, LB timeout 도 3600s 로 올렸지만 웹소켓 드롭은 멈추지 않았다.
    • 공유하던 L7 LB 를 L4 LB 로 바꿔 웹소켓 드롭을 없앴다.
    교훈

    문제의 범위를 미리 단정해 스스로 제한하면 안 된다. 인프라 팀과 네트워크 팀이 문제없다고 답했다는 이유로 직접 다룰 수 있는 영역만 뒤지다가 공유 L7 LB 를 늦게 의심했다. LB 같은 기술 리소스를 다른 서비스와 공유하면 다른 팀의 배포가 내 서비스의 연결을 끊을 수 있다. Nginx 를 늘려 NF_CONNTRACK 부담을 나눌 때는 파드가 서로 다른 노드에 뜨게 해야 하고, 노드 수보다 많이 늘리면 Pending 상태로 남는 파드가 생긴다는 점도 알아야 한다.

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

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

원인별6

용량 한계6건

  1. IL-0581 이구위크 첫날 Redis 커넥션이 실패하며 29CM 상품 전시 서버의 파드가 다운되고 Netty 이벤트 루프가 포화됐다
  2. IL-0027 CoreDNS 파드가 모두 한 노드에 몰린 채 그 노드의 메모리가 고갈되자 DNS 가 응답하지 못해 아이디어스 서비스 전체가 멈췄다
  3. IL-0182 트래픽이 급변할 때 수가 모자란 CoreDNS 가 과부하로 지연과 간헐적 네트워크 끊김을 일으켰고, 나중에는 과하게 늘린 CoreDNS 파드가 Karpenter 의 노드 통합을 막았다
  4. IL-0445 EKS 로 옮기던 레거시 시스템에서 conntrack 테이블이 넘쳐 연결이 끊겼고, 이어 CoreDNS 파드가 축출될 때와 node-local-dns 를 넣은 뒤에 DNS 오류가 났다
  5. IL-0013 노드 RAM 을 절반으로 줄이자 conntrack 테이블이 가득 차 집계 서비스에 연결 리셋과 오류가 늘었다
  6. IL-0064 CPU 를 많이 쓰는 파드가 Google Cloud 노드 하나에 몰려 노드가 커널 패닉으로 죽었고, 다시 배치된 파드가 다음 노드를 또 죽이며 웹사이트와 API 가 멈췄다.

소프트웨어 결함6건

  1. IL-0150 DynamoDB DNS 자동화의 경쟁 조건이 us-east-1 리전 엔드포인트의 DNS 레코드를 비워 DynamoDB 와 EC2 인스턴스 시작이 실패했고, 그 여파로 EKS, ECS, Fargate 의 컨테이너 시작과 클러스터 스케일링이 14시간 넘게 막혔다
  2. IL-0112 나중에 회수된 EKS 노드 AMI 로 노드를 교체한 뒤 노드가 PLEG is not healthy 를 보고하며 NotReady 를 오갔고 파드 네트워크 타임아웃이 났다
    DFDS2022
  3. IL-0012 CPU limit 과 커널 CFS 쿼터 버그로 파드가 과하게 스로틀링돼 헬스 체크가 실패하고 애플리케이션이 멈췄다
    Omio2020
  4. IL-0062 GKE Ingress 뒤의 파드가 SIGTERM 을 받자마자 새 연결을 받지 않고 정상 종료해서 API 에 가끔 502 오류가 났다
  5. IL-0011 HAProxy 인그레스 템플릿이 백엔드 파드를 IP 순으로 정렬해 일부 파드에 요청이 몰리고 인그레스 컨테이너가 OOMKilled 됐다
  6. IL-0050 ndots:5, Alpine 의 musl 리졸버, Netty 4.1.30 의 DNS 처리 문제가 겹쳐 쿠버네티스 서비스가 클러스터 밖 Redis 호스트 이름을 반복해서 해석하지 못했다

클라우드 제공자 장애1건

조직
  1. IL-0084 베어메탈 업체 vSwitch 의 패킷 드롭으로 Namespace 의 fra3 리전이 빠져 전 세계 용량이 모자랐고, 다음 날에는 컨트롤 플레인 노드의 느린 NVMe 쓰기로 쿠버네티스 API 서버 CPU 가 치솟아 zrh1 이 멈췄다.

DNS·네트워크 장애2건

  1. IL-0154 SFO3 코어 라우터의 라인 카드가 하드웨어 오류로 한꺼번에 재부팅된 뒤 게스트 네트워킹이 돌아오지 않은 DOKS 노드가 비정상으로 남아, 일부 클러스터의 연결과 컨트롤 플레인 접속이 01:40 UTC까지 불안정했다.
  2. IL-0056 kops 에서 EKS 로 옮긴 뒤 AWS VPC CNI 의 SNAT 때문에 파드에서 다른 VPC 의 NLB 뒤 서비스로 가는 호출이 간헐적으로 실패했다

업그레이드로 깨진 호환성1건

조직
  1. IL-0230 쿠버네티스 업그레이드 도중 메인 운영 클러스터의 서비스 간 통신이 끊겨 모든 고객의 작업이 시작되지 않았다

설정 변경1건

조직
  1. IL-0177 다른 팀의 설정 배포로 공유 L7 HAProxy 가 재로드될 때마다 messaging-hub 의 웹소켓 연결이 한꺼번에 끊겼다.