CoreOS : tcpdump가 네트워크 문제를 과도하게 해결합니다 (사용 된 과도한 소켓 수) ssh로 연결할 수 있음)과 다른 피어링

오늘 미스터리가 있습니다. 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



답변

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

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

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

이게 도움이 되길 바란다.


답변

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

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

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

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

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