본 문서는 2025년 12월 30일 기준으로 작성되었습니다.
Elasticsearch 9.2.0, Kibana 9.2.0, Logstash 9.2.0 버전을 기준으로 기술하였습니다.
엘라스틱서치를 사용하다보면 분명히 잘 구성한 것 같은데 데이터가 안들어오는 경우가 있습니다. 원인을 찾으려 엘라스틱서치의 로그를 뒤지고, 설정을 다시 확인해보지만 잘못된게 없는것 같습니다. 특히, 오류 문구도 안보이면서 데이터가 안들어올 땐 미치고 팔짝 뛸 노릇입니다. 이러한 경우는 Ingest Pipeline을 사용할 때 더욱 두드러집니다. 분명 Ingest Pipeline 내에서 Simulate는 문제가 없는데, 도대체 왜 적용하면 데이터가 안들어오는 것인가? 필자도 엔지니어로서 일하며 이러한 경우를 많이 겪었으며, 필자가 겪었던 Ingest Pipeline에서의 이슈와 해결을 위한 트러블슈팅 과정 하나를 정리해 공유하여 또 다른 희생양이 나오지 않길 바라는 마음으로 포스팅을 작성합니다.
필자는 테스트를 위해 CSV 파일을 로그스태시로 읽어 엘라스틱서치로 전송해보려 했습니다. CSV는 다음과 같이 간단한 형식입니다.
timestamp,host.name,client.ip,log.level,message,service.name
2025-12-31T06:50:00Z,win-lab-01,203.0.113.10,INFO,CSV ingest test message 1,web
2025-12-31T06:51:00Z,win-lab-01,203.0.113.11,WARN,CSV ingest test message 2,web
2025-12-31T06:52:00Z,win-lab-02,198.51.100.22,ERROR,CSV ingest test message 3,api
위의 CSV 데이터를 넣기 위해, 사전에 로그스태시에서 사용할 API Key를 생성하였습니다. 인덱스에 대해 모든 권한을 주었습니다.
API Key를 복사해둡니다.
logstash conf 파일을 만들어 CSV 파일을 엘라스틱서치에 적재합니다. (첫 헤더를 스킵하는 것이나, 뉴라인 제거, date 프로세서 파싱 등이 있으나 이 포스팅에서 다루는 내용이 아니므로 크게 상관하지 않아도 됩니다.)
input {
file {
path => "C:/logs-test.csv"
start_position => "beginning"
sincedb_path => "NUL"
mode => "read"
}
}
filter {
mutate {
gsub => ["message", "\r", ""]
}
if [message] =~ /^\uFEFF?(@timestamp|timestamp),/ {
drop { }
}
csv {
source => "message"
separator => ","
columns => ["timestamp","host.name","client.ip","log.level","message","service.name"]
skip_header => true
}
date {
match => ["timestamp", "ISO8601"]
target => "@timestamp"
}
mutate {
remove_field => ["timestamp"]
}
}
output {
elasticsearch {
hosts => ["https://URL:9200"]
api_key => "APIKEY=="
ssl_verification_mode => "none"
data_stream => true
data_stream_type => "logs"
data_stream_dataset => "test-csv"
data_stream_namespace => "default"
}
stdout {
codec => rubydebug
}
}
Discover를 보면, logstash로부터 CSV 문서 세 건이 잘 들어오는 것을 확인할 수 있습니다.
이제, 들어오는 도큐먼트를 Ingest Pipeline 단에서 조건에 따라 다른 인덱스로 보내려 합니다. log.level이 ERROR면 logs-error-csv로 보내볼것입니다. 먼저 파이프라인이 포함된 Data Stream을 만듭니다. Index pattern은 logs-test-csv*로, Priority는 높여서 500으로, Default pipeline을 logs-test-csv로, Data Stream 모드를 Yes로 하여 생성합니다.
그리고, logs-test-csv라는 파이프라인을 만든 뒤, log.level이 ERROR일 경우 logs-error-csv로 보내도록 Reroute 프로세서를 만듭니다. 이렇게 된다면 log.level이 INFO, WARN인 두개의 도큐먼트는 그대로 logs-test-csv에 남고, log.level이 ERROR인 하나의 도큐먼트는 logs-error-csv 인덱스에 적재될 것입니다.
Ingest Pipeline이 정상작동할지는 simulate를 통해 미리 테스트 할 수 있습니다. 기존의 log.level이 ERROR인 도큐먼트를 복사해 simulate를 돌려봅니다. 그러자 index가 logs-error-csv로 간다고 시뮬레이팅 결과가 나옵니다.
이 상태로, 다시 한번 로그스태시로 적재를 시도합니다. 그러자 logs-test-csv 에는 두개의 도큐먼트만 들어왔습니다. 총 세 개 중에 ERROR는 하나니까 당연한거겠죠? 그럼 하나는 logs-error-csv에 있을겁니다.
그런데 logs-error-csv로 안갑니다. 심지어 logs-error-csv는 생기지도 않았습니다. 분명 ingest pipeline에서 돌린 시뮬레이션에서는 잘 되어놓고 어째서? 라는 생각이 듭니다.
적재 과정에 오류가 있다면 로그스태시에 로그가 뜰거라는 생각이 들었습니다. 그러나 로그스태시의 로그에는 에러 로그가 없습니다. 모두 INFO 레벨이며 그 내용도 평이합니다. 우리는 에러로그를 찾을 수 가 없습니다.
이유를 아시겠나요? 만약 이유를 눈치채셨다면 당신은 정말 훌륭한 엔지니어입니다. 필자는 범부이므로 이를 찾는데에 고생을 하였습니다. 에러 로그조차 안뜨니까요. 원인은, 가장 처음에 있었습니다. 바로 API key 입니다.
그렇습니다. 로그스태시와 엘라스틱서치 간의 통신을 위해 발급했던 API Key. API Key의 의미에 맞게 올바르게 사용하기 위해서는, 사용 범위를 제한하는 것이 일반적입니다. 필자 역시, logs-test-* 인덱스에 대해서만 권한을 주었습니다. 그러나 reroute는 logs-error-csv로 향합니다. API Key에 있던 인덱스 패턴과는 맞지 않던 것입니다. 그래서 파이프라인 내에서 해당 인덱스로 보내려하니 권한이 없었고, log.level이 ERROR인 도큐먼트는 그대로 증발한 것입니다.
이는 로그스태시에서 에러가 안뜬것도 설명이 됩니다. 로그스태시는 이미 데이터를 보냈고, ingest pipeline은 엘라스틱서치의 영역입니다. 만약 로그스태시에서 전처리를 통해 logs-error-csv로 보내려 했다면 에러가 발생했을 것입니다.
마찬가지로 Ingest pipeline UI에서 simulate를 했을 때 잘 가는것처럼 보인것도 설명이 됩니다. ingest pipeline은 실제로 보내는것도 아닐 뿐더러, 권한을 신경 쓰지 않고 결과를 예상해 돌려주니까요. 말 그대로 시뮬레이션이지 진짜가 아니기 때문에 발생한 이슈였습니다.
API key에 logs-error-*을 추가해 로그스태시로부터 오는 도큐먼트가 logs-error-* 인덱스에 적재될 권한을 줍니다.
그러자 마침내 log.level이 ERROR인 도큐먼트 하나가 logs-error-csv 데이터스트림에 잘 적재가 됩니다. 이 때는 미리 인덱스 탬플릿으로 데이터 스트림으로 생성되게 해두었기 때문에 데이터스트림으로 생성된 것입니다. 포스팅 과정은 짧습니다. 하지만 트러블슈팅을 하는 과정은 깁니다. 모든 엔지니어들이 공감할 것입니다. 트러블슈팅은 길고, 그 결과로 파악한 원인을 설명하는 것은 아주 간단합니다. API Key의 권한 문제였습니다.
어찌보면 당연하고 간단한 문제이지만, 로그가 나오지 않는다는 점에서 파악하기 어려운 이슈였습니다. 로그스태시로부터 들어온 도큐먼트들에 대해 다른 인덱스로 적재될 권한이 없다면, 로그스태시에 표기가 되는게 맞지 않나 하는 생각이 듭니다. 물론 failure 처리를 잘 하면 되겠지만, ingest pipeline을 사용하다보면 어쩔 때는 failure에도 안뜨는 경우도 있습니다. 오늘도 에러, 로그와 싸우는 엔지니어들에게 응원의 말을 보내며, 누군가에게 도움이 되었길 바라는 마음으로 포스팅을 마칩니다.