[IT 심층 분석]
ZFS ARC 캐시의 예상치 못한 대규모 Eviction으로 인한 I/O 성능 붕괴와 메모리 압력 조정기
김민준 · IT 시스템 엔지니어|
고가용성 분산 스토리지 클러스터의 성능을 모니터링하던 중 ZFS(Zettabyte File System) 기반 노드들이 특정 시간대에 디스크 I/O 지연이 급격하게 늘어나는 패턴을 발견했습니다. 단순히 디스크 자체의 IOPS 한계에 도달한 것이 아니었습니다. ARC(Adaptive Replacement Cache) 즉 ZFS가 메인 메모리를 이용해 자주 읽히는 디스크 블록을 캐싱하는 스마트 메모리 캐시 시스템이 갑자기 모아뒀던 데이터 수십 기가바이트를 내다버리고(Evict) 있었고 이것이 불필요한 디스크 재접근을 폭발적으로 유발하는 있었습니다. 이 현상의 근원지를 밝히기 위해 arc_summary 스크립트와 zpool iostat을 주무기로 삼아 파고들었습니다.
ZFS ARC가 데이터를 내쫓는 이벤트는 이상한 것이 아닙니다. 새로운 데이터가 들어오는데 메모리가 부족하면 오래되거나 덜 쓰인 캐시를 비우는 것은 당연한 논리입니다. 문제는 이 증발의 타이밍과 규모가 납득하기 어려울 정도로 크고 갑작스럽다는 점이었습니다. 주범을 매복하기 위해 다른 프로세스의 메모리 사용 행태를 시계열로 기록했는데 충격적인 패턴이 드러났습니다. 정기적으로 돌아가는 야간 데이터 백업 에이전트가 시작되는 시간과 ARC Eviction 폭발 타이밍이 놀랍도록 정확하게 일치하고 있었던 것입니다. 백업 프로세스가 운영체제 전반의 메모리를 다량으로 긁어가기 시작하자 커널이 ZFS ARC 영역에 메모리 반환 요청을 강하게 날렸고 ZFS는 어쩔 수 없이 몸통을 팔아 요청에 응한 것이었습니다.
이 충돌을 완화하기 위한 전략은 두 방향에서 추진했습니다. 첫째로 ZFS ARC의 최솟값과 최댓값을 명확하게 운영 체계에 못 박아두는 것이었습니다. /etc/modprobe.d 설정에서 zfs_arc_min과 zfs_arc_max 파라미터를 설정하여 백업 에이전트가 제아무리 메모리 압력을 가해도 ARC가 절대 침범당하지 않을 최소 보호 구역을 보장해두었습니다. 둘째로 백업 에이전트 프로세스 자체에 cgroups의 메모리 서브시스템을 통해 할당 한도를 부여하여 그것이 무한정으로 메모리를 삼켜버리는 것 자체를 원천 차단했습니다. 두 조치를 함께 적용한 이후 새벽 시간대의 백업 잡이 돌아가는 동안에도 ARC 캐시 히트율은 90% 이상을 일관성 있게 유지하였고 스토리지 지연 그래프는 매끈한 일직선을 보여주었습니다.