학습 목표
Logstash가 input → filter → output 파이프라인으로 수집·변환·전달하는 중앙 transform 역할을 설명할 수 있다.
Beats input(5044)으로 Filebeat와 연동하는 구성을 설명할 수 있다.
grok으로 비구조 로그를 필드로 분리하고 date·mutate로 정리할 수 있다.
multiline codec으로 스택 트레이스를 한 event로 합치는 패턴을 설명할 수 있다.
Logstash filter vs ingest pipeline 선택 기준을 말할 수 있다.
문제 상황
- Filebeat가 ES에 그대로 넣는데 Nginx access log가 한 줄 문자열 —
status·url.path로 집계 불가 - grok 패턴 한 줄 고치려고 Logstash 전체 재시작 — 파이프라인 파일·배포 구조 없음
- Java stack trace가 줄마다 document로 쪼개짐 — multiline·codec 미설정
@timestamp가 수집 시각이라 장애 구간 검색이 어긋남 — date filter 없음- ES 장애 시 Filebeat만 두면 백프레셔가 호스트까지 — 버퍼·중앙 LS 필요
- 6편에서 Beat output.logstash를 봤지만 LS 안에서 무엇을 하는지 비어 있음
- ingest pipeline(8편)과 둘 다 transform인데 어디에 둘지 팀마다 다름
앞 편에서 Beats로 source까지 수집했다. 이번 편은 Logstash로 파싱·enrich·라우팅. ingest pipeline 심화는 8편, data stream은 9편이다.
1. Logstash란?
Logstash — JVM 기반 데이터 파이프라인 엔진. 다양한 input에서 event를 받아 filter로 가공한 뒤 output으로 보낸다.

| 단계 | 역할 | 예시 plugin |
|---|---|---|
| input | event 수신 | beats, tcp, kafka, file |
| filter | 파싱·변환·조건 분기 | grok, json, date, mutate |
| output | 목적지 전송 | elasticsearch, kafka, stdout |
- event — HashMap 형태 필드 묶음 (
message,@timestamp,host…) - pipeline —
logstash.yml+*.conf(또는 pipelines.yml 다중) - worker — filter·output 병렬 처리 — CPU 코어에 맞게 조정
- persistent queue (PQ) — 디스크 버퍼로 ES 장애 시 유실 완화
Filebeat ──► beats input :5044
│
filter (grok · date · mutate)
│
elasticsearch output
│
Elasticsearch
2. Beats와 연동
6편 output.logstash의 반대편이 Logstash beats input이다.

# code/logstash.pipeline.conf (input 발췌)
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/logstash/certs/logstash.crt"
ssl_key => "/etc/logstash/certs/logstash.key"
}
}
| 항목 | 설명 |
|---|---|
| 포트 | 기본 5044 (Beats ↔ Logstash 표준) |
| TLS | prod는 ssl 권장 — 평문은 내부망만 |
| metadata | Beat가 넣은 fields·agent·host가 event에 합쳐짐 |
| backpressure | LS가 느리면 Beat가 대기 — 6편 registry와 별개 |
# Filebeat 쪽 (6편 연계)
output.logstash:
hosts: ["logstash.internal:5044"]
ssl.certificate_authorities: ["/etc/filebeat/ca.crt"]
- 여러 Beat → 한 Logstash 풀 — filter 한 곳에서 grok·enrich
- 수평 확장 — Logstash 인스턴스 여러 대 + LB(또는 Kafka input으로 버퍼)
- Elastic Cloud — LS는 self-hosted·ECK·Elastic Cloud deployment 외부 또는 integration 경로 검토 (16편)
3. Filter — grok
grok — 정규식·pattern으로 message를 명명 필드로 분리.

# code/grok-nginx.example.conf (발췌)
filter {
if [fields][log_type] == "nginx-access" {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
tag_on_failure => ["_grokparsefailure"]
}
mutate {
rename => { "clientip" => "[source][ip]" }
}
}
}
| 개념 | 설명 |
|---|---|
| pattern | %{COMBINEDAPACHELOG} 등 내장·커스텀 |
| match | 필드별 여러 패턴 시도 가능 |
| tag_on_failure | 실패 시 tag — Kibana에서 미파싱 추적 |
| _grokparsefailure | 실패 document 별도 모니터링 |
- 3편 mapping — grok 결과 필드는 keyword·ip·long 등 타입 맞춰야 집계 가능
- COMBINEDAPACHELOG — Nginx·Apache access 표준 — 6편 module과 필드명 맞출지 결정
- Grok Debugger — Kibana Dev Tools 또는 standalone으로 패턴 검증
json filter
구조화 JSON 로그는 grok 대신 json이 단순하다.
filter {
if [service] == "order-api" {
json {
source => "message"
target => "parsed"
}
}
}
- 6편 json.keys_under_root (Filebeat) vs LS json filter — 한쪽만 쓰는 편이 디버깅 쉬움
- 중첩 JSON —
target으로 namespace 분리 후 mutate rename
4. date·mutate
| plugin | 용도 |
|---|---|
| date | 로그 내장 시각 → @timestamp |
| mutate | rename, remove_field, convert |
| geoip | IP → geo 필드 |
| useragent | UA 문자열 → browser·os |
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z", "ISO8601" ]
target => "@timestamp"
}
mutate {
remove_field => [ "message", "timestamp" ]
convert => { "response" => "integer" }
}
@timestamp— 4편 range·5편 date histogram의 기준 — 수집 시각과 이벤트 시각 구분- remove_field — 파싱 후 원본
message제거 시 디스크 절약 — 디버그 시에는 유지 - convert — 문자열 status
"200"→ integer — mapping long과 일치
5. Multiline과 codec
한 event가 여러 줄일 때 — 스택 트레이스·멀티라인 로그.

# code/multiline.codec.example.conf (발췌)
input {
file {
path => "/var/log/order-api/app.log"
codec => multiline {
pattern => "^\d{4}-\d{2}-\d{2}T"
negate => true
what => "previous"
}
}
}
| 옵션 | 의미 |
|---|---|
| pattern | 새 event 시작 줄 정규식 |
| negate | true면 pattern 아닌 줄을 이전에 붙임 |
| what | previous — 위 줄에 합침 / next — 아래 |
| codec | input 단계에서 줄 병합 — filter 전 |
- 6편 Filebeat multiline — 호스트에서 합치기 vs LS codec — 중앙에서 합치기
- Beats 경로 — Filebeat
multiline권장이 많음 — LS 부하·네트워크 줄 수 감소 - 파일 직접 file input — Beat 없이 LS만 쓸 때 codec 필수
6. Output — Elasticsearch
# code/logstash.pipeline.conf (output 발췌)
output {
if "_grokparsefailure" in [tags] {
elasticsearch {
hosts => ["https://es.example.com:9243"]
index => "logs-deadletter-%{+YYYY.MM.dd}"
api_key => "${ES_API_KEY}"
}
} else {
elasticsearch {
hosts => ["https://es.example.com:9243"]
index => "logs-%{[service]}-%{+YYYY.MM.dd}"
api_key => "${ES_API_KEY}"
}
}
}
| 옵션 | 설명 |
|---|---|
| index | 일별 logs-%{+YYYY.MM.dd} — 9편 data stream 전환 검토 |
| pipeline | ES ingest pipeline ID 지정 — LS filter 이후 추가 가공 |
| manage_template | LS가 template 생성 — prod는 14편 template Git 관리 권장 |
- 조건부 output —
if [type]·tags로 index 분리·dead letter - bulk — output이 내부적으로 batch —
flush_size·idle_flush_time튜닝 - ES down — retry + PQ — 그래도 디스크 한계·drop 정책 필요
7. Logstash vs Ingest Pipeline
| Logstash filter | Ingest pipeline (8편) | |
|---|---|---|
| 실행 위치 | 별도 JVM | Elasticsearch 내부 |
| 부하 | LS 클러스터 스케일 | ES ingest 노드 CPU |
| 버퍼 | PQ·Kafka input | ES queue |
| 적합 | heavy grok, 다중 sink, 외부 API enrich | 단순 공통 파싱, Beat→ES 직결 |
| 배포 | LS 설정 배포 | _ingest/pipeline API |
- 둘 다 쓰지 말 것 — 같은 grok을 LS와 ingest에 중복하면 디버깅 지옥
- 흔한 분담 — LS: 소스별 grok·라우팅 / ingest: 공통 geoip·drop·rename
- 신규 스택 — JSON 로그 + ingest만으로 시작 — 복잡해지면 LS 추가
8. 실무 체크리스트
| # | 질문 |
|---|---|
| 1 | grok 실패 tag(_grokparsefailure) 모니터링하는가 |
| 2 | @timestamp가 이벤트 시각인가, date filter가 있는가 |
| 3 | multiline을 Filebeat vs Logstash 중 어디서 하는지 문서화됐는가 |
| 4 | pipeline 설정이 Git·IaC로 버전 관리되는가 |
| 5 | LS PQ·디스크·heap이 ES 장애 시 버틸 만큼 있는가 |
| 6 | output index·mapping이 3편·14편 template과 맞는가 |
정리
- Logstash — input · filter · output 파이프라인, 중앙 transform
- beats input — Filebeat 5044, TLS·backpressure 고려
- grok · json · date · mutate — 비구조 로그 → 검색·집계 가능 필드
- multiline codec — 여러 줄을 한 event로 (Filebeat multiline과 역할 분담)
- ingest pipeline과 중복 없이 역할 분리
다음에 다룰 것
- Ingest Pipeline
- processor chain, enrich, failure handling
해당 내용은 Elastic Logstash Reference (Pipeline, Plugins, Grok, Codec) 를 기반으로 합니다.
'ELK & Elastic Cloud' 카테고리의 다른 글
| Ingest Pipeline (0) | 2026.07.17 |
|---|---|
| Beats (0) | 2026.07.11 |
| Aggregation과 클러스터 (0) | 2026.07.08 |
| Query DSL (0) | 2026.07.05 |
| Mapping과 Analyzer (0) | 2026.07.03 |