ELK - 6

hoegon kim·2023년 4월 25일
0

ELK

목록 보기
6/10
post-thumbnail

6 로그스태쉬

로그스태쉬 : 로그를 저장한다.

로그 : 시스템에서 일련의 동작 과정을 기록하는 것으로 로그는 성능, 오류, 동작 과정 등의 중요한 정보를 담고 있다.

운영과정에서 문제 해결을 위해 반드시 필요하며 개발 과정에서도 테스트나 디버깅을 위해 필요한 정보다.

로그란 일반적으로 시스템 동작의 모든 행위나 이벤트를 기록하는데, 데이터가 중요해지는 빅데이터 시대에는 이런 로그 정보를 데이터 분석에 활용하기도 한다.


하지만 로그활용은 간단하지만은 않다.

  1. 로그 형태가 표준화되어 있지 않기 때문에 로그 생산자는 제각각 다양한 방법으로 로그를 생성하고 있다.

  2. 로그라는 것은 반전형 데이터(완벽하게 일치하지는 않더라도 어느 정도 형태가 있는 데이터) 이며 세상의 모든 것이 로그가 될수가 있기 때문에 로그 형태를 강제할 방법도 없다.

  3. 결국 로그를 수집하는 쪽에서 로그 형태를 분석하고 시스템에서 인식할 수 있도록 로그를 정제하는 작업이 필요한데, 로그스태시는 이 과정을 쉽고 편하게 할 수 있도록 지원한다.

  4. 어떤 형태의 로그에 대해서도 로그를 수집 - 가공 -전송하는 일련의 과정을 간편하게 구현하기 위한 강력한 기능까지 제공한다.


6.1 로그스태시 소개

로그스태시는 플러그인 기반의 오픈소스 데이터 처리 파이프라인 도구다.

복잡하고 귀찮은 데이터 전처리 과정을 별도의 애플리케이션 작성 없이
비교적 간단한 설정만으로 수행할 수 있다.

데이터를 저장하기 전에 사용자가 원하는 형태로 변경할 수 있는 강력한 기능을 제공한다.

또한 장애 대응 로직이나 성능 저하 요인을 쉽게 파악할 수 있는 모니터링 API, 간단한 조정으로 성능을 튜닝할 수 있는 파라미터들도 제공한다.

데이터 수집을 위해 별도의 애플리케이션 제작보다는 로그스태시 사용을 추천한다.

로그스태시 역할

비츠, 로그스태시, 엘라스틱서치, 키바나를 이용해 데이터를 수집 - 변환 - 저장 - 시각화하는 서비스를 구성할 때 로그스태시는 데이터를 저장하기 전에 원하는 형태로 가공하는 역할을 한다.

로그스태시는 비츠를 포함한 여러 소스 파일을 입력으로 받을 수 있고 데이터를 수정/삭제/추가해 엘라스틱서치나 다른 시스템으로 데이터를 전송할 수 있다.


6.1.1 로그스태시 특징

먼저 로그스태시의 특징을 알아보자.

플러그인 기반으로 확장성이 뛰어나고 현업에서 사용하는 대부분의 데이터 소스를 지원하고 있다.

  • 플러그인 기반

    • 로그스태시의 파이프라인을 구성하는 각 요소들은 전부 플러그인 형태로 만들어져 있다.

    • 기본으로 제공되는 플러그인 외에도 수많은 커뮤니티 플러그인을 찾을 수 있으며,

    • 정말 필요할 경우 비교적 간단한 코드로 전용 플러그인을 작성해 로그스태시의 다른 모든 장점을 가져가면서 고유한 로직을 포함시킬수도 있다.

    • 이를 위해 플러그인 개발을 위한 프레임워크를 포함하고 있고 플러그인을 관리할 수 있는 기능도 제공한다.

  • 모든 형태의 데이터 처리

    • 기본 제공되는 플러그인들의 조합만으로도 대다수의 데이터 소스에서 JSON, XML 등의 구조화된 텍스트뿐만 아니라 다양한 형태의 데이터를 입력받아 가공한 다음에 저장할 수 있다.

    • 특히 이벤트 데이터, 즉 시간에 따라 발생하는 데이터를 처리하는데 최적화 되어 있다.

    • 관계형 데이터베이스에서 데이터를 마이그레이션하거나 엘라스틱서치에 이미 저장된 도큐먼트들을 리인덱싱하는 등 시간과 무관하게 데이터를 처리하는 모든 작업에서도 유연하게 사용될 수 있다.

  • 성능

    • 자체적으로 내장되어 있는 메모리와 파일 기반의 큐를 사용하므로 처리 속도와 안정성이 높다.

    • 인덱싱할 도큐먼트의 수와 용량을 종합적으로 고려해 벌크 인덱싱을 수행할 뿐만 아니라 파이프라인 배치 크기 조정을 통해 병목현상을 방지하고 성능을 최적화할 수 있다.

  • 안정성

    • 엘라스틱서치의 장애 상황에 대응하기 위한 재시도 로직이나 오류가 발생한 도큐먼트를 따로 보관하는 데드 레터 큐를 내장하고 있다.

    • 파일 기반의 큐를 사용 할 경우 뜻하지 않은 로그스태시의 장애 상황에서도 도큐먼트 유실을 최소화 할 수 있다.


6.2 로그스태시 설치(도커)

설치이전에 설정환경 알아보기

> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
Codename:       jammy


> docker -v 
Docker version 23.0.2, build 569dd73

open-jdk 설치

  1. openjdk 목록확인하기
sudo apt list|grep openjdk 
  1. openjdk 설치하기
sudo apt-get update
sudo apt-get install openjdk-8-jdk

※ openjdk 삭제하기

$ sudo apt-get purge openjdk*
  1. java 버전 확인
java -version

logstash 설치

  1. 로그스태쉬 이미지 생성
sudo docker pull docker.elastic.co/logstash/logstash:8.6.2
  1. 로그스태쉬 컨테이너 생성 및 실행(최초실행시)
sudo docker run --name log01 -v ~/elasticsearch:/data --net elastic -d docker.elastic.co/logstash/logstash:8.6.2

로그스태쉬 데이터가 저장되는 폴더 경로는 elasticsearch:/data 이다.

  1. 네트워크에 로그스태쉬 컨테이너가 연동됐는지 확인하기
sudo docker network inspect elastic
  1. 로그스태쉬 vi 명령어로 파일 수정하기

4-1. 반드시 처음에 접근할시 root 계정으로 전환

sudo su 

4-2. 계정 전환 후 root 계정 install 비번 생성 하기

sudo docker exec -it --user root log01 bash
passwd root

4-3. 루트계정에서 install

apt-get update
apt-get install sudo
sudo apt-get install vim
  1. 로그스태쉬 내부 컨테이너 접속
sudo docker exec -it log01 bash

※ 컨테이너 빠져나오기 : exit

  1. 내부컨테이너 내에서 파일 수정 접근
vi /usr/share/logstash/pipeline/logstash.conf

  1. 실행하기
sudo docker run -it --rm docker.elastic.co/logstash/logstash:8.6.2 -e 'input { stdin { } } output { stdout { } }' --log.level error

6.3 파이프라인

로그스태쉬에서 가장 중요한 부분은 파이프라인이다.

파이프라인은 데이터를 입력 받아 실시간으로 변경하고 이를 다른 시스템에 전달하는 역할을 하는 로그스태시의 핵심 기능이다.

파이프라인은 입력, 필터, 출력 세가지 구성요소로 이루어진다.

입력 : 소스로부터 데이터를 받아들이는 모듈
필터 : 입력으로 들어오는 데이터를 원하는 형태로 가공하는 모듈
출력 : 데이터를 외부로 전달하는 모듈

6.3.1 입력

파이프라인의 가장 앞부분에 위치하며 소스 원본으로부터 데이터를 입력받는 단계다. 직접 대상에 접근해 읽어 들이는 경우도 있지만 서버를 열어놓고 받아들이는 형태의 구성도 가능하다.

다음 그림을 살펴보자.

입력플러그인의 종류에는

file, syslog, kafka, jabc 가있다.

  • file
    • 리눅스의 tail -f 명령처럼 파일을 스트리밍하며 이벤트를 읽어 들인다.
  • syslog
    • 네트워크를 통해 전달되는 시스로그를 수신한다.
  • kafka
    • 카프카의 토픽에서 데이터를 읽어 들인다.
  • jabc
    • JDBC 드라이버로 지정한 일정마다 쿼리를 실행해 결과를 읽어 들인다.

6.3.2 필터

입력플러그인이 받은 데이터를 의미 있는 데이터로 구조화 하는 역활을 한다. 필수 구성요소가 아니어서 필터 없이 파이프라인을 구성할 수 있지만, 필터 없는 파이프라인은 그 기능을 온전히 발휘하기 힘들다.

로그스태시 필터는 비정형 데이터를 정형화하고 데이터 분석을 위한 구조를 잡아준다. 비츠나 키바나 등에서 입력받은 데이터를 로그스태시 필터를 이용해 필요한 정보만 손쉽게 추출하거나 형태를 변환하고 부족한 정보는 추가하는 등 전반적인 데이터 정제/가공 작업을 수행할 수 있다.

로그스태시, 그중에서 필터는 데이터를 정형화하고 사용자가 필요한 데이터 형태로 가공하는데 핵심적인 역할을 한다.

필터 역시 플러그인 형태이며, 입력과 비슷하게 다양한 필터 플러그인이 존재한다.

전체 플러그인은 온라인 문서를 찾아보고, 여기서는 자주 사용하는 필터 프러그인들 위주로 알아보자


로그스태쉬 정적 파일 입력 받기

input{
	file{
    	path => 
        start_position => "beginning"
        sincedb_path => "nul"
    }
}


output{
	stdout{}
}

해당되는 로직은 filter-example.log 파일을 입력으로 받는 파이프라인 설정

start_position : 어디서 부터 읽을것인가

  • 처음부터 읽으면 : beginning
  • 끝부터 읽으면 : end
sincedb 데이터베이스 파일

sincedb 데이터베이스 파일은 파일을 어디까지 읽었는지 기록하는 파일이다. 앞에서 start_position이 파일을 어디서부터 읽을지 설정한다고 했다. beginning 은 파일의 처음부터 읽어오고, end는 파일의 끝에서 부터 읽어온다.

start_position은 파일을 불러들이는 최초에 한 번만 적용된다는 점이다.

6.3.2.1 문자열 자르기

데이터나 로그는 대부분의 길이가 길기 때문에 우리가 원하는 형태로 분리해야 한다. 필터 플러그인 중 문자열을 자르는 방법을 알아보자.

먼저 logstash-test.conf 파일에서 filter에 플러그인을 추가해보자.

input {
	file {
		path => "C:/logstash-7.10.1/config/fliter-example.log"
		start_positton => "beginning"
		sincedb_path => "nul"
		}
}

filter {
	mutate {
		split => { "message" => " " }
			}
}

output {
	stdout { }
}

mutate 플러그인은 필드를 변형하는 다양한 기능들을 제공하고 있다. 필드 이름을 바꾸거나 변경하거나 삭제하는 작업 등을 할 수 있다. mutate는 플러그인 내부에 옵션이 다양한데 split도 여러 옵션 중 하나다.

split 옵션은 구분자를 기준으로 데이터를 자를 수 있다. message라는 필드를 공백기준으로 ""으로 문자를 분리한다.

mutate는 많은 옵션이 있어서 순서가 중요한데, coerce -rename -update - replace - convert - gsub - uppercase - lowercase - capitalize - lowercase - strip - remove - split - join - merge - copy 순으로 옵션이 적용된다.

mutate 플러그인의 자세한 옵션은 온라인 문서에서 확인 가능하다.

split으로 잘라서 특정 인덱스값을 넣고싶을 경우
filter {
	mutate {
		split => { "message" => " " }
		add_field => { "id" => "%{[message][2]}" }
		remove_fteld => "message"
	}
}    

원하는 인덱스 넣으면됨 번호 %{[message][index_number]

필터 플러그인 공통 옵션

add_field : 새로운 필드를 추가할 수 있다.

add_tag : 성공한 이벤트에 태그를 추가할 수 있다.

enable_metric : 메트릭 로깅을 활성화하거나 비활성화 할 수 있다. 기본적으로 활성화되어 있으며, 수집된 데이터는 로그스태시 모니터링에서 해당 필터의 성능을 분석할 때 사용한다.

id : 플러그인의 아이디를 설정한다. 모니터링 시 아이디를 이용해 특정 플러그인을 쉽게 찾을 수 있다.

remove_field : 필드를 삭제할 수 있다.

remove_tag : 성공한 이벤트에 붙은 태그를 제거할 수 있다.

6.3.2.2 dissect를 이용한 문자열 파싱

mutate 플러그인의 split옵션을 이용해 문자열일 분리했지만 하나의 구분자만 이용해서 데이터를 나눠야 한다는 단점이 있다.

dissect 플러그인은 패턴을 이용해 문자열을 분석하고 주요 정보를 필드로 추출하는 기능을 수행한다.

공백을 표현하기 위해 ^ 기호를 사용했다.

단어간의 구분자 표기법

공백을 표현하기 위해 ^ 기호를 사용했다.

필드를 구분하는 구분자로는 '(공백)','-','[',']'가 있다.

%{?->}라고 입력하면 공백이 몇칸이든 하나의 공백으로 인식한다.

%{ip} %{+ip}을 작성하면 여러 개의 필드를 하나의 필드로 합쳐서 표현한다.

6.3.2.3 grok를 이용한 문자열 파싱

grok는 정규 표현식을 이용해 문자열을 파싱할 수 있다.

정규 표현식은 특정한 규칙을 갖는 문자열을 표현하는 언어다.

grok는 자주 사용하는 정규 표현식들을 패턴화 했뒀으며 패턴을 이용해 %{패턴:필드명} 형태로 데이터에서 특정 필드를 파싱할 수 있다.

grok는 기본적으로 %{패턴명:변수명} 형태로 작성하면 된다.
먼저 TIMESTAMP_ISO8601은 ISO8601 표준 시간 표기법9에 대한 패턴이다.

DATA는 모든 데이터를 인식하고,

IP는 IPv4 형태의 데이터(192.192.192.192)를 인식한다.

NUMBER는 숫자를 인식하는데, 변수명 뒤에 :int를 추가하면 변경시 정수 타입으로 지정한다.

특별한 값을 넣지 않으면 모든 데이터가 문자 타입으로 인식된다.

LOGLEVEL은 시스루.己5ysi°9 레벨(WARN. ERROR 등)을 인식한다.

같은 기호는 역슬래시()를 붙여 이스케이프할 수 있다.

[timestamp]와 [id] 사이에는 공백이 한 칸인 경우와 세
칸인 경우가 있는데 [ ]*라는 정규식을 이용해 모든 공백을 허용하게 했다.

filter {
	grok {
		pattern_deftntttons => { "MY_TIMESTAMP" => "%{YEAR}[/-]%{MONTHNUM}[/-]%{MONTHDAY}[/-]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?" }

		match => { "message" => "%{MY_TIMESTAMP:timestamp} * \[%{DATA:td}\] %{IP:tp}%{NUMBER:port:tnt} \[%{LOGLEVEL:level}\] \- %{DATA:msg}\."}
	
    }
}

dissect와 grok 플러그인은 패턴을 이용해 구문 분석을 한다는 공통점이 있지만 성능 차이가 있다.

로그 형식이 일정하고 패턴이 변하지 않는다면 dissect를 사용하는 것이 좋다.

패턴을 해석하지 않아서 속도가 빠르기 때문이다.

하지만 로그 형태가 일정하다고 장담하기 힘들다면 예외처리나 패턴이 자유로운 grok를 사용하는 것이 좋다.

dissect로 분석이 가능한 문자열은 무조건 dissect로 분석하는 것이 성능상 좋으며, grok는 dissect와 기타 필터 조합으로 간단하게 해결되지 않은 진짜 정규 표현식이 필요한 경우에만 사용하는 것이 좋다.


6.3.2.4 대소문자 변경

앞서 로그스태시의 장점이 플러그인을 통해 문자열을 원하는 형태로 쉽게 가공할 수 있다는 것이라고 설명했다.

이번에는 소문자를 대문자로 바꿔보면서 필터 플러그인을 통해 얼마나 쉽게 데이터를 가공할 수 있는 알아보자.

filter {
	dissect {
		mapping => {"message" => "[잉{?timestamp}]%{?->}[%{?td}] %{?tp} %{?port} [%{level}] -%{?msg}."}
	}
    
	mutate {
		uppercase => ["level"]
    }
}

6.3.2.5 날짜/시간 문자열 분석

이벤트가 발생한 날짜/시간 정보는 모니터링이나 진단을 하는 데 없어서는 안 되는 매우 중요한 정보다.

하지만 로그 생성자들이 만드는 날짜/시간 포맷이 통일되어 있지 않다는 문제가 있다.

ISO8601 같은 표준 표기 법 이 있지만 국가나 문화권별로 표현하는 방법 이 다르고 강제적 인 규약이 없으니 로그를 생성하는 곳마다 다른 날짜/시간 포맷을 사용한다.

6.3.2.6 조건문

조건문의 종류 : if, else if, else 조건문 제공



filter {
	dissect {
		mapping => {"message" => "[%{timestamp}]%{?->}[%{id}] %{tp} 잉{port} [응{level}] - %{msg}."}
	} if [level] = "INFO" {
						drop { }
						} else if [level] = "warn" { mutate {
	remove_fteld => [ "ip", "port", "timestamp", "level" ]
						}
	}
}
조건문을 생성할때 참고해야될 사항
  1. 이벤트 속성(Fields): 이벤트 속성은 Logstash 이벤트의 특정 필드 값을 가리킵니다. 예를 들어, message 필드는 로그 메시지를 포함하고 있으며, timestamp 필드는 이벤트의 타임스탬프를 포함하고 있습니다. 다음은 일반적인 이벤트 속성의 몇 가지 예입니다:
  • message: 로그 메시지 자체
  • timestamp: 이벤트 발생 시간
  • source: 이벤트가 기록된 소스(로그 파일, 소켓 등)
  • host: 이벤트를 생성한 호스트
  1. 필드의 값: 이벤트의 특정 필드 값에 따라 조건을 설정할 수도 있습니다. 예를 들어, 로그 메시지에 포함된 IP 주소, 사용자 이름, 로그 레벨 등과 같은 필드 값에 기반하여 조건을 작성할 수 있습니다.

  2. 이벤트 유형: 이벤트의 유형에 따라 조건을 설정할 수도 있습니다. 일부 로그 시스템에서는 이벤트 유형을 구분하기 위해 특정 필드를 사용합니다. 예를 들어, log_type 필드가 error, warning, info와 같은 값을 가지고 있을 수 있습니다.

기본적인 로그 틀
  1. 타임스탬프: 로그 이벤트가 발생한 시간을 나타냅니다. 일반적으로 날짜와 시간 정보를 포함하며, 이는 로그를 정렬하고 시간 기반 분석을 수행하는 데 도움이 됩니다.

  2. 로그 수준(Level): 로그 이벤트의 중요도를 나타냅니다. 주요 로그 수준에는 디버그(Debug), 정보(Info), 경고(Warning), 오류(Error), 치명적(Critical) 등이 있습니다. 로그 수준은 로그 이벤트의 심각도를 표시하는 데 사용됩니다.

  3. 로그 메시지: 실제 로그 이벤트의 내용이 포함됩니다. 이 메시지는 주로 로그를 읽고 해석하는 데 사용됩니다. 로그 메시지는 사용자 지정된 형식으로 작성될 수도 있고, 이벤트의 특정 속성이나 상황에 따라 동적으로 생성될 수도 있습니다.

  4. 추가 정보: 필요에 따라 로그 이벤트에 추가 정보를 포함할 수 있습니다. 예를 들어, 로그 이벤트와 관련된 사용자, IP 주소, 세션 ID 등의 정보를 기록할 수 있습니다.

6.3.3 출력

출력은 파이프라인의 입력과 필터를 거쳐 가공된 데이터를 지정한 대상으로 내보내는 단계다.

0개의 댓글