[트러블슈팅] 신규 노드 증설 시 일부 정책(주소 그룹, 포트 그룹 등)이 동기화 실패하는 이슈 해소 가이드

개요

기존에 운영중인 시스템에 새로운 노드 클러스터를 연동하거나 기존 노드를 재구성할 때 로그프레소 정책(ex. 주소 그룹(address_group), 위협 인텔리전스(threat_feed))와 같은 일부 정책이 신규 노드에 생성되지 않는 현상이 발생할 수 있습니다.

본 글에서는 해당 이슈의 증상, 원인 분석 방법, 그리고 해소 방안을 안내합니다.


1. 발생 증상

1.1 araqne.log에 나타나는 에러

신규 노드 부팅 후 정책 동기화(policy sync) 단계에서 다음과 같은 에러가 대량으로 발생합니다.

(1) 정책(ex.address_object )동기화 시 NullPointerException 발생

ERROR (PolicyLoaderImpl) - **sonar node: policy sync failure -**
  id=573503, module=address_object, action=add, ...

java.lang.NullPointerException: Cannot invoke
  **"com.logpresso.sonar.api.address.AddressGroup.getGuid()" because "b" is null**
    at com.logpresso.sonar.node.impl.AddressGroupRegistryImpl.getDir(...:333)
    at com.logpresso.sonar.node.impl.AddressGroupRegistryImpl.addItems(...:144)
    at com.logpresso.sonar.node.impl.AddressGroupSyncerImpl.syncAddressObject(...:74)

(2) address_group update 시 IllegalStateException

ERROR (PolicyLoaderImpl) - sonar node: policy sync failure -
  id=736577, module=address_group, action=update, ...

java.lang.IllegalStateException: address group not found:
  **3488daca-0516-4ddb-9e3e-f48650d05a42**
    at com.logpresso.sonar.node.impl.AddressGroupRegistryImpl.updateAddressGroup(...:291)

(3) threat_feed uninstall 시 NullPointerException

ERROR (PolicyLoaderImpl) - sonar node: policy sync failure -
  id=573458, module=threat_feed, action=uninstall, params={name=otx}, ...

**java.lang.NullPointerException: Cannot enter synchronized block because the
  return value of "java.util.Map.get(Object)" is null**
    at com.logpresso.sonar.node.impl.ThreatFeedRegistryImpl.sync(...:345)

1.2 운영상 나타나는 영향

  • 새로운 노드에 일부 정책이 존재하지 않기 때문에 해당 정책 기반의 차단/탐지가 신규 노드에서는 동작하지 않으며, 그로 인한 araqne.log 의 ERROR 로그가 룰 실행 마다 증적이 됩니다.
  • 신규 정책을 추가/수정해도 해당 노드에는 반영되지 않을 수 있습니다.

2. 원인

발생 원인은 다양할 수 있지만, 금번 이슈는 sonar_sync_queue 테이블에 일부 정책의 create 이벤트가 누락되어 있는 것이 원인이었습니다.

로그프레소 데이터 경로($DATA_DIR)하위의 sonar-node에 클러스터 연동 시 sonar_sync_queue 테이블의 작업을 id 순서대로 실행하여 정책들을 동기화 받게 됩니다. 이때 자식 객체의 작업(예: address_object add)이 부모 객체의 create 이벤트보다 먼저 등장하면, 노드 메모리에 부모 객체가 없는 상태에서 자식 객체를 추가하려다 NPE가 발생하게 됩니다.


3. 원인 분석 방법

다음 절차로 누락된 정책을 식별할 수 있습니다.

3.1 araqne.log에서 실패한 정책 ID와 GUID 확인

먼저 어떤 모듈, 어떤 id에서 실패가 발생했는지 확인합니다.

# 모듈별 실패 건수 집계
grep "policy sync failure" /logpresso/log/araqne.log* \
  | grep -oE "module=[a-z_]+" | sort | uniq -c | sort -rn

아래 명령어를 적용하면 not found: <guid> 형태의 에러가 발생한 guid 결과를 얻을 수 있습니다.

grep "not found" /logpresso/log/araqne.log* \
  | grep -oE "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" \
  | sort -u

3.2 sonar_sync_queue에서 누락된 정책 확인

위에서 추출한 guid가 sonar_sync_queue에 어떤 액션으로 기록되어 있는지 확인할 수 있습니다.
만약 운영 시스템이라면 부하가 가지 않도록 쿼리 실행에 유의해주시기 바랍니다.

-- 특정 guid의 sync_queue 기록 확인
dbquery sonar
SELECT id, module, action, created_at
FROM sonar_sync_queue
WHERE params LIKE '%<문제_guid>%'
ORDER BY id;

정상이라면 createupdate/add 순으로 기록되어 있어야 합니다. create 액션이 없고 updateadd만 있다면 누락된 정책입니다.

3.3 실제 운영 테이블과 sync_queue 비교

sonar_ip_blacklist 등 실제 운영 테이블에는 정책이 존재하는데 sonar_sync_queue에는 create 기록이 없는 경우, 노드 동기화 시 NPE를 유발하게 됩니다.

-- 1) 운영 테이블의 전체 정책 guid
dbquery sonar
SELECT guid, name, created_at FROM sonar_ip_blacklist ORDER BY created_at;

-- 2) sync_queue에 create 이벤트가 있는 guid
dbquery sonar
SELECT JSON_EXTRACT(params, '$.address_group.guid') AS guid
FROM sonar_sync_queue
WHERE module = 'address_group' AND action = 'create';

(1)에는 있는데 (2)에는 없는 guid가 누락된 정책입니다.


4. 해결 방법

신규 노드의 sonar-node 경로 하위의 데이터들을 다른 노드(ex. 운영중인 수집서버)의 데이터와 수동으로 맞추는 것으로 해소할 수 있습니다.

4.1 사전 준비

  • 작업 전 운영팀과 점검 시간을 협의합니다.
  • 마스터 노드의 정책 데이터 백업을 권장합니다.

4.2 신규 노드 sonar-node 수동 동기화

  1. 신규 노드의 sonar-node 프로세스 중지

    systemctl stop logpresso.service
    # 또는
    cd $LOGPRESSO_HOME && ./logpresso stop 
    
  2. 노드의 기존 정책 데이터 디렉터리 백업 및 초기화

    mv /data/logpresso-data/sonar-node /data/logpresso-data/sonar-node.bak.$(date +%Y%m%d)
    
  3. 마스터 노드에서 최신 sonar-node 데이터 디렉터리를 받아 신규 노드에 복사

    • sftp, rsync 또는 scp 등을 이용하여 마스터의 /data/logpresso-data/sonar-node 디렉터리를 신규 노드의 동일 경로에 복사합니다.
    • 권한과 소유자가 동일하게 유지되도록 주의해야 합니다 (chown -R logpresso:logpresso).
  4. sonar-node 프로세스 재시작

    systemctl start logpresso.service
    # 또는
    cd $LOGPRESSO_HOME && ./logpresso start
    
  5. araqne.log에서 정상 동기화 확인

    tail -f /logpresso/log/araqne.log | grep -E "policy sync failure|AddressGroup"
    # 더 이상 NPE 에러가 발생하지 않으면 정상입니다.
    

4.3 정책 적재 검증

신규 노드에서 정책 개수와 항목 수가 마스터와 동일한지 확인합니다.

아래는 IP 차단리스트 데이터를 조회하는 쿼리 예시로, 정책 별로 테이블을 구분하여 관리합니다.

dbquery sonar SELECT COUNT(*) FROM sonar_ip_blacklist;
dbquery sonar SELECT COUNT(*) FROM sonar_ip_blacklist_items;

5. 재발 방지 권장 사항

  • 신규 노드 증설 시에는 부팅 단계에서 마스터 주소(sonar.setMaster) 설정이 정상적으로 완료되었는지 로그를 확인해야 합니다.
  • 운영 간 정책 등록은 반드시 정상 API/UI 경로를 통해 수행하고, 직접 SQL로 정책 테이블을 변경하는 것은 권고하지 않습니다.
  • Galera 클러스터의 split-brain 또는 IST/SST 발생 시에는 sync_queue 정합성도 함께 점검할 것을 권장합니다.

6. 문의

본 글의 내용이 이해하기 어려우시거나, 유사 이슈가 해당 가이드로 해소되지 않을 경우에 아래 정보를 함께 첨부하여 Logpresso 기술지원으로 문의해 주시기 바랍니다.

  • 신규 노드의 araqne.log (초기 셋팅(설치)한 이후 24시간)
  • dbquery sonar SELECT COUNT(*), module, action FROM sonar_sync_queue GROUP BY module, action; 결과
  • 실패한 정책의 guid 목록 (3.1 절차로 추출 가능)