[ Splunk ] Event Processing
본문 바로가기

Splunk

[ Splunk ] Event Processing

728x90
반응형

1. 이벤트 처리란?

  • Splunk는 들어온 데이터를 이벤트(event) 단위로 쪼개고, 이를 인덱스에 저장한다.
  • 이벤트 = 머신 데이터 속에서 발견되는 활동 기록

이벤트 인덱싱 단계

  1. 문자 인코딩 처리 (UTF-8 변환 시도)
  2. 멀티라인 이벤트 줄 구분(Line Breaking)
  3. 타임스탬프 식별 및 적용
  4. 표준 필드(host, source, sourcetype) 추출
  5. 이벤트 분리(Segmentation)

2. 데이터 파이프라인 구조

  • 데이터는 인덱서(Indexer)에 들어와 여러 파이프라인 단계를 거친다.
  • 크게 두 단계:
    • Parsing (이벤트 분리)
    • Indexing (최종 저장/전송)

주요 파이프라인

  • Parsing Pipeline: 데이터 청크(10KB 단위)를 이벤트로 나눔
  • Indexing Pipeline: 이벤트를 최종적으로 저장하거나 다른 인스턴스로 전송
  • Merging/Typing Pipeline: 이벤트 병합, 정규식 변환, 주석(annotator) 등 보조 기능
  • Forwarder 차이점:
    • Universal Forwarder: 단순 수집·전달 (Parsing 없음)
    • Heavy Forwarder: Parsing + Indexing 수행 가능, 대신 디스크에 저장하지 않고 TCP로 전달

3. Parsing 단계

(1) 문자 인코딩

  • 기본적으로 UTF-8로 처리
  • props.conf의 CHARSET으로 소스 인코딩 지정 가능 (UTF-16, BIG5 등)
  • 잘못 지정 시 타임스탬프 인식 실패 가능

(2) Line Breaking

  • 기본 패턴: ([\r\n]+) (개행 기준)
  • 커스텀 정규식으로 이벤트 경계 지정 가능 (LINE_BREAKER)
  • 잘못 설정하면 이벤트가 둘로 쪼개질 수 있음 → 필요 시 Line Merging으로 복구

(3) Header

  • 여러 데이터 스트림을 하나의 채널로 합칠 때 사용
  • props.conf → HEADER_MODE = always|firstline|none
    • always: ***SPLUNK*** 문자열이 있으면 인덱스 타임 필드를 재작성
    • firstline: 첫 번째 줄만 재작성에 사용
    • none: ***SPLUNK*** 문자열을 일반 데이터로 취급
    • <empty>: Scripted input은 always, File input은 none 적용

(4) Timestamp 추출

  • Splunk는 다양한 날짜/시간 형식을 처리 (datetime.xml 참조)
  • 관련 옵션: TIME_PREFIX, TIME_FORMAT, MAX_TIMESTAMP_LOOKAHEAD
  • DATETIME_CONFIG = none → 파일 수정 시간 사용
  • DATETIME_CONFIG = current → 현재 시각 사용
더보기

📘 Merging: Time 결정

It’s critical that time is set since Splunk indexing based on time.

  • Splunk 인덱싱은 시간(time) 을 기반으로 하기 때문에, 올바른 타임스탬프 설정이 매우 중요하다.

주요 설정 파라미터

  1. TIME_PREFIX
    • 이벤트 내에서 타임스탬프를 찾기 시작할 위치를 지정한다.
    • Splunk는 이벤트를 스캔하다가 TIME_PREFIX와 일치하는 문자열을 발견하면, 그 지점부터 시간을 찾는다.
  2. TIME_FORMAT
    • Splunk가 어떤 형식의 시간을 찾을지 정의한다.
    • 예: 월/일/년, YYYY-MM-DD HH:MM:SS, Unix epoch 등
  3. MAX_TIMESTAMP_LOOKAHEAD
    • TIME_PREFIX 이후 얼마나 떨어진 위치까지 시간을 찾을지(최대 바이트 수) 지정한다.
    • 예: TIME_PREFIX 이후 50자 이내에서 시간이 발견되지 않으면 → 해당 줄은 타임스탬프가 없다고 판단.
  4. SHOULD_LINEMERGE / LINE_BREAKER
    • 여러 줄 이벤트 병합 여부 및 줄 단위 이벤트 구분 방식에 영향을 미친다.
  5. TRUNCATE
    • 한 이벤트의 최대 길이를 지정한다. (기본 10,000 바이트)
    • 초과 시 잘리므로, 긴 이벤트를 다루는 경우 반드시 적절히 설정해야 한다.
  6. EVENT_BREAKER / EVENT_BREAKER_ENABLE
    • 라인 단위가 아닌 이벤트 경계(Event Boundary) 를 명확히 정의할 수 있는 설정.
    • 멀티라인 로그 처리에서 권장됨.

DATETIME_CONFIG 설정

  • DATETIME_CONFIG = none
    → 이벤트에 날짜/시간 정보가 전혀 없는 경우 사용.
    → Splunk는 파일 수정 시각(file modified time)을 이벤트 시간으로 사용한다.
  • DATETIME_CONFIG = current
    → 이벤트에 날짜/시간이 없을 때, 현재 시스템 시각(wall clock time)을 사용.
    → 예: 스크립트 실행 결과를 실시간으로 수집할 때.
  • DATETIME_CONFIG = <파일 경로>
    → 커스텀 XML(datetime.xml) 파일을 지정해 날짜/시간 추출 규칙을 정의할 수 있다.
    → 예시:→ $SPLUNK_HOME이 경로 앞에 자동으로 붙는다.
/etc/slave-apps/pathToFile   (Indexer Cluster 환경)  
/etc/apps/pathToFile         (단일 Indexer 환경)

 


동작 흐름 예시

  1. Splunk가 이벤트를 읽는다.
  2. TIME_PREFIX에서 시작 지점을 찾는다.
  3. TIME_FORMAT에 맞는 문자열이 나오는지 검사한다.
  4. MAX_TIMESTAMP_LOOKAHEAD 안에서 발견되지 않으면, 해당 줄은 시간 없음으로 처리 → 이전 이벤트의 타임스탬프를 이어받는다.
  5. 최종적으로 결정된 시간 정보는 이벤트 인덱싱 시 사용

4. Merging 단계

  • 잘린 라인을 다시 하나의 이벤트로 합침 (SHOULD_LINEMERGE = True)
  • 기준: 이전 라인의 타임스탬프 존재 여부 등
  • 성능을 위해 Best Practice → 가능하면 SHOULD_LINEMERGE = False + 적절한 Line Breaker

5. Typing 단계

  • 이벤트 내용을 변형하거나 필드 생성

(1) Regex Replacement

  • _raw 변환, _meta 데이터(host, sourcetype, index) 수정
  • 개인 정보 마스킹 가능 (SEDCMD)

(2) 실행 순서

  • props.conf에서 TRANSFORMS 지정 → transforms.conf 실행
  • 여러 변환이 있으면 순차적 적용 (우선순위 = 사전순 or TRANSFORMS-0/-1 순서)

(3) Annotator

  • 이벤트의 구두점 패턴(punct)을 인덱싱
  • 유사 이벤트 빠른 분류/검색에 활용
더보기

Typing: Annotator 자세히

무엇을 하는가?

  • 목적: 이벤트의 구두점 패턴( punctutation pattern ) 을 식별해서, 형태가 비슷한 이벤트를 빠르게 묶거나 걸러내도록 도와줍니다.
  • 동작: ANNOTATE_PUNCT = true 로 설정하면, Splunk는 각 이벤트에 대해 특수 토큰 punct::<서명>인덱스 시점에 추가로 색인합니다. 이 토큰은 이벤트 본문에서 영문자/숫자를 제거하고, 남은 공백을 _ 로 치환해 만든 구두점 서명(signature) 입니다.

예시

 
_raw: Sep 12 06:11:58 abath-mba13.no.cox.net storeagent[49597] <Critical>: Starting update scan
punct 서명(예): __:__:_._.__.__.___[____]_<______>:_ ________ ______ ____
  • 핵심은 문자/숫자 등 변수값을 걷어내고, []<>:"- 같은 구두점 배치만 남겨 “이 이벤트의 형태”를 표현한다는 점입니다. 같은 형태의 로그라면 내용이 달라도 같은 punct:: 서명을 갖습니다.

왜 유용한가?

  • 패턴 기반 필터링/그룹화: 같은 템플릿(형태)의 로그를 한 번에 모을 수 있습니다. 예를 들어 메시지 텍스트 안의 사용자명, ID, 숫자 등이 달라도 같은 형태라면 같은 punct:: 로 필터링 가능.
  • 희귀 패턴 탐지(이상치): 평소와 다른 구두점 패턴이 나타나면 스키마 드리프트비정상 포맷(예: 인젝션 시도) 을 빠르게 의심할 수 있습니다.
  • 소음 제거: 단어가 다양한데 형태는 같은 잡음성 이벤트를 뭉뚱그려 보기에 편합니다.

어떻게 켜나? (index-time 설정)

props.conf (해당 sourcetype 또는 source/host 범위)

 
 
# props.conf
[my_sourcetype]
ANNOTATE_PUNCT = true   # 기본값 false. true면 punct:: 서명을 색인함
  • 배포 위치: 인덱싱이 실제로 이뤄지는 곳(인덱서 또는 인덱싱을 수행하는 Heavy Forwarder)에 배포해야 효과가 납니다. Search Head에만 두면 의미가 없습니다.
  • 비용: 이벤트당 punct:: 토큰 1개가 추가로 색인되므로 TSIDX가 약간 증가할 수 있습니다(원문도 “특수 토큰을 인덱스한다”는 수준의 설명). 일반적으로 오버헤드는 매우 작습니다.

어떻게 검색하나? (실전 팁)

1) 특정 형태만 빠르게 필터링

  • punct::<서명> 을 검색어로 직접 사용할 수 있습니다. (이 토큰은 “필드=값” 형태의 인덱스된 검색어(term) 이며, 일반 필드처럼 사이드바에 뜨지 않을 수 있습니다.)
 
index=app_logs punct::"__:_-..._[]_<>:___"

 

위처럼 기대하는 서명만 통과시켜 형태가 같은 이벤트만 모읍니다.

2) “형태가 다른 것”만 보고 싶을 때(이상 탐지)

  • 운영상 정상 형태 몇 가지에 대해 eventtype 또는 macro로 미리 정의(각각의 punct:: 서명 사용)해 두고, NOT 조건으로 제외:
 
index=app_logs NOT ( punct::"<정상서명1>" OR punct::"<정상서명2>" OR punct::"<정상서명3>" )

남는 건 처음 보는 형태—로그 포맷 변경, 오류 페이지, 공격 패턴 등을 빠르게 포착.

3) 서명을 “값으로” 묶어 집계하고 싶을 때

  • punct:: 는 토큰이라 stats by punct 처럼 바로는 못 씁니다.
    분석용으로는 검색 시 구두점 서명 재생성 필드를 하나 만들어 그룹화하세요:
 
index=app_logs
| eval punct_sig = replace(_raw, "[A-Za-z0-9]+", "")    /* 영숫자 제거 */
| eval punct_sig = replace(punct_sig, "\s+", "_")       /* 공백 -> _ */
| stats count by punct_sig
| sort -count

인덱스 단계의 알고리즘과 100% 동일하다고 보장하긴 어렵지만, 실전 집계/탐색에는 충분히 유용합니다.


언제/어디에 특히 효과적인가?

  • JSON/구조화 로그 스키마 변화 탐지: 중괄호·콜론·쉼표 위치가 달라지면 다른 punct 가 됩니다 → 스키마 드리프트 조기 경보.
  • 에러 템플릿 분류: 메시지 안의 변수(ID·경로·숫자)가 달라도 에러 템플릿 형태로 묶여 원인/빈도 파악이 쉬움.
  • 입력값 인젝션/이상한 문자열: 따옴표, 괄호, 세미콜론 등 특정 구두점 조합이 튀면 빠르게 스팟팅.

주의/한계 & 베스트 프랙티스

  • 과도한 일반화: 구두점이 빈약한 소스(평문 문장)나, 반대로 구두점이 지나치게 많은 소스는 구분력이 떨어질 수 있습니다.
  • JSON 대량 환경: 많은 sourcetype이 유사한 JSON 형식을 쓰면 punct 가 서로 비슷해집니다. 이 경우 소스별로 분리하거나, 키 일부 제거/정규화와 병행하세요.
  • 성능/용량: 인덱스 토큰 1개 추가 수준이라 보통 안전하지만, 초대용량 환경에선 적용 대상을 핵심 sourcetype 위주로 선택하세요.
  • 운영 배포: props 변경은 인덱서(또는 HWF) 에 배포. 클러스터면 Cluster Master(Deployer가 아님) 를 통해 peer에 배포하는 일반 절차를 따르세요.

한 줄 요약

ANNOTATE_PUNCT = true → 이벤트의 구두점 서명을 punct:: 토큰으로 인덱스.
같은 형태의 로그를 빨리 묶고, 이상한 형태를 빠르게 포착하는 데 큰 도움이 됩니다.


6. Indexing 단계

  • 이벤트를 실제 인덱스에 저장하거나 다른 곳으로 전달

(1) TCP Out

  • 데이터를 다른 Splunk 인스턴스로 TCP 전송
  • outputs.conf에서 tcpout 그룹 지정
  • 네트워크 문제 발생 시 자동으로 다른 인덱서로 failover

(2) Syslog Out

  • Heavy Forwarder → Syslog 서버로 RFC 3164 규격 이벤트 전송
  • 주로 타 SIEM 교체·마이그레이션 시 사용

(3) Indexer

  • 데이터를 이벤트로 변환해 인덱스에 기록
  • 내부 데이터는 사전 구성된 인덱스에, 외부 데이터는 기본 인덱스(설정하지 않는 경우, main)에 기록
  • 필요 시 새로운 인덱스 생성 가능
더보기

📘 Indexing: Indexer (구체적 설명)

1. Indexer의 역할

  • 데이터 수신 → 이벤트로 변환 → 인덱스에 저장
  • Splunk Enterprise에서 검색 속도데이터 보관을 책임지는 핵심 컴포넌트

2. 내부 데이터 (Internal Indexes)

Splunk 자체가 동작하면서 만들어내는 로그/메타데이터는 자동으로 내부 인덱스에 기록됩니다.

대표적인 내부 인덱스들:

  • _internal : Splunk 자체 로그 (검색 로그, 에러 로그, 리소스 사용량 등)
  • _audit : 사용자 로그인, 검색 실행, 권한 변경 등 보안/감사 로그
  • _introspection : 시스템 리소스 사용량(CPU, 메모리, Disk I/O 등)
  • _telemetry, _metrics 등 : 성능, 모니터링용 데이터

👉 즉, 별도로 설정하지 않아도 Splunk는 자기 자신을 관찰하기 위해 여러 인덱스를 운영합니다.


3. 외부 데이터 (User Data)

  • 우리가 실제로 로그 소스(방화벽, 서버, 앱, 보안 장비 등) 에서 수집해 넣는 데이터
  • 별도 지정하지 않으면 기본 인덱스(default) 에 들어갑니다.
    • 예: index=default

4. 추가 인덱스 생성

실무에서는 대부분 새로운 인덱스를 만듭니다.
이유:

  1. 데이터 분리 관리: 보안 로그, 시스템 로그, 애플리케이션 로그 등을 따로 저장
  2. 권한 제어: 특정 팀만 볼 수 있도록 인덱스 단위 접근제어(Role 기반 RBAC)
  3. 보존 기간 설정: 인덱스마다 보존 기간(frozenTimePeriodInSecs)을 다르게 설정
    • 보안 로그: 1년
    • 웹 서버 로그: 90일
    • 테스트 로그: 7일

예시 (indexes.conf):

 
[security_logs]
homePath   = $SPLUNK_DB/security_logs/db
coldPath   = $SPLUNK_DB/security_logs/colddb
thawedPath = $SPLUNK_DB/security_logs/thaweddb
frozenTimePeriodInSecs = 31536000   # 365일 보존

[web_logs]
homePath   = $SPLUNK_DB/web_logs/db
coldPath   = $SPLUNK_DB/web_logs/colddb
thawedPath = $SPLUNK_DB/web_logs/thaweddb
frozenTimePeriodInSecs = 7776000    # 90일 보존

5. 데이터 흐름 요약

  1. Forwarder → Indexer
    데이터가 포워더에서 인덱서로 전달됨
  2. Indexer → Parsing/Indexing Pipeline
    인코딩, Line Breaker, Timestamp 추출, 필드 할당
  3. 저장 위치
    • 내부 운영 데이터 → _internal, _audit 등
    • 외부 수집 데이터 → default (기본), 혹은 indexes.conf에서 정의한 사용자 지정 인덱스

✅ 정리

  • Indexer는 Splunk에서 실제 데이터를 보관하는 창고 역할
  • 내부 데이터는 _internal, _audit 등 미리 준비된 인덱스에 자동 저장
  • 외부 데이터는 기본 인덱스(default) 또는 관리자가 만든 커스텀 인덱스에 저장
  • 인덱스를 나누는 이유는 권한, 보존 기간, 성능 관리 때문

7. 효율적인 인덱싱을 위한 설정

  • sourcetype별로 꼭 조정해야 할 주요 8가지 설정 (props.conf)
    1. EVENT_BREAKER
    2. EVENT_BREAKER_ENABLE
    3. TIME_PREFIX
    4. TIME_FORMAT
    5. MAX_TIMESTAMP_LOOKAHEAD
    6. LINE_BREAKER
    7. SHOULD_LINEMERGE
    8. TRUNCATE

✅ 핵심 요약

  • 이벤트 처리는 Parsing → Indexing 두 단계로 진행됨
  • Parsing: UTF-8 인코딩, Line Breaker, 타임스탬프 추출
  • Merging: 잘린 이벤트 병합 (성능상 가급적 피하는 편이 좋음)
  • Typing: 정규식 기반 변환, 메타데이터 수정, 이벤트 패턴화
  • Indexing: 인덱스에 저장 or 다른 인스턴스/서버로 전달
  • 효율적인 인덱싱을 위해 sourcetype별 파라미터 최적화 필요
728x90
반응형