AWS EC2 인스턴스에 ELK를 설치하여 Flask 혹은 python의 로그를 수집해보려고 합니다.
ELK는 Elastichsearch, Logstash, Kibana를 부르는 약어입니다.
Elasticsearch는 Json형식으로 Rest API를 활용하여 저장 및 호출할 수 있는 검색 및 분석 엔진입니다.
Logstash는 로그수집기로 로그를 Elasticsearch로 전달하는 역할을 합니다.
Kibana는 Elasticsearch의 데이터를 대시보드 형태로 볼 수 있도록 합니다.
AWS에는 Amazon OpenSearch Service라고 하여 매니지드 서비스가 존재하지만, 비싸다고 알고 있습니다.
그래서 EC2에 직접 ELK를 설치하여 로그 수집을 진행합니다.
python으로 짜여진 Flask의 API에서 발생하는 데이터를 logstash를 활용하여 Elasticsearch로 저장하고 로그내용을 kibana로 확인해보겠습니다.
ELK를 각각 EC2에 설치하여 연동 테스트를 진행하겠습니다.
저는 프리티어로 AWS를 사용하고 있기 때문에, t2.micro - AMI를 이미지로 선택하였습니다.
그리고 원하는 키페어를 선택하고, 보안 그룹은 elk로 하나 만들었습니다. logstash와 kibana를 설치할때도 elk 보안 그룹을 사용합니다.
인스턴스 생성 개수를 3으로 하여 3개를 동시에 생성합니다.
각각의 인스턴스를 ELK의 이름을 하나씩 부여합니다.
저는 mobaXterm을 사용합니다. 각자의 취양에 맞게 키페어를 사용하여 각각의 인스턴스에 SSH로 접속해주세요
Elastichsearch를 설치한 인스턴스에 접속합니다.
sudo yum install -y java-1.8.0-openjdk-devel.x86_64
java -version
자바 8버전을 설치하고 버전에 맞게 잘 설치되어 있는지 확인합니다.
sudo cat > /etc/yum.repos.d/elasticsearch.repo << EOF
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
Elastichserach 7.x버전 설치를 위해 repo파일을 위와 같이 생성합니다.
sudo yum update -y
sudo yum install -y elasticsearch
설치한 뒤 설정을 변경하여 외부에서도 접속이 가능한 형태로 변경합니다.
sudo vim /etc/elasticsearch/elasticsearch.yml
아래 내용에 주석으로 처리되어 있다면 주석을 해제하여 내용을 변경합니다.
#/etc/elasticsearch/elasticsearch.yml
network.host: 0.0.0.0
cluster.initial_master_nodes: ["node-1", "node-2"]
sudo service elasticsearch start
로 서비스를 실행합니다.
잠시 후 curl -X GET 'localhost:9200'
명령어를 실행해 API가 잘 작동하는지 확인합니다.
외부에서 [인스턴스 public ip:9200]로 접속이 가능하도록 보안그룹에서 인바운드 규칙을 편집합니다.
이전에 생성했던 elk 보안그룹에서 인바운드 규칙 편집을 눌러 아래와 같이 9200번을 추가합니다.
설정을 저장한 뒤 웹브라우저에서 [인스턴스 public ip:9200]을 입력하면 아래와 같이 API응답이 표시됩니다.
{
"name" : "ip-000.00.00.00.ap-northeast-2.compute.internal",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "Cshz1fFbQhXXXXXXXcRC68w",
"version" : {
"number" : "7.17.5",
"build_flavor" : "default",
"build_type" : "rpm",
"build_hash" : "8d61b4f7ddf931f219e3745f295ed2bbc50c8e84",
"build_date" : "2022-06-23T21:57:28.736740635Z",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
kibana를 설치할 인스턴스에 접속합니다.
sudo cat > /etc/yum.repos.d/kibana.repo << EOF
name=Kibana repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
kibana 7.x버전 설치를 위해 repo파일을 위와 같이 생성합니다.
sudo yum update -y
sudo yum install -y kibana
키바니 설치 후에 elasticsearch와 연결이 가능하도록 설정합니다.
sudo vim /etc/kibana/kibana.yml
아래처럼 해당 부분에 주석이 달렸으면 변경해줍니다. 반드시 Elastichsearch-public-ip를 정확하게 입력합니다. 만약 이 부분에 오타가 있으며 "kibana service is not yet ready"라는 에러가 뜰 수 있습니다.
#/etc/kibana/kibana.yml
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://[Elastichsearch-public-ip]:9200"]
sudo service kibna start
마찬가지로 보안그룹 설정에서 인바드운드 규칙을 편집하여 포트를 열어줘야합니다.
5601 포트를 오픈한 뒤 보안그룹을 저장합니다.
웹브라우저에서 [인스턴스 public ip:5601]로 접속하여 로그인을 확입니다.
로그인 성공을 확인합니다.
logstash 인스턴스로 접속합니다.
sudo yum install -y java-1.8.0-openjdk-devel.x86_64
java -version
자바 8버전을 설치하고 버전에 맞게 잘 설치되어 있는지 확인합니다.
sudo cat > /etc/yum.repos.d/elasticsearch.repo << EOF
[logstash-6.x]
name=Elastic repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
logstash 설치를 위해 repo파일을 위와 같이 생성합니다.
sudo yum update -y
sudo yum install -y logstash
mkdir /user/sahre/logstash/config
vim /user/sahre/logstash/config/pipline.conf
위 명령어를 입력하여 파이프라인 생성을 위한 파일을 만들어 아래와 같이 입력합니다.
#/user/sahre/logstash/config/pipline.conf
input {
tcp {
port => 50000
}
}
output {
elasticsearch {
hosts => "000.000.000.000:9200"
}
}
tcp 50000포트로 들어오는 로그들을 elasticsearch에 전송합니다.
sudo /usr/share/logstash/bin/logstash -f /usr/share/logstash/config/pipline.conf
위에서 작성한 파일을 실행 시킵니다.
아래와 비슷한 로그가 출력되면 정상적으로 구동됩니다.
저는 50000번 포트를 통해 로그를 받도록 설정했습니다. 그렇기 때문에 보안그룹의 인바운드 규칙도 추가합니다.
flask rest api를 또 다른 인스턴스에 생성하여, API 발생되는 로그를 logstash에 전송하겠습니다.
저는 편의상 이미 사용한 적이 있는 API를 사용하겠습니다.
자세한 사항은 아래 링크를 참조해주세요
https://velog.io/@gyounghwan1002/KoELECTRA%EB%A1%9C-%EA%B8%B0%EA%B3%84%EB%8F%85%ED%95%B4MRC-API-%EA%B0%9C%EB%B0%9C
본인이 사용하고자 하는 API에 따라 적절한 사양을 골라주시면됩니다.
저는 보안그룹도 elk에 포함시켜 관리하도록 하겠습니다.
아래와 같이 logstash 모듈을 불러오고, 보내고자하는 logstash의 host와 port를 적어주면 logstash 보낼 로깅 인스턴스가 생성됩니다. 해당 인스턴스를 사용하여 로그를 전송합니다.
import logging
import logging.handlers
import logstash
with open("./connection.json","r") as file:
access_info = json.load(file)
logstash_host = access_info['AWS-logstash']['host']
logstash_port = access_info['AWS-logstash']['port']
logger = logging.getLogger('elk-mrc-predict')
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s : %(message)s')
stash = logstash.TCPLogstashHandler(logstash_host, logstash_port, version=1)
stash.setFormatter(formatter)
logger.addHandler(stash)
sudo docker-compose -f mrc_api_logstash.yml up --build -d
저는 docker compose를 사용했습니다.
80포트를 사용해서 nginx로 구성했기 때문에 보안그룹에서 80포트를 열어줍니다.
Postman을 사용하여 아래와 같이 API를 call합니다.
정상적으로 return값이 왔습니다. 이제 이 API하면서 생긴 로그들을 확인해보겠습니다.
kibna 웹으로 접속합니다.
햄버거 메뉴 옆에 "D"를 클릭 -> "Manage spaces"를 클릭 -> Data카테고리에서 "index Management"를 클릭
losgstash에서 elasticsearch로 보낸 로그가 보입니다.
햄버거 메뉴에서 "Kibana"의 Index Patterns에서 패턴을 추가합니다. 아래와 사진과 같이 패턴규측을 저장합니다.
햄버거 메뉴를 눌러 "Observability"의 logs를 클릭합니다.
"Add a logging integration" 클릭
"elastichserach "를 입력하여 Elastichserach Logs를 클릭
맨 아래로 이동하여 "Discover" 클릭
Flask API 수집한 로그들을 아래처럼 확인이 가능합니다.
본 포스팅에서 작성한 방법은 보안이 취약합니다. 사용하지 않을때는 인스턴스를 중지하거나, ELK에 비밀번호를 반드시 설정해주세요