패킷이 외부 스위치에서 들어와 실제 애플리케이션(User Space)까지 도달하는 과정은 매우 복잡하지만, 플랫폼 엔지니어링 관점에서 중요한 '데이터의 전이 과정'을 중심으로 단계별로 정리해 드립니다.
특히 현재 겪고 계신 native routing 및 Cilium eBPF 환경에 맞춰 최적화된 흐름입니다.
패킷이 물리적인 전기 신호에서 메모리 상의 데이터로 변환되는 단계입니다.
ksoftirqd에 의해 SoftIRQ 레벨에서 처리됩니다.커널의 메인 네트워크 스택에 진입하기 전, Cilium이 주입한 eBPF 프로그램이 패킷을 먼저 가로챕니다.
tc 훅에 로드된 Cilium eBPF 프로그램에 의해 검사됩니다.여기서부터는 리눅스 커널의 표준 네트워킹 로직이 작동합니다.
ip_rcv(): IP 헤더의 무결성을 검사합니다.iptables나 nftables의 규칙이 적용됩니다. (Cilium은 이를 상당 부분 우회하지만 여전히 존재합니다.)fib_lookup): 이 패킷이 로컬 프로세스용인지, 아니면 다른 곳으로 포워딩할 것인지 결정합니다.ip_local_deliver(): 로컬 목적지 패킷임이 확인되면, 파편화된 패킷을 재조립하고 상위 계층(TCP/UDP)으로 전달합니다.가장 복잡하고 논리적인 검증이 일어나는 단계입니다. (이전 질문의 드랍 지점)
tcp_v4_rcv(): 패킷의 TCP 헤더를 읽고 해당 패킷을 처리할 소켓(Socket)을 찾습니다.SYN에 대한 응답(ACK)인 경우, tcp_check_req()를 호출하여 request_sock(미니소켓) 상태를 검증합니다. (여기서 실패하면 드랍됩니다.)마지막으로 데이터가 커널 메모리에서 유저 메모리로 이동합니다.
sleep 상태에 있던 애플리케이션 프로세스를 깨웁니다.read / recv): 애플리케이션(예: sshd, Go/Java App)이 시스템 콜을 호출합니다.tcp_check_req 단계는 커널 스택(4단계)에 해당하며, 이는 하드웨어나 Cilium의 결정이 아니라 커널이 가진 '연결 상태 정보'와 '도착한 패킷'이 일치하지 않을 때 발생하는 논리적 거부 단계입니다.이 과정 중 특히 어느 레이어의 메트릭이 가장 의심되시나요? 각 단계별로 더 깊게 파고들고 싶은 부분이 있다면 말씀해 주세요.
===
TCP 계층은 리눅스 커널에서 가장 똑똑하면서도 까칠한 영역입니다. 단순히 패킷을 넘기는 L3와 달리, "이 패킷이 내가 기다리던 게 맞나?"를 집요하게 따지기 때문이죠.
플랫폼 엔지니어로서 pwru 트레이스에서 보셨던 tcp_check_req 단계를 포함해, L4 스택 내부에서 벌어지는 일을 5단계로 더 자세히 풀어보겠습니다.
패킷이 L3(IP)를 통과해 tcp_v4_rcv() 함수에 진입하면 가장 먼저 하는 일은 "이 패킷의 주인이 누구인가?"를 찾는 것입니다.
Source IP/Port, Destination IP/Port 정보를 추출합니다.struct sock)를 검색합니다.RST를 보내고 패킷을 버립니다.소켓을 찾았다면, 이제 소켓의 현재 상태(sk_state)에 따라 패킷 처리 경로가 완전히 달라집니다. tcp_v4_do_rcv()가 이 역할을 수행합니다.
tcp_check_req()가 호출됩니다.tcp_check_req)질문하셨던 드랍 지점이 바로 여기입니다. 서버가 SYN을 받고 SYN-ACK를 보낸 후, 클라이언트의 마지막 ACK를 기다리는 SYN_RECV 상태에서의 로직입니다.
request_sock을 만들어 둡니다.struct tcp_sock)으로 승격(Promote)시키고 ESTABLISHED 상태로 전이합니다. pwru에 찍힌 것처럼 드랍 처리됩니다.연결이 수립된 후 데이터를 주고받을 때는 성능을 위해 두 가지 경로를 사용합니다.
검증이 끝난 데이터 페이로드는 소켓의 수신 큐(Receive Queue)에 쌓입니다.
sk_buff 구조체들이 리스트 형태로 큐에 매달립니다.epoll이나 read() 시스템 콜로 대기 중이던 애플리케이션 프로세스를 깨웁니다.지금 겪고 계신 문제는 3단계(Gatekeeper)에서 발생하고 있습니다. L3 스위치만 있는 환경에서 이 단계의 드랍이 발생한다는 것은, 하드웨어 에러보다는 "네트워크 지연으로 인해 서버가 클라이언트를 기다리다 지쳐(Minisock Timeout) 정보를 삭제했는데, 뒤늦게 클라이언트의 ACK가 도착한 경우"가 가장 유력합니다.
RHEL 10에서도 이 핵심 로직은 동일하며, nstat으로 확인하신 TcpExtTCPMinisocksDrop이 이 3단계를 대변하는 지표라고 보시면 됩니다.
다음 단계로 넘어가기 위해 nstat의 구체적인 수치를 한 번 확인해 보시겠어요? 어떤 카운터가 가장 높은지에 따라 튜닝할 sysctl 변수가 결정됩니다.
===
nstat은 리눅스 커널의 네트워크 통계 정보(/proc/net/netstat 및 /proc/net/snmp)를 실시간으로 읽어와서 보여주는 강력한 도구입니다. 대규모 인프라를 관리하신다면 netstat -s보다 가독성이 좋고 증분값(Delta) 확인이 쉬운 nstat을 주력으로 사용하시는 것이 좋습니다.
플랫폼 엔지니어링 실무에서 가장 많이 쓰이는 확인 방법들을 정리해 드립니다.
nstat은 실행 시점 사이의 변화량(증분)을 보여주는 것이 기본 동작입니다.
nstat -z: 값이 0인 지표까지 모두 포함해서 출력 (전체 지표 확인 시 유용)nstat -a: 증분값이 아닌, 부팅 이후 누적된 전체 합계(Absolute) 출력nstat -n: 현재까지의 통계를 한 번 '0'으로 리셋 (다음 실행 때 깨끗한 증분 확인 가능)앞서 논의한 tcp_check_req 드롭이나 핸드셰이크 문제를 진단할 때 아래 명령어를 사용하세요.
명령어를 실행하고 1~2초 뒤에 다시 실행하면 그 사이의 변화량만 딱 찍힙니다.
# -z를 붙여야 현재 0이라도 나중에 올라오는 지표를 미리 볼 수 있습니다.
nstat -z | grep -E 'TcpExtListenDrops|TcpExtSyncookiesFailed|TcpExtTCPMinisocksDrop'
장애가 이미 지나갔다면 누적값을 보고 시스템의 전반적인 건강 상태를 판단합니다.
nstat -az | grep -E 'TcpExtListenDrops|TcpExtSyncookiesFailed|TcpExtTCPMinisocksDrop'
SSH 연결 지연이나 간헐적 끊김이 있을 때 함께 보면 좋은 지표들입니다.
| 지표명 | 의미 | 해석 가이드 |
|---|---|---|
| TcpExtTCPTimeouts | TCP 재전송 타임아웃 발생 | 네트워크 경로상에 패킷 손실이 있음을 시사 |
| TcpExtTCPBacklogDrop | 백로그 큐가 가득 차서 드롭 | 커널이 패킷을 처리하는 속도보다 유입 속도가 빠름 |
| TcpExtSyncookiesSent | SYN Cookie 발동 횟수 | SYN Backlog가 꽉 찼음을 의미 (튜닝 신호) |
| TcpExtTCPACKSkipped | ACK 처리를 건너뜀 | 주로 윈도우/시퀀스 불일치 시 발생 |
# 위 지표들을 한꺼번에 모니터링하기
nstat -z | grep -E 'Timeout|BacklogDrop|SyncookiesSent|ACKSkipped'
장애 상황을 재현하면서 실시간으로 수치가 올라가는 것을 보고 싶을 때 유용합니다. watch 명령어를 조합하세요.
# 1초마다 nstat을 실행하고(증분 확인), 이전에 확인한 값은 리셋(-n)
watch -n 1 "nstat -n | grep -E 'TcpExtListenDrops|TcpExtSyncookiesFailed|TcpExtTCPMinisocksDrop'"
명령어를 실행했을 때 아래와 같이 나온다면 어떻게 판단해야 할까요?
TcpExtListenDrops 15 0.0
TcpExtTCPMinisocksDrop 120 0.0
nstat을 실행한 이후, ListenDrops는 15회, TCPMinisocksDrop은 120회 발생했다는 뜻입니다.MinisocksDrop이 압도적으로 많다면, 클라이언트의 ACK가 늦게 와서 커널이 기다리다 지쳐 버린 경우가 많으므로 네트워크 지연(Latency)이나 RTT를 먼저 의심해야 합니다.RHEL 10에서도 이 명령어 체계와 결과 형식은 동일하게 유지됩니다. 지금 시스템에서 nstat -az를 실행했을 때 TcpExtTCPMinisocksDrop 수치가 다른 드롭 지표들에 비해 유독 높게 나오나요?