안녕하세요. 이번 글에서는 Spring Boot 프로젝트를 생성하고 ELK Stack을 연결하여 로깅을 해보려고 합니다. 시작에 앞서 ELK Stack이 무엇인지 먼저 정리한 후 실습을 진행하도록 하겠습니다.
https://aws.amazon.com/ko/what-is/elk-stack/
자세한 내용은 AWS에서 정리한 글을 보면 명확하게 알 수 있으니, 이 글에서는 간략하게 소개정도만 작성하겠습니다. 내용 전반에 대한 이해가 필요하신 분은 위 문서를 참조해 주세요.
- Elasticsearch (E) : JSON 문서를 지원하는 오픈소스 분석 검색엔진
- Logstash (L): 애플리케이션의 로그를 수집하여 Elasticsearch로 전송하는 역할을 담당하는 오픈소스 데이터 수집 도구
- Kibana (K): Elasticsearch를 기반으로 한 시각화 도구
Spring Boot 어플리케이션을 로컬에서 기동한 후 docker-compose로 ELK 컨테이너를 실행하여 local에서 발생하는 로그를 logstash로 elasticsearch에 적재한 후 kibana에서 확인해보겠습니다. 먼저 컨테이너 실행을 위해 ELK Stack docker-compose 파일을 준비합니다. 저는 망나니 개발자님의 github repository를 참조하였습니다.
1. docker-compose source clone
git clone "https://github.com/MangKyu/Docker-ELK"
소스를 내려받은 후 config를 살펴보면 elasticsearch의 username과 password를 설정하는 부분이 있는데요. 이 부분은 default 값을 유지하도록 하겠습니다. 이 값을 사용자 임의로 변경하게 될 경우 docker-compose build 후 컨테이너를 실행하였을 때 elasticsearch와 kibana에서 인증 관련 fail 오류가 발생합니다. (http 401 response) 물론 위 오류는 실행중인 elasticsearch 컨테이너에 접속하여 인증 정보를 변경해주면 해결할 수 있지만, 이번 글의 목적은 ELK를 구성하여 실행하는 것에 있기에 별도로 다루지는 않겠습니다. 혹시라도 docker-desktop에서 인증 관련 401오류가 발생한다면
위 글을 참고하셔서 인증 정보를 변경하신 후 실행하시면 되겠습니다.
2. set configuration
내려받은 github 소스의 /logstash/pipeline/logstash.conf 파일을 열어준 후 다음과 같이 수정합니다.
input {
# 실습에서는 filebeat를 사용하지 않으므로 주석처리
# beats {
# port => 5044
# }
tcp {
port => 5000
codec => json_lines
}
}
## Add your filters / logstash plugins configuration here
# logstash에서 수집한 데이터를 elasticsearch로 전송
output {
elasticsearch {
hosts => "elasticsearch:9200"
user => "elastic"
password => "changeme"
index => "kylen_app-%{+YYYY.MM.dd}"
}
}
애플리케이션의 로그를 elasticsearch로 전송하는 방법은 다양하지만 위 실습에서는 Spring Boot에서 logstash encoder를 설정하여 직접 logstash로 로그를 보낸 후 elasticsearch로 적재하는 방식을 사용할 것입니다. 따라서 logstash input의 filebeat 설정은 주석을 잡아주었고, json형태로 로그를 전달하기 위해 tcp에 json_lines를 추가해주었습니다.
output의 user / password 항목은 위의 설명과 같이 default 설정을 유지하였고 elasticsearch에서 index를 잡아주기 위해 kylen_app의 이름으로 index를 생성하도록 지정하였습니다.
3. docker-compose build & up
ELK 설정이 마무리되면 docker-compose build와 up 명령어를 통해 컨테이너를 실행시켜줍니다.
docker-compose build && docker-compose up -d
혹시 no configuration file provided: not found 에러가 발생한다면 설정 파일을 찾지 못하는 것이므로, github에서 내려받은 디렉터리 경로로 이동한 후에 다시 명령어를 실행하면 됩니다.
다음과 같은 화면이 나오면 정상적으로 빌드 & 실행이 된 것입니다. docker 프로세스를 확인해보면
Elasticsearch, Logstash, Kibana 세가지 모두 정상적으로 올라간 것을 확인할 수 있습니다. 하지만.. 기본설정을 유지했음에도 Logstash에서 401에러가 발생하였습니다.
elasticsearch 컨테이너에 접속해서 authentication 정보를 변경해주려고 했으나.. 문제가 생겼습니다.
elasticsearch의 username과 password를 default로 유지하면 정상적으로 실행될 것이라 생각하였는데, 아니었습니다.. 컨테이너와 이미지를 모두 제거하고 패스워드를 새로 설정한 후 docker build를 다시 실행해야겠습니다.
logstash의 /pipeline, /config 그리고 kinana의 /config 경로에 있는 설정파일의 password를 elastic으로 변경해주겠습니다.
여기에 추가적으로, 최상위 dir에 있는 docker-compose.yml 과 docker-stack.yml 파일을 수정해주어야 합니다. elasticsearch의 하위 depth에 password 속성을 elastic으로 변경해줍니다. 변경작업이 완료되었다면 docker build & up을 실행해줍니다. elk container가 정상적으로 기동되었다면 호스트의 9200번 포트(elasticsearch)로 접속해 elastic/elastic 으로 로그인 하면 됩니다.
{
"name" : "71976b68d625",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ox9mv5DLTmecxRGe-CJSIw",
"version" : {
"number" : "7.16.3",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "4e6e4eab2297e949ec994e688dad46290d018022",
"build_date" : "2022-01-06T23:43:02.825887787Z",
"build_snapshot" : false,
"lucene_version" : "8.10.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
로그인시 다음과 같은 화면이 response로 온다면 정상입니다.
3. Spring Boot configuration
elk stack container 구성이 완료되었다면 다음으로 Spring Boot에서 logstash로 로그를 전송할 수 있도록 logback-encoder dependency를 추가해줍니다.
build.gradle
implementation 'net.logstash.logback:logstash-logback-encoder:7.3'
log-config
<!-- logstash spec -->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:5000</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
<layout class="net.logstash.logback.layout.LogstashLayout">
<timestampPattern>yyyy-MM-dd' 'HH:mm:ss.SSS</timestampPattern>
</layout>
</appender>
<root level="debug">
<appender-ref ref="LOGSTASH" />
</root>
was를 local에서 실행할 것이고, logstash 컨테이너도 로컬에서 가상머신으로 포워딩 하고 있기 때문에 localhost:5000 주소로 로그를 보낼 수 있도록 destination을 잡아주었습니다. 설정이 다 되었으니 로컬에서 was를 구동한 후에 kibana 주소인 localhost:5601 로 접속하여 index를 설정하고 로그가 정상적으로 적재되는지 확인해 보겠습니다.
※ 혹시나 위의 방법으로도 http 401 response를 해결하지 못하였다면, docker-compose build 전에 logstash와 kibana 설정파일에 임의의 username을 작성 후 build를 실행하여 컨테이너를 먼저 실행한 후에 elasticsearch 컨테이너에 접속하여 home dir의 /bin 경로에 있는 ./elasticsearch-users 스크립트를 실행하셔서 설정파일에 입력하였던 username으로 user를 추가하시면 됩니다. (role을 superuser로 주지 않으면 403 response가 반환됩니다.)
저의 경우에는 집에서 mac으로 컨테이너를 올렸을 땐 정상적으로 실행되었으나, 윈도우 환경에서 실행하였을 때에는 default user인 elastic 유저로 접속도 되지 않고, elasticsearch-setup-passwords interactive 명령어도 동작하지 않아서 새로운 유저를 추가하여 문제를 해결하였습니다.
접속 후 왼쪽의 Discover 메뉴에 들어가면 index pattern을 생성하라는 창이 뜹니다. logstash에서 설정한 index pattern으로 인덱스를 만들어줍니다.
설정이 되었으니 local was를 구동한 후 로그가 정상적재되는지 확인해보겠습니다.
정상적으로 was의 로그가 전송된 것을 확인할 수 있습니다.
다음 글에서는 custom field를 추가하는 방법에 대해 간단하게 다뤄보겠습니다.
References
https://mangkyu.tistory.com/197
https://ggparkitbank.tistory.com/190
'devops > docker' 카테고리의 다른 글
docker를 활용한 web-was 설정하기 (2) (2) | 2023.05.31 |
---|---|
docker를 활용한 web-was 설정하기 (0) | 2023.05.31 |