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

사례4건

4건 중 1~4번째

  1. 증상

    파드 안의 애플리케이션이 초당 수백 건씩 클러스터 내부 서비스의 이름을 조회하자 no such host 와 i/o timeout 오류가 자주 났다. 쿠버네티스 플랫폼을 쓰는 팀은 클러스터의 DNS 서버에 성능 문제가 있다고 보고 Cloud Platform 팀에 문의했다.

    촉발

    MySQL 클러스터 감시 애플리케이션이 감시하는 클러스터 수가 늘어났고, 그 뒤부터 이름 조회 오류가 잦아졌다.

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

    Cloud Platform 팀은 쿠버네티스 플랫폼을 쓰는 팀에게서 클러스터 DNS 서버에 성능 문제가 있다는 문의를 받고 알게 됐다.

    조치
    • 커널 파라미터 net.core.netdev_max_backlog 값을 늘렸다.
    • softnet 지표에 알림을 설정했다.
    • softnet 알림에 대응하는 런북을 마련했다.
    후속 조치
    • veth 인터페이스를 netkit 인터페이스로 바꿔 파드의 송신 패킷이 backlog 큐를 거치지 않고 물리 장치로 바로 가게 하는 방안을 검증한다. netkit 은 리눅스 커널 6.7 에 들어온 가상 네트워크 장치이고, Cilium 1.16 부터 쓸 수 있다.
    교훈

    netdev_max_backlog 를 늘리고 softnet 알림과 런북을 두면 같은 장애가 덜 나고, 나더라도 일찍 알아챌 수 있다. 다만 값을 늘리는 것은 근본 대책이 아니어서, 더 많은 패킷을 보내는 파드가 배포되면 backlog 큐가 다시 차고 패킷이 버려질 수 있다.

  2. 증상

    2021년 9월부터 메트릭 질의 서비스의 업데이트를 롤아웃할 때마다 오류가 늘었다. 서비스 로그에는 DNS 오류 때문에 메트릭 데이터 저장소에 연결하지 못했다는 내용이 찍혔다. 클라이언트가 실패한 질의를 자동으로 재시도해 사용자에게 보이는 오류는 적었지만, 재시도 때문에 대시보드와 모니터의 지연이 늘었다.

    촉발

    2021년 8월 메트릭 질의 클라이언트의 업데이트를 롤아웃하면서 새 기본값인 gRPC round_robin 부하 분산 정책이 처음 적용됐다. round_robin 은 끊긴 채널을 자동으로 다시 연결하는데, 오래전에 넣어 둔 매우 공격적인 gRPC 재연결 타임아웃과 겹쳐 서비스 롤아웃 때마다 사라진 파드 IP 로 SYN 이 쏟아졌다.

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

    2021년 9월부터 메트릭 질의 서비스 롤아웃 때 오류가 늘어나는 것을 보았고, 서비스 로그에서 DNS 오류가 데이터 저장소 연결을 막는 것을 확인했다.

    조치
    • node-local-dns 파드의 메모리를 64 MB 에서 256 MB 로 올렸다. OOM 오류는 멈췄지만 DNS 오류는 계속됐다.
    • AWS 가 더 많은 연결을 추적할 수 있다고 한 더 큰 인스턴스 유형으로 서비스 인프라를 올려 보았고, 그것만으로 문제가 사라지는 것을 확인했다.
    • SYN 폭주를 일으킨 사용자 지정 gRPC 재연결 파라미터를 지우고 기본값으로 되돌리는 PR 을 만들었다. 다음 롤아웃에서는 오류가 나지 않았다.
    후속 조치
    • Cilium 프로젝트에 PR 을 기여한다. 이 PR 은 옛 파드 IP 에 unreachable 경로를 더해, 지워진 파드로 가는 요청이 martian 패킷이 되지 않게 한다. 그러면 역경로 필터가 SYN 을 버리지 않고, 클라이언트는 분명한 ICMP 오류를 받는다.
    교훈

    gRPC, 쿠버네티스, AWS 같은 강력한 추상화도 엣지 케이스에서는 평소에 숨어 있던 복잡함이 오류로 드러난다. 몇 달을 조사한 끝에, 이번 장애의 뿌리가 팀이 직접 한 변경에 있다는 것을 찾았다. 의존성의 버그를 피해 가려던 변경, 이전 장애를 고치려던 변경, 기본 재연결 파라미터를 덮어쓴 변경이었다. 이 변경들은 당시에는 안전해 보였지만 한참 뒤에 상관관계를 찾기 어려운 때에 뜻밖의 결과를 냈다. DNS 문제처럼 보여도 DNS 문제가 아닐 때가 있다. AWS ENA 지표와 VPC Flow Logs 는 연결 추적을 들여다보는 데 중요하다. DNS 전파 시간은 여러 요인에 좌우된다.

  3. 증상

    클러스터 전체 네트워크 장애를 겪은 뒤, 팀은 파드 사이 통신이 간헐적으로 늦어지고 웹 애플리케이션 전체가 이따금 느려지는 것을 알아챘다.

    촉발

    libc 리졸버가 A 레코드와 AAAA 레코드 조회를 같은 포트로 보냈고, DNAT 와 SNAT 변환이 일어나는 경로에서 conntrack 경합 조건 때문에 그중 하나가 응답을 받지 못했다.

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

    웹 애플리케이션이 간헐적으로 느려지고 파드 사이 요청이 5초의 배수만큼 늦게 도착하는 것을 보고 알았다. 지연이 5초 단위라는 점에서 DNS 조회를 의심했고, tcpdump 로 확인했다.

    조치
    • 파드 스펙의 dnsConfig options 에 single-request-reopen 을 넣어 A 와 AAAA 조회가 서로 다른 포트로 나가게 했다.
    • gRPC 애플리케이션의 Dockerfile 에 GRPC_DNS_RESOLVER=native 를 넣어 ares 대신 libc 리졸버를 쓰게 했다.
    • `tcpdump port 53` 으로 A 와 AAAA 조회가 서로 다른 포트로 나가는 것을 확인했다.
    교훈

    지연이 5초, 10초, 15초처럼 5초의 배수로 나타나면 DNS 조회 재시도를 먼저 의심한다. 리눅스 이미지는 파드 dnsConfig 에 single-request-reopen 을 넣으면 된다. gRPC 는 기본 리졸버가 libc 를 쓰지 않을 수 있으므로 GRPC_DNS_RESOLVER=native 도 함께 설정해야 한다. 설정이 먹었는지는 tcpdump 로 A 와 AAAA 조회가 나가는 포트를 보고 확인한다.

  4. 증상

    2019-01-08 이른 아침 Tinder 플랫폼에 오래 이어지는 장애가 났다. 노드에서 파드로 가는 통신과 DNS 조회가 실패했다.

    촉발

    그날 아침 장애에 앞서 이번 장애와 관계없는 플랫폼 지연이 늘자 클러스터의 파드와 노드 수를 늘렸다. 장애 당시 노드는 605개였고, 이 수는 기본 gc_thresh3 값을 넘기에 충분했다.

    원인
    구성 요소
    기여 요인
    조치
    • gc_thresh1, gc_thresh2, gc_thresh3 값을 올렸다.
    • Flannel 을 재시작해 ARP 표에서 빠진 네트워크를 다시 등록했다.
    교훈

    Tinder 는 이 장애로 네트워크 구성의 한계를 알게 됐다고 정리했다. Flannel 과 VXLAN 을 쓰는 클러스터에서는 노드마다 ARP 항목이 생기고, ELB 를 거쳐 다른 노드의 파드로 가는 통신이 항목을 더 늘린다. 그래서 노드가 605개에 이르자 리눅스의 기본 gc_thresh3 값으로는 모자랐다. 이 한계를 넘으면 패킷만 버려지는 것이 아니라 Flannel 의 /24 대역이 ARP 표에서 통째로 빠져 노드와 파드 사이 통신과 클러스터 안 DNS 가 함께 멈춘다.

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

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

원인별3