Skip to content

Latest commit

 

History

History
609 lines (447 loc) · 20.9 KB

010.Set_ElastAlert2.md

File metadata and controls

609 lines (447 loc) · 20.9 KB

010. ElastAlert2 설정하기

ElastAlert2는 Yelp에서 만든 ElastAlert을 기반으로 발전한 오픈소스입니다. 더 이상 ElastAlert은 관리되지 않기에 ElastAlert2를 사용해야 합니다. 이와 관련하여 ElastAlert 공식 Github에서도 다음과 같이 기재해두었습니다.

ElastAlert is no longer maintained. Please use ElastAlert2 instead.

ElastAlert2는 도커를 통해서도 설치가 가능한데, 여기서는 Python Package를 이용하여 설치하는 방법으로 진행하겠습니다. 다른 설치 방법은 공식 문서를 참고해주세요.

00. 실습환경

  • CentOS 7.9
  • Python 3.11
  • OpenSSL 1.1.1
  • ElastAlert2 2.13.2

01. 파이썬 설치

ElastAlert2를 사용하기 위해서는 Python 3.11 이상의 버전이 필요합니다. 현재 설치된 버전을 아래 명령어로 확인해주세요.

python3 --version
# or
python3 -V

만약 설치가 되어있지 않거나 Python 3.11 보다 낮은 버전인 경우, python을 설치해야 합니다. 여기서는 설치하는 과정을 진행하도록 하겠습니다.

먼저 CentOS를 업데이트 합니다.

sudo yum -y update

업데이트를 완료하면 서버를 재부팅해주세요.

sudo systemctl reboot

재부팅이 되면 Python 3.11을 설치하기 위한 패키지를 설치합니다. CentOS 7 / RHEL 7의 경우 Python 3.11을 공식적으로 지원하지 않아 소스 코드를 직접 설치해야 하는데 이 때 아래의 패키지가 필요하기 때문입니다. 이미 설치가 되어 있다면 Noting to do라는 문구가 화면에 표출됩니다.

sudo yum -y install epel-release
sudo yum install -y wget make cmake gcc bzip2-devel libffi-devel zlib-devel

그 다음으로 Python 3.11을 빌드하기 위해 필요한 OpenSSL 1.1.1를 설치하도록 하겠습니다. 참고로, OpenSSL 1.1.1 이상의 버전이면 어떤 버전이든 괜찮습니다.

설치 전 먼저 현재 openssl이 존재하는지 확인해주세요.

openssl version

현재 설치된 버전이 OpenSSL 1.1.1 이상의 버전이 아니라면 제거합니다.

sudo yum -y remove openssl openssl-devel

그 다음 OpenSSL 설치에 필요한 패키지를 추가로 설치합니다.

sudo yum install -y gcc-c++ pcre-devel perl

패키지 설치가 완료되면, 아래 명령어를 통해 압축 파일을 다운로드 받거나 공식 문서에서 직접 다운로드 받아 서버로 업로드 합니다.

wget https://www.openssl.org/source/openssl-1.1.1v.tar.gz

다운로드가 완료되면 압축을 해제합니다.

tar xvf openssl-1.1.1v.tar.gz

그 다음 생성된 디렉터리로 이동(cd openssl-1.1.1v) 후 OpenSSL을 설정합니다.

./config --prefix=/usr/local/openssl --openssldir=/usr/local/openssl

설정이 완료되면 아래 명령어를 통해 OpenSSL 1.1.1 버전을 빌드합니다.

make -j $(nproc)

이제 OpenSSL 1.1.1을 설치할 수 있습니다. 아래 명령어를 통해 설치해 주세요.

sudo make install

설치가 완료되면 공유 라이브러리 캐시를 업데이트 합니다.

sudo ldconfig

그 다음 시스템 전체 OpenSSL 설정을 업데이트 합니다.

sudo tee /etc/profile.d/openssl.sh<<EOF
export PATH=/usr/local/openssl/bin:\$PATH
export LD_LIBRARY_PATH=/usr/local/openssl/lib:\$LD_LIBRARY_PATH
EOF

업데이트가 완료되면 쉘 환경을 리로드합니다.

source /etc/profile.d/openssl.sh

서버를 logout 했다가 다시 접속하여 OpenSSL 버전을 확인하면, 1.1.1로 설정된 것을 확인할 수 있습니다.

openssl version
# 아래와 같이 화면에 표출됨
# OpenSSL 1.1.1v  1 Aug 2023

이제 Python 3.11 설치를 위한 준비가 끝났습니다. 아래 명령어를 이용해서 Python 3.11 설치용 압축 파일을 다운로드 받거나 공식 문서에서 직접 다운로드 받아 서버로 업로드 합니다.

wget https://www.python.org/ftp/python/3.11.4/Python-3.11.4.tgz

다운로드가 완료되면 압축을 해제합니다.

tar xvf Python-3.11.4.tgz

그 다음 생성된 디렉터리로 이동(cd Python-3.11.4) 후 아래 명령어를 통해 설정합니다.

LDFLAGS="${LDFLAGS} -Wl,-rpath=/usr/local/openssl/lib" ./configure --with-openssl=/usr/local/openssl 

설정이 완료되면 빌드해주세요. 빌드하는 데 조금 걸릴 수 있습니다.

make

빌드가 완료되었다면, 이제 Python 3.11을 설치할 수 있습니다. 아래 명령어를 통해 설치해 주세요.

sudo make altinstall

설치가 완료되면 다음 명령어를 통해 버전이 뜨는지 확인해주세요.

python3.11 --version
# or
python3.11 -V

그리고 설치 과정에서 pip도 함께 설치됩니다. pippython과 마찬가지로 --version 또는 -V를 통해 버전 확인이 가능합니다.

pip3.11 --version
# or
pip3.11 -V

02. ElastAlert2 설치

ElastAlert2를 설치하기 전, Python 모듈을 업데이트 합니다.

pip3.11 install "setuptools>=11.3"

pip 업그레이드도 진행해주세요.

pip3.11 install --upgrade pip

그 다음 공식 Github에서 필요한 버전을 다운로드 받습니다. 저는 $HOMEelastalert2 디렉터리를 생성하고 그 안에 다운로드 받았습니다. 참고로, git clone을 통해 받으시는 방법도 있습니다.

다운로드가 완료되면 압축을 해제합니다.

tar xvf elastalert2-2.13.2.tar.gz

압축 해제가 완료되면, 생성된 디렉터리(elastalert2-2.13.2)로 이동합니다. 그리고 ElastAlert을 설치하기 위해 필요한 모듈을 먼저 설치합니다.

pip3.11 install -r requirements.txt

그 다음 setup.pyinstall_requires 내에 있는 모듈 설정을 모두 주석 처리합니다. 이렇게 하는 이유는 install_requires의 모듈은 기본적으로 pip를 통해 설치되기 때문입니다. 그러나 여기서는 pip3.11로 실행해야 하기 때문에 이러한 과정이 필요합니다. 이러한 과정이 싫다면 pip 실행 시 pip3.11이 실행되도록 변경하면 됩니다.

import os

from setuptools import find_packages
from setuptools import setup

base_dir = os.path.dirname(__file__)
setup(
    # 내용 생략
    install_requires=[
       # 'apscheduler>=3.9.1.post1,<4.0',
       # 'aws-requests-auth>=0.4.3',
       # 'boto3>=1.26.30',
       # 'cffi>=1.15.1',
       # 'croniter>=1.3.8',
       # 'elasticsearch==7.10.1',
       # 'envparse>=0.2.0',
       # 'exotel==0.1.5',
       # 'Jinja2>=3.1.2',
       # 'jira>=3.4.1',
       # 'jsonpointer>=2.3',
       # 'jsonschema>=4.17.3',
       # 'prison>=0.2.1',
       # 'prometheus_client>=0.15.0',
       # 'python-dateutil>=2.8.2',
       # 'PyYAML>=6.0',
       # 'py-zabbix>=1.1.7',
       # 'requests>=2.8.2',
       # 'sortedcontainers>=2.4.0',
       # 'statsd-tags==3.2.1.post1',
       # 'stomp.py>=8.1.0',
       # 'tencentcloud-sdk-python>=3.0.795',
       # 'texttable>=1.6.7',
       # 'twilio>=7.16.0',
       # 'tzlocal==2.1'
    ]
)

만약 이렇게 하지 않고 setup.py를 설치하면 다음과 같은 에러가 발생하게 됩니다.

Download error on https://pypi.org/simple/: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002) -- Some packages may not be found!

모듈 설치가 완료되면, 아래 명령어를 사용하여 ElastAlert2를 설치합니다.

sudo python3.11 setup.py install

그 다음 ElastAlert이 동작하는데 필요한 Elasticsearch 인덱스를 생성하면 설치가 끝납니다. 만약 여러 대의 Elastsearch Cluster를 바라보고 있는 ElastAlert 서버가 여러 대라면, ElastAlert 한 대에서만 진행해주세요.

elastalert-create-index

그리고 Elastsearch 1대에 대한 host, port 정보와 username, password 정보를 입력합니다. 만약 index 이름을 따로 설정하고 싶다면 원하는 대로 입력해주세요. 여기서는 elastalert으로 설정했습니다. 설정하지 않으면 elastalert_status라고 저장됩니다.

image

생성이 완료되었는지는 Kibana DevTools에서 확인해보겠습니다.

GET _cat/indices/elastalert*?v&s=index:desc

Kibana DevTools에 위와 같이 입력하고 실행하면, 다음과 같은 내용을 확인할 수 있습니다.

health status index              uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   elastalert_status  rnVmB4KzSOuORgnZn5v9Vg   1   1          0            0       416b           208b
green  open   elastalert_silence wQ5tzi49TKG0EFtrae_ESQ   1   1          0            0       416b           208b
green  open   elastalert_past    JCYlZdA2SCmcIeY_sPdHJQ   1   1          0            0       416b           208b
green  open   elastalert_error   KH8xpGLDSdWnME13limEQQ   1   1          0            0       416b           208b
green  open   elastalert         PlfHTmXrRuOX3bDtSuvKAA   1   1          0            0       416b           208b

03. ElastAlert 설정

ElastAlert 설치가 완료되었으므로, 이제 실행을 위한 설정을 진행하도록 하겠습니다. 먼저, 설정 파일인 config.yml과 규칙을 저장할 rules 디렉터리를 생성합니다. 여기서는 elastalert2 디렉터리 위치에 생성했으며, 구조는 다음과 같습니다.

elastalert2
├── config.yaml
├── elastalert2-2.13.2
└── rules

그 다음 config.yaml을 아래와 같이 작성합니다.

rules_folder: rules

run_every:
  seconds: 10
buffer_time:
  minutes: 15

use_ssl : True
ca_certs: <ElasticSearch CA 파일 경로>

es_host: 10.0.0.1
es_port: 9200
es_username: <Elasticsearch user name>
es_password: <Elasticsearch 패스워드>
es_hosts:
    - 10.0.0.1:9200
    - 10.0.0.2:9200
    - 10.0.0.3:9200
    - 10.0.0.4:9200
    - 10.0.0.5:9200
writeback_index: elastalert

query_key: "env"
  • rules_folder : 규칙 파일이 위치한 디렉터리 경로
  • run_every : 규칙을 리로드하는 시간 간격 (default minutes: 5)
  • buffer_time : 지정한 시간 범위 내에서 이벤트나 패턴을 역추적하고 알림을 생성하기 위해 사용되는 설정
  • use_ssl : SSL 사용 여부 설정
  • ca_certs : ElasticSearch CA 파일 경로 설정
  • es_hosts : ElastSearch 목록
  • es_host : Elasticsearch IP
  • es_port : Elasticsearch Port
  • es_username : Elasticsearch 사용자 이름
  • es_password : Elasticsearch 사용자 비밀번호
  • es_hosts : Elasticsearch 클러스터 목록
  • writeback_index : ElastAlert2가 데이터를 저장할 인덱스 이름
  • query_key : 인덱스 내 알림 그룹 기준

04. rule type 알아보기

rule을 생성하기 전, ElastAlert의 rule type에 대해 간단히 알아보겠습니다.

  • any : 모든 필드
  • blacklist : 특정 필드가 블랙 리스트에 포함되어 있을 때
  • whitelist : 특정 필드가 화이트 리스트에 포함되어 있지 않을 때
  • change : 특정 필드의 값이 변경된 경우
  • frequency : 주어진 시간 내에 특정 수의 이벤트가 있을 때
  • spike : 두 슬라이딩 윈도우 내의 이벤트 수 비교하여 spike_height 이전 기간보다 몇 배 더 크거나 작은 경우
  • flatline : 일정 기간 동안 발생한 총 이벤트 수가 주어진 값보다 적을 때
  • new_term : 필드에 이전에 볼 수 없었던 새로운 값이 나타날 때
  • cardinality : 특정 시간 동안 특정 필드에 대한 고유 값의 총 개수가 임계값보다 높거나 낮을 때
  • metric_aggregation : calculation window의 메트릭 값이 임계값보다 높거나 낮을 때
  • spike_aggregation : calculation window의 메트릭 값이 spike_height 이전 기간보다 몇 배 더 크거나 작은 경우
  • percentage_match : calculation windowmatch bucket에 있는 문서의 백분율이 임계값보다 높거나 낮은 경우

각 rule type에 따라 설정하는 옵션이 다르며, 상세한 설명이나 사용 가능한 옵션은 공식 문서를 참고하시길 바랍니다.

05. rule 생성

rule을 생성하기 전, 먼저 조건에 맞는 인덱스와 도큐먼트를 생성합니다. 이 때, 도큐먼트에 date 타입을 가지는 필드를 가지고 있어야 ElastAlert에서 날짜에 대해 구분할 수 있습니다. ElastAlert에서는 기본적으로 @timestamp필드를 기준으로 알림을 보냅니다. 알림을 보내는 필드 기준을 변경하기 위해 date 타입을 두 개 생성해보았습니다.

# 인덱스 생성
PUT testalertindex
{
  "mappings": {
    "properties": {
      "@timestamp": {"type": "date"},
      "datetime": {"type": "date"},
      "name": {"type": "text"},
      "env": {"type": "keyword"}
    }
  }
}

# 도큐먼트 생성
PUT testalertindex/_doc/1
{
  "@timestamp": "2023-10-23T00:00+09:00",
  "datetime": "2023-10-22T15:00:00+09:00",
  "name": "kim1",
  "env": "prod"
}

그 다음, any 타입으로 rule을 생성해보도록 하겠습니다. 알림은 Teams를 통해 받도록 설정하였습니다.

name: "test any"
type: any
index: testalertindex

filter:
- query:
    query_string:
        query: "name: kim*"

alert:
  - "ms_teams"
ms_teams_webhook_url: "MS Teams Webhook URL"

rule이 정상 동작하는지 테스트를 진행합니다.

elastalert-test-rule --config config.yaml rules/test_any.yaml

테스트를 진행하면 현재 시간 기분으로 24시간 전부터 15분마다 쿼리에 맞는 도큐먼트가 있는지 검색합니다. 그러면 다음과 유사하게 @timestamp 시간대에 알림이 하나 있는 것을 발견합니다.

# ...
INFO:elastalert:Queried rule test any from 2023-10-22 14:58 KST to 2023-10-22 15:13 KST: 0 / 0 hits
# ...
INFO:elastalert:Queried rule test any from 2023-10-22 23:58 KST to 2023-10-23 00:13 KST: 1 / 1 hits

이번에는 datetime 필드를 기준으로 알림을 보내도록 설정해보겠습니다. config.yml 또는 직접 생성한 rule 파일에 다음 내용을 추가하면 됩니다.

timestamp_field: "datetime"

그 다음 테스트를 해보면, 알림이 datetime 필드를 기준으로 발생한 것을 확인할 수 있습니다.

#...
INFO:elastalert:Queried rule test any from 2023-10-22 14:59 KST to 2023-10-22 15:14 KST: 1 / 1 hits
#...
INFO:elastalert:Queried rule test any from 2023-10-22 23:59 KST to 2023-10-23 00:14 KST: 0 / 0 hits

이제 실제로 적용하기 위해 ElastAlert을 실행합니다.

python3.11 -m elastalert.elastalert --verbose --config config.yaml

그리고 알림에 해당하는 새로운 도큐먼트를 추가합니다. 여기서 @timestamp를 생략한 이유는 알림 기준이 datetime이므로 추가하지 않아도 괜찮기 때문입니다.

PUT testalertindex/_doc/2
{
  "datetime": "2023-10-23T10:25:00+09:00",
  "name": "kim2",
  "env": "prod"
}

도큐먼트를 추가하고 나면 Teams에서 다음과 같이 알림이 정상적으로 오는 것을 확인할 수 있습니다.

image

06. rule 비활성화

ElastAlert에서는 알림 비활성화 기능을 제공합니다. 알림을 받지 않길 원하는 elastalert rule 파일에 다음 내용을 추가하면 됩니다.

is_enabled: false

그 다음 ElastAlert을 실행해보면 아래와 같은 로그를 확인할 수 있습니다.

INFO:elastalert:Disabled rules are: ['test any']

is_enabled는 default 값을 true로 가지기 때문에, 비활성화하는 경우가 아니라면 입력하지 않아도 괜찮습니다.

만약 rule을 완전히 없애고 싶다면, rule 파일을 삭제하면 됩니다.

07. 알림 메시지에 Kibana URL 추가하기

ElastAlert 알림 메시지에는 Kibana URL을 설정할 수 있습니다. rule 파일 또는 config.yml에 다음과 같은 내용을 추가합니다. 이 때, 설정하려는 인덱스에 대한 인덱스 패턴을 생성한 상태여야 합니다. 참고로, 전체 rule에 공통으로 적용하고 싶다면 config.yml, 특정 rule에 대해서만 적용하고 싶다면 rule 파일에 추가하면 되고, config.yml보다 rule 파일에 쓰인 내용의 우선 순위가 더 높습니다.

generate_kibana_discover_url: True
kibana_discover_app_url: "<Kibana URL>/app/discover#/"
kibana_discover_index_pattern_id: "<인덱스 패턴 ID>"
kibana_discover_version: "7.10"

설정을 한 다음 ElastAlert을 추가하고 다음과 같이 인덱스를 추가합니다.

PUT testalertindex/_doc/3
{
  "datetime": "2023-10-23T15:15:00+09:00",
  "name": "kim3",
  "env": "prod"
}

그 다음 전송된 알림의 Kibana URL에 접속하면 아래와 같이 설정한 쿼리와 그룹을 통해 구분된 알림을 표출하는 것을 확인할 수 있습니다.

image

08. 알림 메시지 내용 변경

이번에는 알림 메시지 내용을 변경해보겠습니다. alert_text_typealert_text_jinja로 설정하여 추가하였습니다. 다른 alert_text_type 설정 방법은 공식 문서를 참고해주세요.

generate_kibana_discover_url: True
kibana_discover_app_url: "<Kibana URL>/app/discover#/"
kibana_discover_index_pattern_id: "<인덱스 패턴 ID>"
kibana_discover_version: "7.10"
ms_teams_attach_kibana_discover_url: True
ms_teams_kibana_discover_title: "Discover in Kibana"

alert_text_type: alert_text_jinja
alert_text: |
  Time: {{datetime}}

  Name: {{name}}

ms_teams_attach_kibana_discover_urlms_teams_kibana_discover_title는 kibana url 전체를 보지 않고 입력 버튼으로 제공하기 위해 추가한 설정입니다. alert_text 내용을 작성할 때는 {{ }} 내에 필드명을 입력하면, 해당 알림에 대한 필드 값을 제공합니다. 그리고 줄바꿈을 하고 싶다면 중간에 한 줄 비워두면 됩니다.

적용 후 실행하고 다음 도큐먼트를 추가해봅시다.

PUT testalertindex/_doc/4
{
  "datetime": "2023-10-23T17:42:00+09:00",
  "name": "kim4",
  "env": "stg"
}

image

09. systemctl 등록하기

ElastAlert을 백그라운드로 실행할 수 있도록 설정해보겠습니다. 다양한 방법이 있지만 그 중 systemctl을 사용하려고 합니다.

먼저 elastalert.service 파일을 생성합니다.

sudo vi /etc/systemd/system/elastalert.service

그리고 파일 내용을 아래와 같이 입력한 다음, 저장합니다.

[Unit]
Description=elastalert2
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/monitoring/elastalert2
ExecStart=/usr/local/bin/python3.11 -m elastalert.elastalert --verbose --config config.yaml
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

그 다음 아래 명령어를 통해 서비스를 새로 불러옵니다.

sudo systemctl daemon-reload

이제 모든 설정이 완료 되었으므로, systemctl을 통해 실행해봅시다.

sudo systemctl start elastalert

실행 상태는 다음 명령어를 통해 상세하게 확인할 수 잇습니다.

sudo systemctl status elastalert -l

이제 실제로 알림이 오는지 확인해보겠습니다.

PUT testalertindex/_doc/5
{
  "datetime": "2023-10-24T22:58:00+09:00",
  "name": "kim5",
  "env": "prod"
}

새로운 도큐먼트를 추가하면 다음과 같이 알림이 정상적으로 오는 것을 확인할 수 있습니다.

image

정상 동작을 확인했으므로, 부팅 시 자동으로 시작되도록 설정해줍니다.

sudo systemctl enable elastalert

참고