The trouble with mounting (새 탭에서 열림)

데이터독(Datadog) 에이전트가 특정 환경에서 응답을 멈추고 종료조차 되지 않는 문제는 NFS(Network File System)의 '하드 마운트' 속성과 시스템 콜의 작동 방식 때문에 발생했습니다. 하드 마운트된 NFS 서버와의 연결이 끊기면 디스크 정보를 확인하는 statvfs 시스템 콜이 무한 대기에 빠지며, 이는 결과적으로 에이전트 전체의 중단으로 이어졌습니다. 이를 해결하기 위해 데이터독은 디스크 체크 로직을 별도 스레드로 분리하고 타임아웃을 적용함으로써, 고객사의 시스템 설정에 관계없이 에이전트의 가용성을 확보하는 설계를 도입했습니다.

에이전트 정지 현상과 원인 분석

  • 일부 시스템에서 모든 메트릭 수집이 중단되고 에이전트가 '종료 불가능한(unkillable)' 상태로 멈추는 버그가 보고되었습니다.
  • 조사 결과, 에이전트는 항상 디스크 체크 과정에서 멈췄으며 구체적으로 파이썬의 os.statvfs 함수 호출 시점에서 병목이 발생했습니다.
  • os.statvfs는 내부적으로 glibc의 statvfs 시스템 콜을 호출하는데, 이는 리눅스 환경에서 파일 시스템의 상태 정보를 가져오는 표준적인 방법입니다.

NFS 하드 마운트와 시스템 콜의 무한 대기

  • NFS를 '하드 마운트(hard mount)' 옵션으로 연결하면, 서버가 응답하지 않을 때 시스템 콜이 타임아웃 없이 성공할 때까지 영구적으로 재시도합니다.
  • 하드 마운트는 데이터의 일관성을 보장하지만 네트워크 불안정 시 해당 마운트 지점에 접근하는 프로세스를 '좀비' 상태로 만들 수 있으며, 이는 NFS의 기본 설정이기도 합니다.
  • 특히 glibc의 statvfs 구현체는 정보를 찾기 위해 /proc/mounts에 나열된 모든 디렉토리를 순회하므로, 현재 조사하려는 대상이 아닌 다른 NFS 마운트에 문제가 생겨도 시스템 전체가 멈추는 현상이 발생합니다.

별도 스레드 및 타임아웃 도입을 통한 해결

  • 데이터독 에이전트는 고객이 설정한 마운트 옵션을 강제로 변경할 수 없으므로, 어떤 환경에서도 정상 동작할 수 있는 방어적인 코드가 필요했습니다.
  • 문제를 해결하기 위해 statvfs 호출을 별도의 스레드에서 실행하도록 구조를 변경하고, 메인 스레드에는 타임아웃 로직을 추가했습니다.
  • 만약 특정 마운트 지점에서 시스템 콜이 응답하지 않더라도, 메인 스레드는 지정된 시간 이후 작업을 포기하고 다음 메트릭 수집으로 넘어감으로써 에이전트의 전체 성능을 보존합니다.
  • 이 방식은 하드 마운트가 활성화된 시스템에서 약간의 메모리 사용량 증가를 야기하지만, 다양한 이질적 환경에서 모니터링 연속성을 보장하기 위한 필수적인 트레이드오프(Trade-off)로 채택되었습니다.

서버 환경에서 NFS를 운용할 때는 soft 마운트 옵션이나 intr(interruptible) 옵션을 검토하여 시스템 콜이 무한 대기에 빠지는 상황을 예방해야 합니다. 또한, 모니터링 도구와 같이 외부 환경에 민감한 애플리케이션을 개발할 때는 외부 시스템 콜(I/O) 작업을 반드시 별도 스레드로 격리하고 엄격한 타임아웃을 적용하는 설계가 중요합니다.