다소 복잡하고 귀찮은 데이터 전처리 과정을 별도의 애플리케이션 작성 없이 비교적 간단한 설정만으로 수행할 수 있음
데이터를 저장하기 전에 사용자가 원하는 형태로 변경할 수 있는 강력한 기능을 제공
데이터 수집(비츠/데이터) -> 데이터가공/변환(로그스태시) -> 데이터 저장(엘라스틱서치) -> 분석&시각화(키바나)
로그스태시 특징
파이프라인을 구성하는 각 요소들은 전부 플로그인 형태로 만들어져 있음
모든 형태(JSON, XML등)의 데이터 처리
자체적으로 내장되어 있는 메모리와 파일 기반의 큐를 사용하므로 처리 속도와 안정성이 높음
엘라스틱서치의 장애 상황에 대응하기 위해 재시도 로직이나 오류가 발생한 도큐먼트를 따로 보과나는 데드 레터 큐를 내장하고 있음
6.2 로그스태시 실행
커맨드라인에서 다음 명령으로 실행
./bin/logstash -e "input {stdin { } } output { stdout { } }"
로그스태시를 실행하기 위해서는 반드시 파이프라인 설정이 필요함
일반적으로 파이프라인은 따로 설정 파일을 만들어서 기록하거나 config 폴더의 pipelines.yml에 기록하는데, -e 옵션을 사용하면 콘솔에서 직접 파이프라인을 설정할 수 있음
위 명령에 적은 파이프라인은 운영체제의 표준 입력(stdin)으로 전달받은 메시지를 다시 표준 출력(stdout) 으로 표시함
./bin/logstash -e "input {stdin { } } output { stdout { } }" --log.level error
--log.level error는 로그 중 error 레벨 미만의 로그는 감추는 설정
로그스태시에 제공하는 로그 레벨은 다음과 같음
fatal
error
warn
info
debug
trace
error 로그 레벨은 스크린샷이 길어지는 것을 막기 위해 추가한 옵션
6.3 파이프라인
파이프라인은 데이터를 입력받아 실시간으로 변경하고 이를 다른 시스템에 전달하는 역할을 하는 로그스태시의 핵심 기능
입력, 필터, 출력이라는 세 가지 구성요소로 이뤄짐
입력과 출력은 필수 구성요소이고, 필터는 옵션
파이프라인 실행 순서
데이터 소스 -> 로그스태시 파이프라인(입력->필터->출력) -> 엘라스틱서치
로그스태시가 입력, 필터, 출력 순으로 실행
입력은 소스로부터 데이터를 받아들이는 모듈
필터는 입력으로 들어오는 데이터를 원하는 형태로 가공하는 모듈
출력은 데이터를 외부로 전달하는 모듈
파이프라인에 입력과 출력은 반드시 포함돼야 하며 입력, 필터, 출력 각 단계에서 복수의 플러그인을 포함시킬 수 있음
로그스태시를 실행하고 'hello world'를 타이핑하면 모니터에 다음과 같이 출력됨
로그스태시는 JSON 형태로 데이터를 출력하는데, @version이나 @timestamp는 로그스태시가 만든 필드로 혹시 사용자가 만든 필드와 충돌이 날 것을 대비해 앞에 @ 기호가 붙어 있음
message, host 필드는 데이터와 시스템 사용자를 나타냄. 여기에는 @ 기호가 붙지 않았는데, @ 기호는 로그스태시에 의해 생성된 필드, 붙지 않은 필드는 수집을 통해 얻어진 정보라고 이해하자
간단한 파이프라인일 경우 방금처럼 콘솔에서 직접 작성할 수 있지만 작업의 이력 관리를 위해 pipelines.yml이나 파이프라인 설정 파일을 만들어 로그스태시를 동작하는 것이 좋음
파이프라인을 작성하는 기본 템플릿은 다음과 같다
input {
{ 입력 플러그인 }
}
filter {
{ 필터 플러그인 }
}
output {
{ 출력 플러그인 }
}
- 파이프라인 구성요소인 입력, 필터, 출력의 내부에 플러그인을 지정할 수 있음
- 용도나 형태에 맞춰 이미 만들어진 수많은 플러그인이 있기 때문에 필요한 기능을 지원하는 플러그인을 검색하여 템플릿에 추가하면 됨
## 6.3.1 입력
- 파이프라인의 가장 앞부분에 위치하며 소스 원본으로부터 데이터를 입력받은 단계
- 직접 대상에 접근해 읽어 들이는 경우도 있지만 서버를 열어놓고 받아들이는 형태의 구성도 가능
- 로그스태시 입력이 받아들일 수 있는 데이터 소스
- 파일, 통계, 웹, 데이터베이스, 스트림
- 다양한 형태의 데이터를 인식할 수 있고 이를 쉽게 처리하기 위해 다양한 입력 플러그인들이 존재
- ex) 특정 파일은 파일 플러그인을, 실시간 트윗은 트위터 플러그인을 통해 가져올 수 있음
> 자주 사용하는 입력 플러그인
입력 플러그인 | 설명
--| --
file | 리눅스의 tail -f 명령처럼 파일을 스트리밍하여 이벤트를 읽어 들임
syslog | 네트워크를 통해 전달되는 시스로그를 수신
kafka | 카프카의 토픽에서 데이터를 읽어 들임
jdbc | jdbc 드라이버로 지정한 일정마다 쿼리를 실행해 결과를 읽어 들임
- 로그스태시의 플러그인은 대부분 사용법이나 형태가 비슷하므로 파일 플러그인 사용법을 배워두면 다른 입력 플러그인 사용도 크게 어렵지 않음
## 실습
- 로그스태시가 설치된 config 폴더에 logstash-test.conf라는 파이프라인 설정 파일을 만들어 보자
- 확장자가 꼭 conf일 필요는 없음
- 파이프라인 설정 파일의 위치 역시 크게 중요하지는 않지만 가능하면 프로젝트끼리 묶어두는 것이 소스 관리 차원에서 좋음
- 이제 logstash-test.conf 파일에 파일 입력 플러그인을 적용해보자.
![image](https://user-images.githubusercontent.com/7028121/173599383-9e26c61d-5faa-4601-9d55-dade08df0c77.png)
- 필터 로그인을 사용하지 않음
- 입력으로는 파일 플러그인, 출력으로는 표준 출력을 사용
- 파일 플러그인에는 여러 옵션이 있는데 그중 path는 읽어들일 파일 위치를 결정
- elasticsearch.log 파일을 읽는 것으로 설정했는데, 파일에 로그가 쌓이면 실시간으로 elasticsearch.log 파일의 변경을 감지해 읽어 들임
- start_position은 최초 파일을 발견했을 때 파일을 읽을 위치로, 파일의 시작 부분부터 읽어들일지 끝부분부터 새로운 라인만 읽어들일지 정할 수 있음
- 출력은 표준 출력 플러그인을 사용했기 때문에 입력이 발생하면 모니터에 출력
- 실시간으로 출력되는 elasticsearch.log를 수집하기 위해 먼저 엘라스틱서치를 실행하고 로그스태시를 실행해보자.
`user@AL01978864 logstash-8.2.2 % ./bin/logstash -f ./conf/logstash-text.conf`
![image](https://user-images.githubusercontent.com/7028121/173616515-57c3cf2e-4cdc-4363-bd17-30da0f5c7072.png)
- -f 옵션은 설정 파일이나 폴더를 지정하는 옵션으로 방금 만들었던 logstash-test.conf를 파이프라인 설정에 사용하게 됨
- 입력 플러그인 경로에 적힌 elasticsearch.log 파일이 업데이트될 떄마다 출력 플러그인의 stdout(표준 출력)에 의해 모니터에 위 이미지 같은 로그들이 보이게 됨
- message에 적힌 구문을 분석해 의미 있는 데이터로 변환하는 역할을 필터 플러그인이 해야 하며 이는 로그스태시의 가장 중요한 업무라고 할 수 있음
## 6.3.2 필터
- 입력 플러그인이 받은 데이터를 의미 있는 데이터로 구조화하는 역할을 함
- 로그스태시 필터는 비정형 데이터를 정형화하고 데이터 분석을 위한 구조를 잡아줌
- 필터 역시 플러그인 형태이며 입력과 비슷하게 다양한 필터 플러그인이 존재함
> 자주 사용되는 필터 플러그인
필터 플러그인 | 설명
--| --
grok | grok 패턴을 사용해 메시지를 구조화된 형태로 분석. grok 패턴은 일반적인 정규식과 유사하나, 추가적으로 미리 정의된 패턴이나 필드 이름 설정, 데이터 타입 정의 등을 도와줌
dissect | 간단한 패턴을 사용해 메시지를 구조화된 형태로 분석한다. 정규식을 사용하지 않아 grok에 비해 자유도는 조금 떨어지지만 더 빠른 처리가 가능
mutate | 필드명을 변경하거나 문자열 처리 등 일반적인 가공 함수들을 제공
date | 문자열을 지정한 패턴의 날짜형으로 분석
## 실습
>filter-example.log
```text
user@AL01978864 log % cat filter-example.log
[2020-01-02 14:17] [ID1] 192.10.2.6 9500 [INFO] - connected.
[2020/01/02 14:19:25] [ID2] 218.25.32.70 1070 [warn] - busy server.
- add_field는 필드를 새로 만들어서 추가하는 옵션
- id라는 필드를 새로 생성하고 앞에서 split으로 분리되어 있는 message 필드의 배열 중에서 message[2] 의 데이터를 넣음
- remove_field 는 특정 필드를 삭제하는 옵션
- add_field와 remove_field는 mutate의 특별한 옵션은 아니고 모든 필터 플러그인에서 사용할 수 있는 옵션
> 필터 플러그인 공통 옵션
공통옵션 | 설명
--| --
add_field | 새로운 필드 추가
add_tag | 성공한 이벤트에 태그를 추가
enable_metric | 메트릭 로깅을 활성화하거나 비활성화할 수 있음. 기본적으로 활성화되어 있으며, 수집된 데이터는 로그스태시 모니터링에서 해당 필터의 성능을 분석할 때 사용
id | 플러그인의 아이디를 설정. 모니터링 시 아이디를 이용해 특정 플러그인을 쉽게 찾을 수 있음
remove_field | 필드 삭제
remove_tage | 성공한 이벤트에 붙은 태그를 제거
> mutate 플러그인의 split, add_field, remove_field 옵션 사용 결과
```text
{
"id" => "[ID1]",
"host" => {
"name" => "AL01978864.local"
},
"@timestamp" => 2022-06-14T16:32:11.702740Z,
"log" => {
"file" => {
"path" => "/Users/user/ELK/logstash/log/filter-example.log"
}
},
"event" => {
"original" => "[2020-01-02 14:17] [ID1] 192.10.2.6 9500 [INFO] - connected."
},
"@version" => "1"
}
{
"id" => "[ID2]",
"host" => {
"name" => "AL01978864.local"
},
"@timestamp" => 2022-06-14T16:32:11.776895Z,
"log" => {
"file" => {
"path" => "/Users/user/ELK/logstash/log/filter-example.log"
}
},
"event" => {
"original" => "[2020/01/02 14:19:25] [ID2] 218.25.32.70 1070 [warn] - busy server.."
},
"@version" => "1"
}
필터 플러그인은 순서대로 동작하는데 먼저 split에 의해 message 필드의 문자열이 공백을 기준으로 분리
다음으로 id 필드를 추가하고 필드값은 message[2]를 사용
마지막으로 message 필드가 사라짐
6.3.2.2 dissect를 이용한 문자열 파싱
dissect 플러그인은 패턴을 이용해 문자열을 분석하고 주요 정보를 필드로 추출하는 기능을 수행
표준 출력 플러그인에서 코덱을 따로명시하지 않으면 기본으로 rubydebug 코덱이 기본으로 사용됨
6.4 다중 파이프라인
하나의 로그스태시에서 여러 개의 파이프라인을 동작할 수 있음
하나의 파이프라인으로 다중 처리할 수도 있지만, 분기처리가 복잡해져 지저분해질 수 있어서 이럴 경우 다중 파이프라인을 작성하는게 좋다
6.4.1 다중 파이프라인 작성
다중 파이프라인은 하나의 로그스태시에서 여러 개의 파이프라인을 독립적으로 실행할 수 있게 함
다중 파이프라인 실행하는 법
먼저 pipelines.yml을 수정해야 한다.
pipelines.yml 파일은 config 폴더에서 찾을 수 있음
pieplines.yml에 주석으로 Example of two pieplines라고 적혀 있는 부분이 있는데 이 부분을 참고해 다음 내용을 추가하자.
pipeline.id는 다중 파이프라인의 고유한 아이디를 설정
path.config는 파이프라인 설정 파일의 위치
파이프라인 설정
설정
설명
pipeline.id
파이프라인의 고유한 아이디
path.config
파이프라인 설정 파일의 위치
pipeline.workers
필터와 출력을 병렬로 처리하기 위한 워커 수. 기본적으로 호스트의 CPU 코어 수와 동일하게 설정
pipeline.batch.size
입력 시 하나의 워커당 최대 몇 개까지의 이벤트를 동시에 처리할지를 결정. 배치 처리된 이벤트들은 엘라스틱서치 출력에서 하나의 벌크 요청으로 묶이기 때문에, 이 수치가 클수록 요청 수행 횟수가 줄어들어 인덱싱 성능 개선 효과가 있지만, 그만큼 단일 요청이 커지므로 1000, 2000과 같이 적당히 조절해가며 튜닝할 필요가 있음
queue.type
파이프라인에서 사용할 큐의 종류를 정할 수 있음. 기본적으로 memory 타입이 사용되나, persisted 타입을 선택해 이벤트의 유실을 좀 더 최소화할 수도 있음
6.1 로그스태시 소개
6.2 로그스태시 실행
./bin/logstash -e "input {stdin { } } output { stdout { } }"
./bin/logstash -e "input {stdin { } } output { stdout { } }" --log.level error
6.3 파이프라인
filter { { 필터 플러그인 } }
output { { 출력 플러그인 } }
output { stdout { } }
6.3.2.1 문자열 자르기
filter { mutate { split => { "message" => " " } add_field => { "id" => "%{[message][2]}" } remove_field => "message" } }
output { stdout { } }
6.3.2.2 dissect를 이용한 문자열 파싱
filter { dissect { mapping => {"message" => "[%{timestamp}] [%{id}] %{ip} %{port} [%{level}] - %{message}."} } }
output { stdout { } }
filter { dissect { mapping => {"message" => "[%{timestamp}]%{?->} [%{id}] %{ip} %{+ip} [%{?level}] - %{}."} } }
output { stdout { } }
grok을 이용한 문자열 파싱
자주 쓰는 로그스태시 패턴
filter { grok { pattern_definitions => { "MY_TIMESTAMP" => "%{YEAR}[/-]%{MONTHNUM}[/-]%{MONTHDAY}[/-][T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?" } match => { "message" => "[%{MY_TIMESTAMP:timestamp}] [ ]*[%{DATA:id}] %{IP:ip} %{NUMBER:port:int} [%{LOGLEVEL:level}] - %{DATA.msg}."} } }
output { stdout { } }
6.3.2.4 대소문자 변경
두 가지 필터 플러그인을 사용하고 있음
먼저 dissect 플러그인을 이용해 패턴에 맞춰 문자열을 자름
level 필드를 제외하고 나머지는 ?를 사용해 모두 무시
다음으로 mutate 플러그인의 uppercase 옵션을 통해 level 필드의 데이터를 모두 대문자로 변경
level 필드의 데이터가 warn에서 WARN으로 변경
lowercase는 uppercase와 반대
6.3.2.5 날짜/시간 문자열 분석
T
HH:mm:ss.SSSSSSZ, yyyy-MM-dd, epoch_millis)을 기본으로 사용dissect 플러그인으로 문자열을 자름
timestamp 필드만 제외하고 나머지 필드는 무시
mutate 플러그인의 strip 옵션은 선택한 필드의 양옆에 공백이 있을 경우 제거하는데, dissect에 의해 만들어진 timestamp 필드 좌우에 공백이 포함되어 있다면 제거됨
date 플러그인은 날짜/시간 관련된 데이터를 ISO8601 타입으로 일괄적으로 변경
match 옵션의 첫번째 값은 매칭할 필드명이고 이후 값들은 매칭할 날짜/시간 포맷
여기서는 timestamp 필드 중에서 YYYY-MM-DD HH:mm 포맷이거나 yyyy/MM/dd HH:mm:ss 포맷인 경우 매칭
target은 match에 의해 매칭된 필드가 저장될 새로운 필드를 의미하고, timezone은 원본 문자열에 타임존 정보가 포함되어 있지 않을 때 어떤 타임존으로 분석할지 설정
로그스태시는 타임존을 지정하지 않으면 로컬 PC의 타임존을 적용
이 경우 표준시간대와 맞지 않을 수 있으니 타임존을 UTC로 설정
로그스태시에서 사용하는 날짜/시간 포맷은 Joda Time 라이브러리 포맷을 사용
new_timestamp라는 새로운 필드가 생성되었고, 시간 포맷이 달랐던 두 데이터가 ISO8601 타입의 포맷으로 통일됨
6.3.2.6 조건문
filter { dissect { mapping => {"message" => "[%{timestamp}]%{?->}[%{id}] %{ip} %{port} [%{level}] - %{msg}."} } if [level] == "INFO" { drop { } } else if [level] == "warn" { mutate { remove_field => [ "ip", "port", "timestamp", "level" ] } } }
output { stdout { } }
6.3.3 출력
전체 출력 플러그인
6.3.4 코덱
output { stdout {} }
#
는 주석인데 한 번에 하나의 주석만 풀면서 파이프라인을 세번 실행해보자.6.4 다중 파이프라인
6.4.1 다중 파이프라인 작성
mypipe1.conf 파일을 작성해보자.
6.5 모니터링
6.5.1 API를 활용하는 방법
6.5.2 모니터링 기능 활성화
6.6 정리