CoreOS : tcpdump가 네트워크 문제를 과도하게 해결합니다 (사용 된 과도한 소켓 수)


14

오늘 미스터리가 있습니다. Azure에서 CoreOS (2023.5.0 / Linux 4.19.25-coreos) 기반의 소규모 3 노드 Elasticsearch 클러스터를 실행합니다. Elasticsearch는 호스트 네트워크 모드의 도커 컨테이너 내에서 실행됩니다. 거의 1 년 이상 유지 보수가 거의 필요없는 상태에서 기계가 매우 흥미로운 상태로 전환되는 것을 보았습니다.

최신 정보

이 문제는 Linux 커널 의 드라이버 수정으로 해결되었습니다 . 아래 답변을 참조하십시오.

조짐

기본적으로 영향을받는 시스템과 다른 두 노드 사이의 네트워킹은 죽습니다. 모두 동일한 가상 네트워크와 동일한 서브넷에 있으며 보통 다른 사람과 통신 할 수 있습니다. 영향을받는 노드는 여전히 다른 서브넷 (및 ssh로 연결할 수 있음)과 다른 피어링 된 가상 네트워크에서 도달 할 수 있습니다. 컴퓨터는 인터넷에 (매우 드문) 연결되어 있지만 대부분의 요청은 시간 초과됩니다.

영향을받는 노드에서보고 된 "소켓 사용"수가 /proc/net/sockstat매우 높은 것으로 나타났습니다 (정상 노드에서 ~ 300 대신 ~ 4.5k). 모니터링에 따르면이 수는 노드를 사용할 수 없게 된 순간부터 빠르게 증가합니다.

재밌는 점은 사용 된 소켓의 소스를 식별 할 수 없다는 것입니다.

# cat /proc/net/sockstat
sockets: used 4566
TCP: inuse 2 orphan 0 tw 2 alloc 98 mem 4
UDP: inuse 1 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

# cat /proc/net/sockstat6
TCP6: inuse 98
UDP6: inuse 1
UDPLITE6: inuse 0
RAW6: inuse 1
FRAG6: inuse 0 memory 0

그 외에는 기계가 괜찮아 보입니다. 실행중인 의심스러운 프로세스가없고 CPU 사용량이 최소화되며 사용 가능한 메모리가 충분합니다.

동일한 서브넷에 "연결할 수없는"VM을 핑 (Ping)하면 몇 가지 EAGAIN응답이 발생 recvmsg하고 ENOBUFS에서 다시 가져 옵니다 sendmsg. 여기에 strace ping 출력

추가 출력을 수집하여 (시스템을 수정하기 전에) https://gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c 에 게시했습니다.

분석

우리는 서버에서 생각할 수있는 모든 것을 종료하려고 시도했으며, elasticsearch가 첫 번째 용의자입니다. 그러나 elasticsearch 컨테이너를 종료해도 사용 된 소켓이 해제되지 않습니다. 모든 CoreOS 관련 프로세스 (update-engine, locksmithd, ...) 또는 전체 Docker 런타임 또는 Azure 관련 항목에 대해서도 동일합니다. 아무것도 도움이되지 않는 것 같습니다.

그러나 이제는 더 이상해집니다. 우리는 tcpdump무슨 일이 일어나고 있는지 확인하기 위해 머신에서 실행 을 시도 했습니다. 보라 : 문제는 스스로 해결되었고 연결성은 회복되었다. 우리의 이론은 tcpdump가 그것을 해결하는 일종의 syscall을 수행한다는 것입니다. gdb로 tcpdump를 실행하고 모든 syscall에 중단 점을 설정했습니다. 많은 중단 점을 단계별로 수행 한 후, 캡처 소켓에서 프로 미스 쿠스 모드 (특히 libpcap의이 행 )를 설정하는 작업은 사용 된 소켓을 재설정하고 정상 상태로 되 돌리는 것입니다.

추가 결과

  • 우리는 실행중인 것을 확인했다 tcpdump-p/--no-promiscuous-mode플래그하면 소켓을 사용 카운터를 삭제하고 사용 가능한 상태로 기계를 반환하지 않습니다.
  • 실행 ifconfig eth0 txqueuelen 1001하면 사용 된 소켓 카운터가 재설정 되지만 연결은 복원 되지 않습니다 .
  • 수동 모드를 사용하여 수동 모드 ip link set eth0 promisc on를 설정해도 연결이 복원되지 않습니다.
    • net.ipv4.xfrm4_gc_thresh 이 32768로 설정되어 있고 약간 늘리면 문제가 해결되지 않습니다.

사용 된 소켓

우리는 우리와 마찬가지로 당황한 Azure와 연락을 취했습니다. 이것이 문제가 아니라 증상 일 뿐이라는 것을 이해합니다. 그러나 그것은 내가 지금까지 찾은 유일한 유형의 것입니다. 내 희망은 증상을 이해함으로써 근본 원인에 더 가까이 갈 수 있다는 것입니다. Azure의 네트워크 인터페이스는 이 네트워크 드라이버 로 실행됩니다 .

아마 CoreOS / Kernel이 책임이 있습니까?

타임 라인 관점에서 볼 때 2019-03-11에 CoreOS가 최신 버전으로 자동 업데이트 된 날에 문제가 시작되었습니다. 릴리스 노트에 따르면 이 업데이트에는 4.15.23 에서 4.19.25로 커널 업데이트가 포함 되었습니다 . 여전히 변경 로그를 통해 문제가 있는지 확인하고 있습니다. 지금까지 나는 최근 몇 달 동안 hyperv 네트워크 드라이버가 상당히 많은 업데이트를 받았음을 알았지 , 전부 4.19.25의 일부인 것 같지는 않습니다. CoreOS가 4.19.25에 적용한 패치 세트는 그다지 인상적이지는 않지만 가짜 nf_conntrack_ipv4 모듈을 도입 한 패치는 새로운 것입니다.

업데이트 : 가능한 관련 들어오는 커널 패치?

도움!

지금까지 우리가 가진 질문은 다음과 같습니다.

  • 이 "소켓 사용"메트릭이 급상승하는 원인은 무엇입니까? 이 메트릭에 대한 커널 소스 를 읽었으며 실제로 어떤 종류의 소켓인지 또는 어떤 소켓을 만들 었는지에 대한 참조가없는 카운터 인 것 같습니다 .

  • 왜 숫자가 약 4.5k로 평평합니까? 어떤 한계로 인해이 문제가 발생합니까?

  • 커널 4.14.96과 4.19.25 사이에 중요한 변화가 있었습니까?

  • setsockopt()libpcap 의 호출이 상태를 재설정하는 이유는 무엇 입니까?

관련 CoreOS 버그 : https://github.com/coreos/bugs/issues/2572


열린 소켓은 결과적인 문제이며 IMHO의 근본적인 문제는 아닙니다. 브리지 장치의 macvlan 장치 (자체 mac 주소 포함)가있는 Linux 시스템 에서이 동작을했습니다. 브리지를 무단으로 설정하면 macvlan 장치가 작동했습니다. 나는 코레 오스 나 하늘빛을 모른다. 문제는 기본 레이어가 상위 레벨의 mac 주소에 대해 알지 못한다는 것입니다.
AndreasM

당신의 의견에 감사드립니다! 나는 사용 된 많은 소켓이 근본 원인이 아니라는 것을 알고 있습니다. 나는 기계에서 비정상으로 식별 할 수있는 확실한 한 가지에 집착하고 있습니다.
Stephan Klein

안녕 스테판. 어떤 소식? 1) WOL이 활성화되어 있습니까? 2) sysctl -w net.ipv4.route.flush = 1이 해결됩니까? 3) 작동하지 않는 상태에서 arp 캐시는 무엇입니까? 작업 상태에서?
Massimo

답변:


4

우선, 잘 쓰여진 질문에 감사드립니다!

설명 한 세부 수준이 매우 높고 이미 gdb 수준에 있으므로 내 대답이별로 유용하지 않을 것이라고 생각합니다. 어쨌든, 여기 시도해보십시오 :

  • 아마도 당신은 이미 같은 시도 ss -aelsof -n?
  • 합니까 dmesg이 경우 반환 아무것도 흥미는?
  • 서버에서 iptables를 사용합니까?
  • tcpdump 이외의 다른 방법 (예 :)을 사용하여 무차별 모드를 설정하면 ip link set [interface] promisc on문제가 해결됩니까?
  • 의심스러운 프로세스, 파일 또는 기타 이상한 활동이 있는지 확인 했습니까? 어쩌면 초대받지 못한 불쾌한 과정이 숨어있는 그림자에 숨어 있고 무차별 모드가 설정 될 때마다 침묵한다고 생각하십니까?
  • tcpdump를 백그라운드로 실행하면이 문제가 다시 발생합니까?

이게 도움이 되길 바란다.


1
당신의 답변에 감사드립니다! 실제로 참조하는 일부 명령의 출력을 수집했습니다. 그들은 또한 질문에 연결되어 있습니다 ( gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c ). 이상한 점은 GET 방식으로 적은 소켓에서보고 ss, lsof그리고 netstat에서 "사용 소켓"에서보다 /proc/net/sockstat. 그 파일에서 읽은 것처럼 보이는 총 수만 같습니다. iptables실행하지만 특별한 규칙이 없습니다 (장점 참조), promiscous 모드를 직접 설정하거나 tcpdump를 계속 실행하지 않았습니다. 다음에 그렇게 할 것입니다.
Stephan Klein

ss -aepi내 출력 컬렉션에 출력을 추가 했습니다 : gist.github.com/privatwolke/…- 슬프게도 dmesg는 이것이 일어날 때 아무것도 반환하지 않습니다. 실제로, 사건이 발생하기 전 최신 항목은 5 일입니다.
Stephan Klein

dmesg / journalctl -k출력이 추가되었습니다 .
Stephan Klein

ip link set eth0 promisc on단독으로 시스템을 사용 가능한 상태로 복원하지 않는지 확인했습니다 .
Stephan Klein

안녕하세요,이 사이트에서이 다른 질문을 보셨습니까? serverfault.com/questions/614453/… xfrm4 대상 캐시가 고갈되었을 수 있습니다. 이 커널 설정으로 그것을 늘릴 수 있습니다 : xfrm4_gc_thresh - INTEGER The threshold at which we will start garbage collecting for IPv4 destination cache entries. At twice this value the system will refuse new allocations. 내가 말할 수있는 한, 여기서도 실행되지 않는 IPsec과 관련이 있습니다.
페드로 페레즈

0

이것은 Linux 커널의 hv_netsvc 드라이버 버그로 인한 것입니다. Microsoft 개발자와 함께이 문제를 해결하고 수정 프로그램을 업스트림에 적용 할 수있었습니다.

여기에 커밋 메시지를 인용하면 문제가 아주 잘 요약됩니다.

RX 완료 메시지로 인해 링 버퍼가 거의 가득 차면 TX 패킷이 "낮은 워터 마크"에 도달하여 큐가 중지 될 수 있습니다. TX 완료가 대기열 중지보다 일찍 도착하면 웨이크 업이 누락 될 수 있습니다.

이 패치는 EAGAIN 및 성공 사례를 모두 포함하도록 마지막 보류 패킷에 대한 검사를 이동하므로 필요할 때 큐가 안정적으로 깨어납니다.

나중에 참조 할 수 있도록이를 수정하는 커밋은 https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f 입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.