{"id":"IL-0472","org":"Tinder","date":"2019-01-08","docs":[],"title":{"en":"Node-to-pod traffic and DNS failed on Tinder's 605-node Flannel cluster when every node's ARP cache passed gc_thresh3","ko":"노드 605개 클러스터의 모든 노드에서 ARP 캐시가 넘쳐 노드와 파드 사이 통신과 DNS 조회가 끊겼다"},"domain":["kubernetes","aws","networking"],"impact":{"scope":"Tinder's platform had a persistent outage: node-to-pod communication and in-cluster DNS lookups failed across the 605-node cluster","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Tinder lists the outage among its learnings about network fabric limits: with Flannel over VXLAN, every node, and every pair of nodes that exchange pod traffic, adds entries to each node's ARP table, so at 605 nodes the default gc_thresh3 hard cap was exceeded on all nodes.","ko":"Tinder 는 이 장애로 네트워크 구성의 한계를 알게 됐다고 정리했다. Flannel 과 VXLAN 을 쓰는 클러스터에서는 노드마다 ARP 항목이 생기고, ELB 를 거쳐 다른 노드의 파드로 가는 통신이 항목을 더 늘린다. 그래서 노드가 605개에 이르자 리눅스의 기본 gc_thresh3 값으로는 모자랐다. 이 한계를 넘으면 패킷만 버려지는 것이 아니라 Flannel 의 /24 대역이 ARP 표에서 통째로 빠져 노드와 파드 사이 통신과 클러스터 안 DNS 가 함께 멈춘다."},"related":[],"sources":[{"url":"https://medium.com/tinder/tinders-move-to-kubernetes-cda2a6372f44","kind":"blog","archived":"https://web.archive.org/web/20260822043736/https://medium.com/tinder/tinders-move-to-kubernetes-cda2a6372f44"}],"summary":{"en":"Tinder ran its platform on a Kubernetes cluster on Amazon EC2, provisioned with kube-aws, with Flannel as the network fabric forwarding packets over VXLAN. Each worker node takes its own /24 of pod addresses out of a larger /9 block, which adds one route table entry, one ARP entry on the flannel.1 interface and one forwarding database entry per node. Node-to-pod and pod-to-pod traffic also flows over the eth0 interface and adds an ARP entry for each source and destination node. This traffic was common: each Kubernetes Service had an ELB that registered every node, and a node that received a packet from the ELB used its iptables rules for the Service to pick a pod at random, often on another node.\n\nOn the morning of 8 January 2019 pod and node counts were scaled up in response to an unrelated latency increase. With 605 nodes in the cluster, the ARP entries exceeded the default gc_thresh3 on all nodes. Packets were dropped and entire Flannel /24 ranges disappeared from the ARP table, so node-to-pod communication and DNS lookups, served inside the cluster, failed. The fix was to raise gc_thresh1, gc_thresh2 and gc_thresh3 and restart Flannel so it registered the missing networks again.","ko":"2019-01-08 이른 아침 Tinder 플랫폼에 오래 이어지는 장애가 났다. 그날 아침 장애에 앞서 이번 장애와 관계없는 지연이 늘어 클러스터의 파드와 노드 수를 늘렸다. 그 결과 모든 노드에서 ARP 캐시가 바닥났다. ARP 캐시를 다루는 리눅스 커널 값 셋 가운데 gc_thresh3 는 넘을 수 없는 상한이다. 동기 가비지 컬렉션 뒤에도 자리가 없으면 커널은 패킷을 버린다.\n\nTinder 는 쿠버네티스 네트워크로 Flannel 을 쓰고 패킷을 VXLAN 으로 전달했다. 워커 노드는 저마다 큰 /9 대역에서 /24 가상 주소 대역을 받는다. 노드 하나마다 라우팅 표 항목 하나, flannel.1 인터페이스의 ARP 항목 하나, 포워딩 데이터베이스 항목 하나가 생긴다. 노드에서 파드로, 파드에서 파드로 가는 통신은 결국 eth0 를 거치므로 출발 노드와 도착 노드마다 ARP 항목이 하나씩 더 생긴다. Tinder 환경에서는 이런 통신이 아주 많았다. 쿠버네티스 서비스마다 ELB 가 하나씩 생기고 모든 노드가 ELB 에 등록되는데, ELB 는 파드를 모른다. 그래서 패킷을 받은 노드가 iptables 규칙에 따라 다른 노드의 파드를 무작위로 골라 다시 보냈다.\n\n장애 당시 클러스터에는 노드가 605개 있었고, 이 수는 기본 gc_thresh3 값을 넘기에 충분했다. 그러자 패킷이 버려질 뿐 아니라 Flannel 의 /24 가상 주소 대역 전체가 ARP 표에서 빠져, 노드에서 파드로 가는 통신과 클러스터 안에서 도는 DNS 의 조회가 실패했다. Tinder 는 gc_thresh1, gc_thresh2, gc_thresh3 값을 올리고, Flannel 을 재시작해 빠진 네트워크를 다시 등록해서 장애를 해결했다."},"trigger":{"en":"Earlier that morning, pod and node counts on the cluster were scaled up in response to an unrelated increase in platform latency.","ko":"그날 아침 장애에 앞서 이번 장애와 관계없는 플랫폼 지연이 늘자 클러스터의 파드와 노드 수를 늘렸다. 장애 당시 노드는 605개였고, 이 수는 기본 gc_thresh3 값을 넘기에 충분했다."},"severity":"unknown","symptoms":["service-unavailable","network-unreachable","dns-resolution-failures"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"incident","detection":null,"components":["linux-kernel","cni-plugin"],"root_cause":"capacity","remediation":[{"text":{"en":"Raised gc_thresh1, gc_thresh2 and gc_thresh3 on the nodes","ko":"gc_thresh1, gc_thresh2, gc_thresh3 값을 올렸다."}},{"text":{"en":"Restarted Flannel so it re-registered the missing networks","ko":"Flannel 을 재시작해 ARP 표에서 빠진 네트워크를 다시 등록했다."}}],"action_items":[],"contributing":["default-config-unchanged"],"recurrence_of":null,"symptoms_text":{"en":"In the early morning of 8 January 2019 Tinder's platform had a persistent outage. Communication from nodes to pods failed, and so did DNS lookups, because DNS ran inside the Kubernetes cluster.\n\nThe ARP cache on every node of the 605-node cluster was exhausted. gc_thresh3 is the Linux kernel's hard cap on the ARP cache: \"neighbor table overflow\" log entries mean that even after a synchronous garbage collection there was no room for the neighbor entry, and the kernel then drops the packet. Besides the dropped packets, whole Flannel /24 pod address ranges went missing from the ARP table.\n\nThe outage followed a scale-up of pod and node counts on the cluster earlier that morning, made in response to an unrelated rise in platform latency.","ko":"2019-01-08 이른 아침 Tinder 플랫폼에 오래 이어지는 장애가 났다. 노드에서 파드로 가는 통신과 DNS 조회가 실패했다.\n\nARP 캐시를 다루는 리눅스 커널 값 가운데 gc_thresh3 는 넘을 수 없는 상한이다. 로그에 \"neighbor table overflow\" 가 찍히면 ARP 캐시를 동기 가비지 컬렉션한 뒤에도 이웃 항목을 넣을 자리가 없다는 뜻이다. 이때 커널은 패킷을 통째로 버린다.\n\n이 상한을 넘으면 패킷이 버려질 뿐 아니라 Flannel 이 노드마다 나눠 준 /24 가상 주소 대역 전체가 ARP 표에서 빠진다. DNS 는 클러스터 안에서 돌았기 때문에 DNS 조회도 함께 실패했다.\n\n장애 직전인 그날 아침, 이번 장애와 관계없는 플랫폼 지연이 늘어서 그 대응으로 클러스터의 파드와 노드 수를 늘렸다. 그 결과 모든 노드에서 ARP 캐시가 바닥났다."},"updated_at":"2026-11-14T12:34:11.950091Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0472","org_slug":"tinder"}