17.3 인프라스트럭처 및 리소스 모니터링 (Infrastructure and Resource Monitoring)
Zenoh 통신 계층이 아무리 최적화되어 동작하더라도, 기저를 이루는 호스트 운영체제(Linux 기반 서버 또는 에지 디바이스)의 하드웨어 자원(CPU, Memory, Storage) 한계치에 봉착할 경우 라우터 데몬은 운영체제 레벨에서 강제 종료되거나 심각한 스로틀링(Throttling)을 겪게 된다.
본 절에서는 소프트웨어 프로토콜 계층의 기능 모니터링에 앞서, 노드 중심(Node-centric)의 물리적·환경적 건전성(Health)을 보장하기 위한 기초 체력 모니터링 아키텍처의 구축 런북(Runbook)을 명세한다. 호스트 인프라스트럭처의 한계를 가시화하는 것은 장애의 원인을 하드웨어 층위와 소프트웨어 층위로 명확히 분리(Decoupling)하는 출발점이다.
1. Zenoh 노드(라우터, 피어, 클라이언트)의 CPU 및 메모리 프로파일링
Zenoh 데몬 프로세스(zenohd)가 호스트 시스템의 연산 리소스 및 물리적 가용 메모리를 점유하는 프로파일 타임라인을 실시간으로 도출해야 한다.
1. node_exporter 탑재를 통한 호스트 지표 추출
분산된 에지 및 클라우드 노드의 베어메탈(Bare-Metal) 상태를 시계열 데이터베이스(Prometheus, 17.4장 참조)로 노출하기 위해 업계 표준 에이전트인 node_exporter를 데몬으로 상주시킨다.
# 백그라운드 프로세스로 CPU, Memory 활용량 등 호스트 매트릭을 수집하여 포트(기본 9100)로 노출한다.
./node_exporter &
2. 특정 프로세스 대상(Targeting) 정밀 프로파일링
전역 시스템 메트릭 추이와는 독립적으로, zenohd 프로세스 단일체가 유발하는 병목 여부를 이분화하여 검증해야 한다. process_exporter를 추가 구성하여 zenohd의 CPU 커널 타임(Kernel Mode) 리소스 지표와 유저 타임(User Mode) 리소스 지표를 분리하여 측정한다.
분석 결과 커널 타임 리소스 점유율이 유저 타임을 압도적으로 상회할 경우, 이는 과도한 컨텍스트 스위칭(Context Switching), I/O 인터럽트 혹은 소켓 폴링(Polling) 구간에서의 병목 등 물리적 수준의 적신호(Red Flag)로 해석해야 한다.
2. 네트워크 대역폭 사용량 및 패킷 누수(Drop) 측정
인프라스트럭처 연결 활성화 여부(Ping 헬스체크)를 능가하는, 물리적 파이프라인의 포화도(Saturation)와 처리 과정에서의 패킷 유실률(Drop Rate) 판독이 필수적이다.
1. 물리적 네트워크 인터페이스(NIC) 단위 대역폭 모니터링
ifstat 또는 sar -n DEV 1과 같은 커널 유틸리티를 브리지하여, 주력 이더넷 인터페이스(예: eth0)에 초당 유입(RX)/유출(TX)되는 바이트 볼륨을 시계열로 수집한다. 특정 순간의 대역폭 점유율이 하드웨어 한계 용량(예: 1Gbps)의 80%를 임계치(Threshold)로 초과할 경우, 버퍼 대기 지연(Queuing Latency)은 기하급수적으로 폭증하게 된다.
2. 커널 스택 패킷 폐기(Drop) 감시
애플리케이션(Zenoh 데몬) 계층으로 데이터가 도달하기도 전, 운영체제 커널의 네트워크 스택에서 데이터 패킷이 강제 폐기되는 링 버퍼(Ring Buffer) 오버플로우 현상을 가장 경계해야 한다.
# 리눅스 커널의 네트워크 스택이 버퍼 고갈 혹은 체크섬 에러로 폐기한 패킷 누적수량을 덤프한다.
netstat -s | grep "packet receive errors"
해당 수치가 점진적으로 증가(0 초과)하는 것은 대규모 네트워크 서비스 거부(DDoS) 트래픽 인입, 혹은 호스트 운영체제의 네트워크 버퍼(rmem_max, wmem_max)가 턱없이 부족하다는 명백한 증거다. 이는 즉각적인 OS 레벨 커널 튜닝(16.2장)으로 연계되어야 한다.
3. 파일 디스크립터(File Descriptor) 및 소켓 상태 모니터링
단일 호스트 환경에서 과도한 클라이언트가 라우터에 동시 연결을 시도할 시 Too many open files 예외가 방출되며 데몬 접속이 전면 거부된다. Unix 계열 운영체제에서 소켓(네트워크 세션)은 파일 구조체(File Descriptor, FD)로 취급되기 때문이다.
1. 파일 디스크립터(FD) 쿼터 한계 모니터링
Zenoh 데몬 프로세스가 점유 중인 활성 파일 및 네트워크 소켓의 유효 개수를 실시간으로 덤프하여 고갈(Exhaustion) 위협을 추적한다.
# zenohd 프로세스(특정 PID)가 현재 개방 중인 파일 디스크립터의 인스턴스 맹수를 집계한다.
ls -l /proc/<PID>/fd | wc -l
해당 수치가 운영체제가 프로세스에 할당한 소프트 임계치(ulimit -n, 통상 1,024 기본값)의 80%를 도과할 경우, 연결 거부(Connection Refused) 장해 직전의 응급 상태(Critical Alert)로 관제 대시보드 및 담당자 인시던트 채널(예: Slack)에 경고를 인가해야 한다.
2. TIME_WAIT 상태 소켓의 군집 감시
TCP 세션 종료 핸드셰이크가 정상적으로 완결되지 못해 자원(포트)을 반환하지 않고 로컬 대기 상태인 TIME_WAIT 소켓의 누적 상태를 순회해야 한다.
# 현재 시스템에 누적 잔류 중인 TIME_WAIT 상태의 네트워크 소켓 식별 및 렌더링
ss -ant | grep TIME_WAIT | wc -l
해당 수치가 비정상적인 우상향 곡선을 그린다면, 코어 애플리케이션의 커넥션 타임아웃 주기가 과도하게 보수적으로 설정되었거나, 퍼블리셔 단에서 연결을 재활용하지 않고 매 세션별로 소켓 파괴와 생성을 무한 반복(Connection Churn)하는 버그가 내포되어 있음을 시사한다.
4. 컨테이너 및 Kubernetes 환경에서의 리소스 추적
Zenoh 프로세스를 물리적 호스트 쉘(Shell)이 아닌 Docker, 혹은 Kubernetes(K8s)의 파드(Pod) 형태로 감싸 배포(Deployment)하였을 경우, 전통적인 논리 커널 모니터링 기법은 무의미해진다. 컨테이너 워크로드는 cgroups(Control Groups) 및 네임스페이스(Namespace)라 불리는 논리적 격리벽 내부에 상주하기 때문이다.
1. Cgroups 매트릭 추출기(cAdvisor) 탑재 전술
물리 호스트 모니터링 대타(Stand-in) 장비로서, 컨테이너 오케스트레이터의 서브 런타임에 직접 액세스하는 cAdvisor(Container Advisor)를 융합 배치해야 한다. 이는 K8s 환경에서 특정 Zenoh 파드(Pod)가 논리적으로 할당받은 메모리 임계(Limit) 2GB 중 현재 1.9GB를 점유 중이라는 상대적 포화도 프로파일을 밀리초(ms) 단위 스텝으로 산출할 수 있다.
2. Pod 재기동 로직 및 OOMKilled 추적
Kubernetes 데몬셋 혹은 디플로이먼트 정책상 장애 발생 파드는 수동 복구(Manual Intervention) 과정을 생략하고 즉시 Kubelet에 의해 자동 부활(Auto-Restart) 조치된다. 이러한 특성 탓에 운영자는 실물 장애 여부를 육안으로 체감하지 못하는 치명적 환상(Illusion)을 경험한다.
클러스터에 kube-state-metrics를 필수로 체인 연결하여, 대상 인프라 라우터 파드의 restarts 횟수 시계열 증가 추이와 OOMKilled(메모리 초과에 의한 K8s의 OOM 킬러 사살 이벤트) 로그를 관제 포크스 포인트로 상정해야 한다. 데몬의 예기치 못한 자동 재기동(Restart)은 곧 해당 프로세스 메모리에 상주하던 모든 버퍼링 큐(Data Payload)가 영구적으로 공중분해(Data Loss)되었음을 입증하는 구조적 재앙의 확증이기 때문이다.
graph TD
classDef os fill:#e1f5fe,stroke:#0277bd,stroke-width:2px;
classDef k8s fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
classDef monitor fill:#fff3e0,stroke:#ef6c00,stroke-width:2px;
classDef alert fill:#ffebee,stroke:#c62828,stroke-width:2px;
subgraph Bare_Metal_Environment [Bare Metal Linux Server]
OS[Kernel Net Stack<br>`netstat -s`]:::os
ZenohProc[zenohd Process<br>`/proc/PID/fd`]:::os
NIC[Network Interfaces<br>`ifstat`]:::os
NodeExp[node_exporter<br>process_exporter]:::monitor
NodeExp -.-> OS
NodeExp -.-> ZenohProc
NodeExp -.-> NIC
end
subgraph Kubernetes_Environment [Kubernetes Cluster]
Pod[Zenoh Router Pod]:::k8s
Cgroups[cgroups Memory/CPU]:::k8s
Kubelet[Kubelet Restart Policy]:::k8s
cAdvisor[cAdvisor]:::monitor
KubeState[kube-state-metrics]:::monitor
cAdvisor -.-> Cgroups
KubeState -.-> Kubelet
end
Prometheus[(Prometheus <br> Time-series DB)]:::monitor
NodeExp ==> Prometheus
cAdvisor ==> Prometheus
KubeState ==> Prometheus
Prometheus --> Rules{Alerting Rules}
Rules -->|FD > 80% Limit| AlertFD[Alert: Port Exhaustion]:::alert
Rules -->|OOMKilled > 0| AlertOOM[Alert: Pod OOMKilled]:::alert
Rules -->|Drop Packets > 0| AlertDrop[Alert: Kernal Ring Buffer Overflow]:::alert