티스토리 뷰

728x90
반응형

본 포스팅에서는 제목에서 명시한 바와 같이 ELK + Redis + SpringSleuth를 활용한 마이크로서비스 로그 추적 시스템 구축 방안에 대해 살펴보겠습니다.

이미 수많은 포스팅에서 ELK + Redis / SpringBoot + Sleuth + Zipkin에 대한 가이드가 있었지만, 이 모든 모듈을 활용하여 종합 로그 추적 시스템을 구축하는 포스팅을 찾지 못해 포스팅을 쓰게 되었습니다.

마이크로서비스를 구축하는 많은 사이트에서는 분산 환경의 추적 관리가 얼마나 중요한지 말로 설명하지 않아도 알 듯 한데요.

이번 포스팅 역시 손쉽게 따라할 수 있는 Hands-On 위주의 따라하기 식으로 풀어나가고자 합니다.

먼저 전체적인 아키텍처를 살펴보겠습니다.

위와 같이 마이크로 서비스 분산 추적 시스템을 구축할 예정입니다.

구성요소와 배치는 다음과 같이 진행됩니다.

  • elasticsearch-7.3.1-linux-x86_64.tar.gz
  • logstash-7.3.1.tar.gz
  • kibana-7.3.1-linux-x86_64.tar.gz
  • filebeat-7.3.1-linux-x86_64.tar.gz
  • redis-5.0.5.tar.gz

ELK + Filebeat는 현재 기준 최신 버전인 7.3.1 버전을 사용할 예정이며, Redis는 5.0.5 버전을 사용할 예정입니다.

테스트에 사용할 OS는

[elastic@elk ~] cat /etc/redhat-release

Red Hat Enterprise Linux Server release 7.6 (Maipo)

[elastic@elk ~]

버전을 사용할 예정이지만 CentOS 7버전을 사용해도 무방합니다.

테스트는 총 2대의 VM에서 진행되며

  • ELK Master Node : ElasticSearch, Kibana, Logstash Indexer, Redis
  • Docker Worker Node : Docker Image Run, Logstash Forwarder

로 각각 구성할 예정입니다.

Docker Image에는 Spring Sleuth + Logback이 적용된 애플리케이션으로 추후 마이크로 서비스 간 추적에 사용될 이미지이며, 확장되어 이후에는 마이크로 서비스 to 마이크로 서비스 호출 시 추적이 어떻게 이루어지는지도 확인해 볼 예정입니다.

그럼 본격적으로 시작해 보겠습니다.

ELK (ElasticSearch + Logstash + Kibana) + Redis Install

1. ElasticSearch 설치

ElasticSearch는 데이터를 저장하고 분석하는 엔진 역할을 수행하는 핵심 모듈입니다.

ElasticSearch는 https://www.elastic.co/kr/downloads/ Elastic 공식 홈페이지에서 다운로드 받을 수 있습니다.

 

직접 다운로드하여 업로드해도 되고, 아래와 같이 wget으로 직접 다운로드도 가능합니다.


[elastic@elk elk]$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.3.1-linux-x86_64.tar.gz

[elastic@elk elk]$ ls 
elasticsearch-7.3.1-linux-x86_64.tar.gz
[elastic@elk elk]$ 


다운로드가 완료되면 다음과 압축을 해제하고 다음과 같이 디렉토리 구조를 확인합니다.


[elastic@elk elk]$ cd elasticsearch-7.3.1/
[elastic@elk elasticsearch-7.3.1]$ ls -la
total 540
drwxr-xr-x. 10 elastic elastic    166 Aug 27 16:05 .
drwxr-xr-x.  7 elastic elastic   4096 Aug 27 20:48 ..
drwxr-xr-x.  2 elastic elastic   4096 Aug 20 05:23 bin
drwxr-xr-x.  2 elastic elastic    178 Aug 27 16:04 config
drwxrwxr-x.  3 elastic elastic     19 Aug 27 16:05 data
drwxr-xr-x.  8 elastic elastic     96 Aug 20 05:23 jdk
drwxr-xr-x.  3 elastic elastic   4096 Aug 20 05:23 lib
-rw-r--r--.  1 elastic elastic  13675 Aug 20 05:18 LICENSE.txt
drwxr-xr-x.  2 elastic elastic   4096 Aug 27 16:05 logs
drwxr-xr-x. 33 elastic elastic   4096 Aug 20 05:23 modules
-rw-r--r--.  1 elastic elastic 502598 Aug 20 05:23 NOTICE.txt
drwxr-xr-x.  2 elastic elastic      6 Aug 20 05:23 plugins
-rw-r--r--.  1 elastic elastic   8500 Aug 20 05:17 README.textile
[elastic@elk elasticsearch-7.3.1]$ cd logs
[elastic@elk logs]$ ls -la
total 36992
drwxr-xr-x.  2 elastic elastic     4096 Aug 27 16:05 .
drwxr-xr-x. 10 elastic elastic      166 Aug 27 16:05 ..
-rw-r--r--.  1 elastic elastic        0 Aug 27 16:04 elasticsearch_audit.json
-rw-r--r--.  1 elastic elastic      715 Aug 27 16:57 elasticsearch_deprecation.json
-rw-r--r--.  1 elastic elastic      380 Aug 27 16:57 elasticsearch_deprecation.log
-rw-r--r--.  1 elastic elastic        0 Aug 27 16:04 elasticsearch_index_indexing_slowlog.json
-rw-r--r--.  1 elastic elastic        0 Aug 27 16:04 elasticsearch_index_indexing_slowlog.log
-rw-r--r--.  1 elastic elastic        0 Aug 27 16:04 elasticsearch_index_search_slowlog.json
-rw-r--r--.  1 elastic elastic        0 Aug 27 16:04 elasticsearch_index_search_slowlog.log
-rw-r--r--.  1 elastic elastic    14774 Aug 27 16:59 elasticsearch.log
-rw-r--r--.  1 elastic elastic    27576 Aug 27 16:59 elasticsearch_server.json
-rw-rw-r--.  1 elastic elastic 30822730 Aug 28 09:41 gc.log
-rw-rw-r--.  1 elastic elastic     1809 Aug 27 16:05 gc.log.00
-rw-r--r--.  1 elastic elastic     3375 Aug 27 16:04 gc.log.0.current
[elastic@elk logs]$ cd ..
[elastic@elk elasticsearch-7.3.1]$ cd config
[elastic@elk config]$ ls -la
total 40
drwxr-xr-x.  2 elastic elastic   178 Aug 27 16:04 .
drwxr-xr-x. 10 elastic elastic   166 Aug 27 16:05 ..
-rw-rw----.  1 elastic elastic   199 Aug 27 16:04 elasticsearch.keystore
-rw-rw----.  1 elastic elastic  2831 Aug 20 05:18 elasticsearch.yml
-rw-rw----.  1 elastic elastic  3524 Aug 20 05:18 jvm.options
-rw-rw----.  1 elastic elastic 17222 Aug 20 05:23 log4j2.properties
-rw-rw----.  1 elastic elastic   473 Aug 20 05:23 role_mapping.yml
-rw-rw----.  1 elastic elastic   197 Aug 20 05:23 roles.yml
-rw-rw----.  1 elastic elastic     0 Aug 20 05:23 users
-rw-rw----.  1 elastic elastic     0 Aug 20 05:23 users_roles
[elastic@elk config]$ cd ..
[elastic@elk elasticsearch-7.3.1]$ cd bin
[elastic@elk bin]$ ls -la
total 18468
drwxr-xr-x.  2 elastic elastic     4096 Aug 20 05:23 .
drwxr-xr-x. 10 elastic elastic      166 Aug 27 16:05 ..
-rwxr-xr-x.  1 elastic elastic     1954 Aug 20 05:18 elasticsearch
-rwxr-xr-x.  1 elastic elastic      491 Aug 20 05:23 elasticsearch-certgen
-rwxr-xr-x.  1 elastic elastic      483 Aug 20 05:23 elasticsearch-certutil
-rwxr-xr-x.  1 elastic elastic      982 Aug 20 05:18 elasticsearch-cli
-rwxr-xr-x.  1 elastic elastic      433 Aug 20 05:23 elasticsearch-croneval
-rwxr-xr-x.  1 elastic elastic     2180 Aug 20 05:18 elasticsearch-env
-rwxr-xr-x.  1 elastic elastic      121 Aug 20 05:18 elasticsearch-keystore
-rwxr-xr-x.  1 elastic elastic      440 Aug 20 05:23 elasticsearch-migrate
-rwxr-xr-x.  1 elastic elastic      126 Aug 20 05:18 elasticsearch-node
-rwxr-xr-x.  1 elastic elastic      172 Aug 20 05:18 elasticsearch-plugin
-rwxr-xr-x.  1 elastic elastic      431 Aug 20 05:23 elasticsearch-saml-metadata
-rwxr-xr-x.  1 elastic elastic      438 Aug 20 05:23 elasticsearch-setup-passwords
-rwxr-xr-x.  1 elastic elastic      118 Aug 20 05:18 elasticsearch-shard
-rwxr-xr-x.  1 elastic elastic      427 Aug 20 05:23 elasticsearch-sql-cli
-rwxr-xr-x.  1 elastic elastic 18828899 Aug 20 05:23 elasticsearch-sql-cli-7.3.1.jar
-rwxr-xr-x.  1 elastic elastic      426 Aug 20 05:23 elasticsearch-syskeygen
-rwxr-xr-x.  1 elastic elastic      426 Aug 20 05:23 elasticsearch-users
-rwxr-xr-x.  1 elastic elastic      346 Aug 20 05:23 x-pack-env
-rwxr-xr-x.  1 elastic elastic      354 Aug 20 05:23 x-pack-security-env
-rwxr-xr-x.  1 elastic elastic      353 Aug 20 05:23 x-pack-watcher-env

[elastic@elk bin]$


주요 디렉토리로는 logs, config, bin 디렉토리가 있으며, 별다른 수정없이 elasticsearch를 구동하는 것만으로 설치를 완료할 수 있습니다.


[elastic@elk bin]$ ./elasticsearch &
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
[2019-08-27T16:05:14,197][INFO ][o.e.e.NodeEnvironment    ] [elk] using [1] data paths, mounts [[/ (rootfs)]], net usable_space [28.7gb], net total_space [43.9gb], types [rootfs]
[2019-08-27T16:05:14,201][INFO ][o.e.e.NodeEnvironment    ] [elk] heap size [989.8mb], compressed ordinary object pointers [true]
...

...

...
[2019-08-27T16:05:24,347][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [elk] adding index lifecycle policy [watch-history-ilm-policy]
[2019-08-27T16:05:24,472][INFO ][o.e.l.LicenseService     ] [elk] license [ef05c999-77d3-4b7d-9b59-05ede69322f4] mode [basic] - valid
[2019-08-27T16:05:24,474][INFO ][o.e.x.s.s.SecurityStatusChangeListener] [elk] Active license is now [BASIC]; Security is disabled
[elastic@elk ~]$


Background로 기동하고 싶을 경우에는 ./elasticsearch --daemonize로 기동합니다.

기동이 완료되면 ElasticSearch가 정상적으로 기동되었는지 확인해 보도록 하겠습니다.


[elastic@elk ~]$ curl http://localhost:9200
{
  "name" : "elk",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "xh3CVLCQRraOFTGruNCl7g",
  "version" : {
    "number" : "7.3.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "4749ba6",
    "build_date" : "2019-08-19T20:19:25.651794Z",
    "build_snapshot" : false,
    "lucene_version" : "8.1.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
[elastic@elk ~]$ netstat -anp | grep 9200 | grep LIST
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp6       0      0 127.0.0.1:9200          :::*                    LISTEN      32079/java
tcp6       0      0 ::1:9200                :::*                    LISTEN      32079/java
[elastic@elk ~]$


ElasticSearch는 Default로 9200 포트를 사용하며, Java Process로 기동되는 것을 알 수 있습니다.

 

2. Kibana 설치

Kibana는 ElasticSearch에 있는 데이터를 시각화 할 수 있는 GUI 분석 툴입니다.

Kibana 역시 Elastic 공식 홈페이지에서 다운로드 받을 수 있습니다.


[elastic@elk elk]$ wget https://artifacts.elastic.co/downloads/kibana/kibana-7.3.1-linux-x86_64.tar.gz

[elastic@elk elk]$ ls 

kibana-7.3.1-linux-x86_64.tar.gz

[elastic@elk elk]$


주요 디렉토리로는 config, bin 디렉토리가 있습니다. kibana의 GUI에 접속 할 수 있도록 설정을 변경해야 하는 kibana.yml 파일이 위치한 config 디렉토리와 역시 기동에 사용할 바이너리가 위치한 bin 디렉토리를 살펴보겠습니다.


[elastic@elk elk]$ cd kibana-7.3.1-linux-x86_64/
[elastic@elk kibana-7.3.1-linux-x86_64]$ ls -la
total 1444
drwxr-xr-x.   14 elastic elastic     271 Aug 27 16:03 .
drwxr-xr-x.    7 elastic elastic    4096 Aug 27 20:48 ..
drwxrwxr-x.    2 elastic elastic      64 Aug 27 16:03 bin
drwxrwxr-x.    5 elastic elastic      43 Aug 27 16:03 built_assets
drwxrwxr-x.    2 elastic elastic      24 Aug 27 16:43 config
drwxrwxr-x.    3 elastic elastic      46 Aug 27 16:08 data
-rw-rw-r--.    1 elastic elastic   13675 Aug 20 05:49 LICENSE.txt
drwxrwxr-x.    6 elastic elastic     108 Aug 27 16:03 node
drwxrwxr-x.    2 elastic elastic       6 Aug 20 05:49 .nodegit_binaries
drwxrwxr-x. 1235 elastic elastic   36864 Aug 27 16:03 node_modules
-rw-rw-r--.    1 elastic elastic 1385050 Aug 20 05:49 NOTICE.txt
drwxrwxr-x.    3 elastic elastic      55 Aug 27 16:03 optimize
-rw-rw-r--.    1 elastic elastic     738 Aug 20 05:49 package.json
drwxrwxr-x.    2 elastic elastic       6 Aug 20 05:49 plugins
-rw-rw-r--.    1 elastic elastic    4048 Aug 20 05:49 README.txt
drwxrwxr-x.   11 elastic elastic     146 Aug 27 16:03 src
drwxrwxr-x.    2 elastic elastic     277 Aug 27 16:03 webpackShims
drwxrwxr-x.    5 elastic elastic     109 Aug 27 16:03 x-pack
[elastic@elk kibana-7.3.1-linux-x86_64]$ cd config
[elastic@elk config]$ ls -la
total 8
drwxrwxr-x.  2 elastic elastic   24 Aug 27 16:43 .
drwxr-xr-x. 14 elastic elastic  271 Aug 27 16:03 ..
-rw-r--r--.  1 elastic elastic 5152 Aug 27 16:43 kibana.yml
[elastic@elk config]$ vi kibana.yml
# Kibana is served by a back end server. This setting specifies the port to use.
server.port: 5601
server.host: "192.168.56.107"
...
...
[elastic@elk config]$ 


위와 같이 config/kibana.yml 파일의 server.port와 server.host 주석을 해제해 주고 서비스할 IP(or Domain), PORT로 설정을 수정합니다.


[elastic@elk kibana-7.3.1-linux-x86_64]$ cd bin
[elastic@elk bin]$ ls -la
total 12
drwxrwxr-x.  2 elastic elastic  64 Aug 27 16:03 .
drwxr-xr-x. 14 elastic elastic 271 Aug 27 16:03 ..
-rwxr-xr-x.  1 elastic elastic 639 Aug 20 05:49 kibana
-rwxr-xr-x.  1 elastic elastic 566 Aug 20 05:49 kibana-keystore
-rwxr-xr-x.  1 elastic elastic 617 Aug 20 05:49 kibana-plugin
[elastic@elk bin]$
[elastic@elk bin]$ ./kibana &
  log   [07:08:18.997] [info][plugins-system] Setting up [1] plugins: [translations]
  log   [07:08:19.003] [info][plugins][translations] Setting up plugin
  log   [07:08:19.004] [info][plugins-system] Starting [1] plugins: [translations]
  log   [07:08:35.611] [info][status][plugin:kibana@7.3.1] Status changed from uninitialized to green - Ready
  log   [07:08:35.616] [info][status][plugin:elasticsearch@7.3.1] Status changed from uninitialized to yellow - Waiting for Elasticsearch
...

...

...

[plugin:visualizations@7.3.1] Status changed from uninitialized to green - Ready
  log   [07:08:36.614] [info][status][plugin:elasticsearch@7.3.1] Status changed from yellow to green - Ready
[2019-08-27T16:08:36,647][INFO ][o.e.c.m.MetaDataIndexTemplateService] [elk] adding template [.management-beats] for index patterns [.management-beats]
...

...

...[o.e.c.r.a.AllocationService] [elk] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.kibana_1][0]] ...]).
  log   [07:08:39.083] [info][migrations] Pointing alias .kibana to .kibana_1.
  log   [07:08:39.133] [info][migrations] Finished in 280ms.
  log   [07:08:39.134] [info][listening] Server running at http://localhost:5601
  log   [07:08:39.141] [info][server][Kibana][http] http server running
[2019-08-27T16:08:39,172][INFO ][o.e.c.m.MetaDataMappingService] [elk] [.kibana_1/3UqvoL97RD6W4Y5uHYycjw] update_mapping [_doc]
  log   [07:08:39.229] [info][status][plugin:spaces@7.3.1] Status changed from yellow to green - Ready

[elastic@elk ~]$ 


위와 같은 로그와 함께 ElasticSearch와 Kibana 연동이 완료됩니다.


[elastic@elk ~]$ netstat -anp | grep 5601 | grep LIST
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.56.107:5601      0.0.0.0:*               LISTEN      5525/./../node/bin/
[elastic@elk ~]$


마찬가지로 기동 정보를 살펴보면 kibana는 kibana.yml 파일에 지정한 ip:port로 Listen하고 있는 것을 확인할 수 있습니다.

 

3. Redis 설치

Redis는 다수개의 서비스가 ElasticSearch에 동시에 로그 데이터를 전송하는 경우 부하가 발생하여 시스템 장애가 발생할 수 있는 문제를 해결하기 위해 제공하는 큐 서비스입니다.

LogStash Forwarder → Redis → LogStash Indexer 간의 큐를 제어하여 부하를 조절하고 필요 시 Scale Out 구성을 할 수 있습니다. Redis 이외에도 RabbitMQ, Kafka 등을 고려할 수 있습니다.

 

Redis 설치 정보는 아래 포스팅을 참고하시기 바랍니다.

[Redis 5.x] 설치 및 CLI 활용 가이드

 

간단히 살펴보자면,


[elastic@elk elk]$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz

[elastic@elk elk]$ ls

redis-5.0.5.tar.gz

[elastic@elk elk]$ 


다운로드가 완료되면, redis-5.0.5.tar.gz 파일 압축을 해제하고 src 하위 디렉토리에서 make를 실행합니다.


[elastic@elk elk]$ cd redis-5.0.5/
[elastic@elk redis-5.0.5]$ ls
00-RELEASENOTES  CONTRIBUTING  deps     Makefile   README.md   runtest          runtest-moduleapi  sentinel.conf  tests
BUGS             COPYING       INSTALL  MANIFESTO  redis.conf  runtest-cluster  runtest-sentinel   src            utils
[elastic@elk redis-5.0.5]$ cd src
[elastic@elk src]$ make
    CC Makefile.dep
rm -rf redis-server redis-sentinel redis-cli redis-benchmark redis-check-rdb redis-check-aof *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep dict-benchmark
(cd ../deps && make distclean)
make[1]: Entering directory `/home/elastic/elk/redis-5.0.5/deps'
(cd hiredis && make clean) > /dev/null || true
(cd linenoise && make clean) > /dev/null || true
(cd lua && make clean) > /dev/null || true
(cd jemalloc && [ -f Makefile ] && make distclean) > /dev/null || true
(rm -f .make-*)
make[1]: Leaving directory `/home/elastic/elk/redis-5.0.5/deps'
(rm -f .make-*)
echo STD=-std=c99 -pedantic -DREDIS_STATIC='' >> .make-settings
echo WARN=-Wall -W -Wno-missing-field-initializers >> .make-settings
echo OPT=-O2 >> .make-settings
echo MALLOC=jemalloc >> .make-settings
echo CFLAGS= >> .make-settings
echo LDFLAGS= >> .make-settings
echo REDIS_CFLAGS= >> .make-settings
echo REDIS_LDFLAGS= >> .make-settings

...

...

...

make[2]: Leaving directory `/home/elastic/elk/redis-5.0.5/deps/jemalloc'
make[1]: Leaving directory `/home/elastic/elk/redis-5.0.5/deps'
    CC adlist.o
    CC quicklist.o
    CC ae.o
    CC anet.o
    CC dict.o
    CC server.o
    CC sds.o
    CC zmalloc.o
    CC lzf_c.o
    CC lzf_d.o
    CC pqsort.o
    CC zipmap.o
    CC sha1.o
    CC ziplist.o
    CC release.o
    CC networking.o
    CC util.o
    CC object.o
    CC db.o
    CC replication.o
    CC rdb.o
    CC t_string.o
    CC t_list.o
    CC t_set.o
    CC t_zset.o
    CC t_hash.o
    CC config.o
    CC aof.o
    CC pubsub.o
    CC multi.o
    CC debug.o
    CC sort.o
    CC intset.o
    CC syncio.o
    CC cluster.o
    CC crc16.o
    CC endianconv.o
    CC slowlog.o
    CC scripting.o
    CC bio.o
    CC rio.o
    CC rand.o
    CC memtest.o
    CC crc64.o
    CC bitops.o
    CC sentinel.o
    CC notify.o
    CC setproctitle.o
    CC blocked.o
    CC hyperloglog.o
    CC latency.o
    CC sparkline.o
    CC redis-check-rdb.o
    CC redis-check-aof.o
    CC geo.o
    CC lazyfree.o
    CC module.o
    CC evict.o
    CC expire.o
    CC geohash.o
    CC geohash_helper.o
    CC childinfo.o
    CC defrag.o
    CC siphash.o
    CC rax.o
    CC t_stream.o
    CC listpack.o
    CC localtime.o
    CC lolwut.o
    CC lolwut5.o
    LINK redis-server
    INSTALL redis-sentinel
    CC redis-cli.o
    LINK redis-cli
    CC redis-benchmark.o
    LINK redis-benchmark
    INSTALL redis-check-rdb
    INSTALL redis-check-aof

Hint: It's a good idea to run 'make test' ;)

[elastic@elk src]$


make가 성공적으로 완료되면 redis-server를 기동합니다.


[elastic@elk src]$ ./redis-server &
4257:C 27 Aug 2019 16:13:27.447 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
4257:C 27 Aug 2019 16:13:27.448 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=4257, just started
4257:C 27 Aug 2019 16:13:27.448 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf
4257:M 27 Aug 2019 16:13:27.448 # You requested maxclients of 10000 requiring at least 10032 max file descriptors.
4257:M 27 Aug 2019 16:13:27.448 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted.
4257:M 27 Aug 2019 16:13:27.448 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'.
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 5.0.5 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 4257
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

4257:M 27 Aug 2019 16:13:27.450 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4257:M 27 Aug 2019 16:13:27.450 # Server initialized
4257:M 27 Aug 2019 16:13:27.450 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
4257:M 27 Aug 2019 16:13:27.450 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
4257:M 27 Aug 2019 16:13:27.450 * Ready to accept connections

[elastic@elk src]$


Background로 기동하고 싶을 경우에는 ./redis-server --daemonize yes로 기동합니다.

기동이 완료되면 Port 정보를 확인해 보도록 하겠습니다.


[elastic@elk src]$ netstat -anp | grep 6379 | grep LIST
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      5749/./redis-server
tcp6       0      0 :::6379                 :::*                    LISTEN      5749/./redis-server
[elastic@elk src]$


Redis 서버는 어디서든 접근이 가능하도록 0.0.0.0:6379 포트로 리슨하고 있는 것을 확인할 수 있습니다.

Redis에 들어오는 데이터를 확인하기 위해서는 redis-cli를 활용하며, select db_num[0~15] / keys * 등으로 확인할 수 있습니다.


[elastic@elk src]$ ./redis-cli

127.0.0.1:6379> ping

PONG

127.0.0.1:6379> config set protected-mode no

OK

127.0.0.1:6379> 


Redis 상태 확인 및 외부에서 Redis에 접근해야 할 경우를 대비하여 config set protected-mode no를 적용합니다.

원격지에서 Redis로 접근 할 경우 인증 검토를 진행하게 되는데 위 옵션이 적용되어 있지 않을 경우


“-DENIED Redis is running in protected mode because protected ”
“mode is enabled, no bind address was specified, no ”

“authentication password is requested to clients. In this mode ”
“connections are only accepted from the loopback interface. ”
“If you want to connect from external computers to Redis you ”
“may adopt one of the following solutions: ”
“1) Just disable protected mode sending the command ”
“‘CONFIG SET protected-mode no’ from the loopback interface ”
“by connecting to Redis from the same host the server is ”
“running, however MAKE SURE Redis is not publicly accessible ”
“from internet if you do so. Use CONFIG REWRITE to make this ”
“change permanent. ”
“2) Alternatively you can just disable the protected mode by ”
“editing the Redis configuration file, and setting the protected ”
“mode option to ‘no’, and then restarting the server. ”
“3) If you started the server manually just for testing, restart ”
“it with the ‘–protected-mode no’ option. ”
“4) Setup a bind address or an authentication password. ”
“NOTE: You only need to do one of the above things in order for ”
“the server to start accepting connections from the outside.\r\n”;


에러가 발생할 수 있습니다.

기동 시점에 바로 적용하기를 원할 경우 ./redis-server protected-mode no &로 직접 옵션을 적용할 수도 있습니다.

 

4. LogStash Indexer 설치

LogStash Indexer는 Redis로부터 전달받은 로그 데이터를 ElasticSearch로 전달하며, 로그를 파싱하고 필터를 적용하는 역할을 수행합니다.

LogStash 역시 Elastic 공식 홈페이지에서 다운로드 받을 수 있습니다.


[elastic@elk elk]$ wget https://artifacts.elastic.co/downloads/logstash/logstash-7.3.1.tar.gz

[elastic@elk elk]$ ls 

logstash-7.3.1.tar.gz

[elastic@elk elk]$


LogStash는 앞서 아키텍처에서 살펴본대로 Indexer와 Forwarder로 나뉘어 구성됩니다.

현재 설치하고 있는 Indexer는 마이크로 서비스에서 Redis를 통해 ElasticSearch로 전송하기 전 Log의 패턴을 분석하고 전송하는 중계 전송하는 역할을 수행하며, Step 5에서 살펴볼 LogStash Forwarder는 실제 마이크로 서비스에서 발생되는 로그를 Redis로 전송하는 역할을 수행합니다.

설치 모듈은 동일 버전을 사용합니다.

LogStash Indexer를 구동하기 전 Input, Ouput에 대해 정의하는 logstash.conf 파일을 작성합니다.

파일 위치는 상관 없지만, logstash-7.3.1/bin 디렉토리에 생성하였습니다.


[elastic@elk bin]$ vi logstash.conf

# Sample Logstash configuration for creating a simple

# Beats -> Logstash -> Elasticsearch pipeline.

 

input {

  redis {

    host => "192.168.56.107"

    port => 6379

    codec => "json"

    data_type => "list"

    key => "logstash"

  }

}

 

output {

  elasticsearch {

    hosts => ["http://localhost:9200"]

    index => "logstash-%{+YYYY.MM.dd}"

    #user => "elastic"

    #password => "changeme"

  }

}

[elastic@elk bin]$


위와 같이 input은 redis로 부터, output은 elasticsearch로 전송한다는 conf 파일을 작성합니다. 최초 아키텍처 이미지의 LogStash Indexer의 위치를 확인해 보고  넘어간다면, 좀 더 이해하기 수월할 것이라 생각됩니다.

LogStash의 기동은 다음과 같습니다.


[elastic@elk bin]$ ./logstash -f logstash.conf &
Thread.exclusive is deprecated, use Thread::Mutex
Sending Logstash logs to /home/elastic/elk/logstash-7.3.1/logs which is now configured via log4j2.properties
[2019-08-27T16:57:53,999][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified
[2019-08-27T16:57:54,013][INFO ][logstash.runner          ] Starting Logstash {"logstash.version"=>"7.3.1"}
[2019-08-27T16:57:55,335][INFO ][org.reflections.Reflections] Reflections took 32 ms to scan 1 urls, producing 19 keys and 39 values
[2019-08-27T16:57:56,089][INFO ][logstash.outputs.elasticsearch] Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>[http://127.0.0.1:9200/]}}
[2019-08-27T16:57:56,342][WARN ][logstash.outputs.elasticsearch] Restored connection to ES instance {:url=>"http://127.0.0.1:9200/"}
[2019-08-27T16:57:56,463][INFO ][logstash.outputs.elasticsearch] ES Output version determined {:es_version=>7}
[2019-08-27T16:57:56,466][WARN ][logstash.outputs.elasticsearch] Detected a 6.x and above cluster: the `type` event field won't be used to determine the document _type {:es_version=>7}
[2019-08-27T16:57:56,491][INFO ][logstash.outputs.elasticsearch] New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>["//127.0.0.1"]}
[2019-08-27T16:57:56,564][INFO ][logstash.outputs.elasticsearch] Using default mapping template
[2019-08-27T16:57:56,588][WARN ][org.logstash.instrument.metrics.gauge.LazyDelegatingGauge] A gauge metric of an unknown type (org.jruby.specialized.RubyArrayOneObject) has been create for key: cluster_uuids. This may result in invalid serialization.  It is recommended to log an issue to the responsible developer/development team.
[2019-08-27T16:57:56,602][INFO ][logstash.javapipeline    ] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>8, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>1000, :thread=>"#"}
[2019-08-27T16:57:56,649][INFO ][logstash.outputs.elasticsearch] Attempting to install template {:manage_template=>{"index_patterns"=>"logstash-*", "version"=>60001, "settings"=>{"index.refresh_interval"=>"5s", "number_of_shards"=>1, "index.lifecycle.name"=>"logstash-policy", "index.lifecycle.rollover_alias"=>"logstash"}, "mappings"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}, "geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>{"type"=>"half_float"}}}}}}}
[2019-08-27T16:57:56,651][INFO ][logstash.inputs.redis    ] Registering Redis {:identity=>"redis://@192.168.56.107:6379/0 list:logstash"}
[2019-08-27T16:57:56,658][INFO ][logstash.javapipeline    ] Pipeline started {"pipeline.id"=>"main"}
[2019-08-27T16:57:56,690][INFO ][logstash.outputs.elasticsearch] Installing elasticsearch template to _template/logstash
[2019-08-27T16:57:56,748][INFO ][logstash.agent           ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2019-08-27T16:57:56,864][INFO ][logstash.outputs.elasticsearch] Creating rollover alias <logstash-{now/d}-000001>
[2019-08-27T16:57:57,193][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}
[2019-08-27T16:57:57,226][INFO ][logstash.outputs.elasticsearch] Installing ILM policy {"policy"=>{"phases"=>{"hot"=>{"actions"=>{"rollover"=>{"max_size"=>"50gb", "max_age"=>"30d"}}}}}} to _ilm/policy/logstash-policy

[elastic@elk bin]$


위와 같이 bin 디렉토리 하위에서 logstash를 기동하며 작성한 logstash.conf 파일을 참조하도록 설정합니다.

기동이 완료되면 Port 정보를 확인해 보도록 하겠습니다.


[elastic@elk bin]$ netstat -anp | grep 9600 | grep LIST
tcp6       0      0 127.0.0.1:9600          :::*                    LISTEN      5799/java
[elastic@elk bin]$

 

5. LogStash Forwader & Docker Image 생성

LogStash Forwarder는 마이크로 서비스에서 생성되는 로그를 Redis로 전송하는 역할을 수행합니다.

LogStash 역시 Elastic 공식 홈페이지에서 다운로드 받을 수 있습니다.


[elastic@elk elk]$ wget https://artifacts.elastic.co/downloads/logstash/logstash-7.3.1.tar.gz

[elastic@elk elk]$ ls 

logstash-7.3.1.tar.gz

[elastic@elk elk]$


다운로드 받은 파일을 기준으로 Dockerfile을 작성하여 도커 이미지에 LogStash를 포함한 이미지를 생성해 보도록 하겠습니다.

Docker 파일을 기동할 VM은 1~4번 스탭과 다른 또다른 VM에서 진행하며, 아래와 같이 구성하였습니다.

1) Dockerfile 작성


[root@kubemaster Template_image]# cat Dockerfile
FROM 192.168.56.107:13000/kdash/common/telemetry/elk/tomcat-centos:jdk8tomcat8
COPY copyFile/logstash-7.3.1.tar.gz .
RUN tar -xzvf logstash-7.3.1.tar.gz
COPY copyFile/logstash.conf logstash-7.3.1/bin/
COPY target/ROOT.war /opt/tomcat/webapps/
CMD ["/root/logstash-7.3.1/bin/logstash", "-f", "/root/logstash-7.3.1/bin/logstash.conf"]
ENTRYPOINT ["/opt/tomcat/bin/catalina.sh", "run"]

[root@kubemaster Template_image]# 


1라인 FROM 절에는 도커 파일에는 Base 이미지로 사용할 tomcat-centos 버전에 jdk8tomcat8 버전을 적용하였습니다.

현재 레포지토리는 Local Nexus3에 구성된 이미지를 Pull하여 구성하게 되어 있으며, 인터넷 환경에서 구성을 원하는 경우

dockerhub에서 참조하여 구성할 수 있습니다.

2~4라인 COPY, RUN 절에는 copyFile 디렉토리에서


[root@kubemaster Template_image]# ls -la copyFile/ 
total 167764 
drwxr-xr-x 2 root root        56 Aug 27 18:00 . 
drwxr-xr-x 6 root root       108 Aug 27 20:01 .. 
-rw-r--r-- 1 root root 171784034 Aug 27 17:47 logstash-7.3.1.tar.gz 
-rw-r--r-- 1 root root       489 Aug 27 18:00 logstash.conf 
[root@kubemaster Template_image]# cd copyFile

[root@kubemaster copyFile]# cat logstash.conf 

# Sample Logstash configuration for creating a simple

# Beats -> Logstash -> Elasticsearch pipeline.

 

input {

  file {

    path => "/var/log/messages"

    stat_interval => 10

  }

}

 

filter {

    grok {

        match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }

    }

}

 

output {

  redis {

    host => "192.168.56.107"

    port => 6379

    data_type => "list"

    key => "logstash"

    #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"

    #user => "elastic"

    #password => "changeme"

  }

}

[root@kubemaster copyFile]#


logstash-7.3.1.tar.gz 압축파일과 사전 작성한 logstash.conf 파일을 복사하고 적용하는 과정입니다.

logstash.conf 파일은 Indexer와 다르게 input, output 이외에 filter라는 항목을 추가하고 있습니다.

input은 전달 받을 로그 파일에 대한 명시와 매 10초에 한번 redis로 전송하겠다는 stat_interval 정보를 포함하고 있으며, output에는 redis 서버 정보가 있습니다.

filter로 적용할 수 있는 모듈은

  • grok - 임의의 구조화된 텍스트로 파싱. 구조화되어 있지 않은 로그 데이터를 파싱할 때 Logstash에서 현재 사용할 수 있는 가장 최선의 방법
  • mutate - rename, remove, replace 등 일반적인 편집을 수행
  • drop - 완전히 삭제
  • clone - 복제본을 생성. 필드를 추가하거나 제거하는 것도 가능.
  • geoip - geo data, ip 주소 등 추가

등이 있으며, 현재 grok를 적용하였습니다.

5라인 COPY 절에는 target/ROOT.war 파일을 tomcat 기동 시 디플로이 할 수 있도록 적용하는 과정입니다.


[root@kubemaster Template_image]# ls -la target/ 
total 70620 
drwxr-xr-x 2 root root       22 Aug 23 12:28 . 
drwxr-xr-x 6 root root      108 Aug 27 20:01 .. 
-rw-r--r-- 1 root root 72312685 Aug 22 19:49 ROOT.war 
[root@kubemaster Template_image]# 


마지막 6~7라인 CMD, ENTRYPOINT 절에서는 

Tomcat을 실행하고 LogStash를 기동하는 과정입니다.

catalina.sh을 docker run 시점에 직접 붙여 실행할 수도 있지만, 이 경우 Dockerfile에 명시한 CMD는 모두 무시하게 됩니다.

Dockerfile 작성이 완료되었으니 이제 직접 기동을 해보도록 하겠습니다.

테스트 과정은 다음과 같이 3Step으로 이루어져 있습니다.

  • docker build -t 192.168.56.107:13000/kdash/common/telemetry/elk/logstashsample:1.0 .
  • docker run -it -p 8080:8080 -d 192.168.56.107:13000/kdash/common/telemetry/elk/logstashsample:1.0
  • docker exec -it cabc171e7e73 /bin/bash

2) docker build


[root@kubemaster Template_image]# docker build -t 192.168.56.107:13000/kdash/common/telemetry/elk/logstashsample:1.0 .
Sending build context to Docker daemon 938.7 MB
Step 1/7 : FROM 192.168.56.107:13000/kdash/common/telemetry/elk/tomcat-centos:jdk8tomcat8
 ---> c5410f1d1d63
Step 2/7 : COPY copyFile/logstash-7.3.1.tar.gz .
 ---> c4420be88d69
Removing intermediate container ebd1b85a0937
Step 3/7 : RUN tar -xzvf logstash-7.3.1.tar.gz
 ---> Running in 2fa62978d7a0

logstash-7.3.1/NOTICE.TXT
logstash-7.3.1/CONTRIBUTORS
logstash-7.3.1/bin/benchmark.sh
logstash-7.3.1/bin/cpdump
logstash-7.3.1/bin/dependencies-report
logstash-7.3.1/bin/ingest-convert.sh
logstash-7.3.1/bin/logstash
logstash-7.3.1/bin/logstash-keystore
logstash-7.3.1/bin/logstash-keystore.bat
logstash-7.3.1/bin/logstash-plugin
logstash-7.3.1/bin/logstash-plugin.bat

...

...

...

logstash-7.3.1/x-pack/src/test/java/org
logstash-7.3.1/x-pack/src/test/java/org/logstash
logstash-7.3.1/x-pack/src/test/java/org/logstash/xpack
logstash-7.3.1/x-pack/src/test/java/org/logstash/xpack/test
logstash-7.3.1/x-pack/src/test/java/org/logstash/xpack/test/RSpecIntegrationTests.java
logstash-7.3.1/x-pack/src/test/java/org/logstash/xpack/test/RSpecTests.java
logstash-7.3.1/LICENSE.txt
logstash-7.3.1/logstash-core/lib/logstash/build.rb
 ---> 0ead22825d47
Removing intermediate container 2fa62978d7a0
Step 4/7 : COPY copyFile/logstash.conf logstash-7.3.1/bin/
 ---> dda5686383a5
Removing intermediate container 249622af18dc
Step 5/7 : COPY target/ROOT.war /opt/tomcat/webapps/
 ---> c6e0a83e2cc9
Removing intermediate container d8fd3224780d
Step 6/7 : CMD /root/logstash-7.3.1/bin/logstash -f /root/logstash-7.3.1/bin/logstash.conf
 ---> Running in 06040a37845f
 ---> 969ffe93bce4
Removing intermediate container 06040a37845f
Step 7/7 : ENTRYPOINT /opt/tomcat/bin/catalina.sh run
 ---> Running in 1829c1c586c9
 ---> 772a156bfbf0
Removing intermediate container 1829c1c586c9
Successfully built 772a156bfbf0
[root@kubemaster Template_image]# 


3) docker run


[root@kubemaster Template_image]# docker run -it -p 8080:8080 -d 192.168.56.107:13000/kdash/common/telemetry/elk/logstashsample:1.0
ee98698a0fc59660069b10291609c314adcefee34674aa60da7ba209fc58da41
[root@kubemaster Template_image]#


-p는 localserviceport:dockerimageport

-d는 백그라운드 데몬으로 기동 이라는 것쯤은 이제 포스팅을 보시는 분들은 알고 있을 거라 생각합니다.

4) docker exec


[root@kubemaster Template_image]# docker ps -a
CONTAINER ID        IMAGE                                                               COMMAND                  CREATED              STATUS              PORTS                    NAMES
ee98698a0fc5        192.168.56.107:13000/kdash/common/telemetry/elk/logstashsample:1.0   "/opt/tomcat/bin/c..."   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   zen_mayer
[root@kubemaster Template_image]# docker exec -it ee98698a0fc5 /bin/bash
[root@ee98698a0fc5 ~]#


위와 같이 docker image 내부로 접속하여 의도한 대로 Docker 이미지가 생성되었는지 확인해 보겠습니다.


==> 로그인 위치에 logFile.log 파일 생성 / 해당 파일은 logback에 지정한 logfile로써 spring sleuth 관련 spanid, traceid가 기록되는 로그

[root@ee98698a0fc5 ~]# ls -la
total 167792
dr-xr-x--- 1 root root        50 Aug 28 01:30 .
drwxr-xr-x 1 root root        40 Aug 28 01:30 ..
-rw-r--r-- 1 root root        18 Dec 29  2013 .bash_logout
-rw-r--r-- 1 root root       176 Dec 29  2013 .bash_profile
-rw-r--r-- 1 root root       176 Dec 29  2013 .bashrc
-rw-r--r-- 1 root root       100 Dec 29  2013 .cshrc
drwxr-x--- 2 root root        40 Aug 28 01:30 .oracle_jre_usage
-rw-r--r-- 1 root root       129 Dec 29  2013 .tcshrc
-rw------- 1 root root      3407 May 10  2017 anaconda-ks.cfg
-rw-r----- 1 root root      3775 Aug 28 01:30 logFile.log
drwxr-xr-x 1 root root        17 Aug 28 01:29 logstash-7.3.1
-rw-r--r-- 1 root root 171784034 Aug 27 08:47 logstash-7.3.1.tar.gz
-rw------- 1 root root      3221 May 10  2017 original-ks.cfg
[root@ee98698a0fc5 ~]# 

 

==> tomcat8과 logstash 기동 상태 확인

[root@ee98698a0fc5 ~]# ps -ef | grep java
root         1     0 29 01:30 ?        00:00:32 /usr/bin/java -Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -classpath /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat -Dcatalina.home=/opt/tomcat -Djava.io.tmpdir=/opt/tomcat/temp org.apache.catalina.startup.Bootstrap /root/logstash-7.3.1/bin/logstash -f /root/logstash-7.3.1/bin/logstash.conf start
root        67    50  0 01:32 ?        00:00:00 grep --color=auto java
[root@ee98698a0fc5 ~]# ps -ef | grep logstash
root         1     0 28 01:30 ?        00:00:32 /usr/bin/java -Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -classpath /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat -Dcatalina.home=/opt/tomcat -Djava.io.tmpdir=/opt/tomcat/temp org.apache.catalina.startup.Bootstrap /root/logstash-7.3.1/bin/logstash -f /root/logstash-7.3.1/bin/logstash.conf start
root        69    50  0 01:32 ?        00:00:00 grep --color=auto logstash
[root@ee98698a0fc5 ~]# 

 

==> logFile.log를 tail을 걸어 둔 상태로 페이지 호출 테스트

[root@ee98698a0fc5 ~]# tail -f logFile.log
[logback]2019-08-28 01:30:22.036  INFO [sleuthtest,,] HikariPool-1 - Driver does not support get/set network timeout for connections. (com.tmax.tibero.jdbc.driver.TbConnection.getNetworkTimeout()I)
[logback]2019-08-28 01:30:22.056  INFO [sleuthtest,,] HikariPool-1 - Start completed.
[logback]2019-08-28 01:30:22.373  INFO [sleuthtest,,] Creating filter chain: Ant [pattern='/css/**'], []
[logback]2019-08-28 01:30:22.373  INFO [sleuthtest,,] Creating filter chain: Ant [pattern='/script/**'], []
[logback]2019-08-28 01:30:22.373  INFO [sleuthtest,,] Creating filter chain: Ant [pattern='image/**'], []
[logback]2019-08-28 01:30:22.373  INFO [sleuthtest,,] Creating filter chain: Ant [pattern='/fonts/**'], []
[logback]2019-08-28 01:30:22.373  INFO [sleuthtest,,] Creating filter chain: Ant [pattern='lib/**'], []
[logback]2019-08-28 01:30:22.425  INFO [sleuthtest,,] Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7ee38c24, org.springframework.security.web.context.SecurityContextPersistenceFilter@30195aa6, org.springframework.security.web.header.HeaderWriterFilter@e958bfd, org.springframework.security.web.csrf.CsrfFilter@1e5ecd43, org.springframework.security.web.authentication.logout.LogoutFilter@20a614a4, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7f56d4d1, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@243b8e3a, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@778f7e6c, org.springframework.security.web.session.SessionManagementFilter@5aaa67ca, org.springframework.security.web.access.ExceptionTranslationFilter@203eeee7, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@494de6e]
[logback]2019-08-28 01:30:22.935  INFO [sleuthtest,,] Initializing ExecutorService 'applicationTaskExecutor'
[logback]2019-08-28 01:30:23.790  INFO [sleuthtest,,] Started ServletInitializer in 6.42 seconds (JVM running for 12.207)
[logback]2019-08-28 01:32:18.498  INFO [sleuthtest,,] Initializing Servlet 'dispatcherServlet'
[logback]2019-08-28 01:32:18.515  INFO [sleuthtest,,] Completed initialization in 15 ms
[logback]2019-08-28 01:32:18.565  INFO [sleuthtest,e9e7539f29d9a1b8,e9e7539f29d9a1b8] ###################################################
[logback]2019-08-28 01:32:21.490  INFO [sleuthtest,07ac1c28b520733a,07ac1c28b520733a] ###################################################
[logback]2019-08-28 01:32:21.741  INFO [sleuthtest,3f6dab975abe314b,3f6dab975abe314b] ###################################################
[logback]2019-08-28 01:32:21.965  INFO [sleuthtest,5dab625ad90a9526,5dab625ad90a9526] ###################################################

 

==> logstash 구성 확인
[root@ee98698a0fc5 ~]# ls
anaconda-ks.cfg  logFile.log  logstash-7.3.1  logstash-7.3.1.tar.gz  original-ks.cfg
[root@ee98698a0fc5 ~]# cat logstash-7.3.1/bin/logstash.conf
# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.

input {
  file {
    path => "/root/logFile.log"
    stat_interval => 10
  }
}

filter {
    geoip {
        source => "[@fields][ip]"
    }
}

output {
  redis {
    host => "192.168.56.107"
    port => 6379
    data_type => "list"
    key => "logstash"
    #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
    #user => "elastic"
    #password => "changeme"
  }
}

[root@ee98698a0fc5 ~]#

 

==> tomcat 구성 확인
[root@ee98698a0fc5 ~]# cd /opt/tomcat/conf
[root@ee98698a0fc5 conf]# ls
Catalina  catalina.policy  catalina.properties  context.xml  jaspic-providers.xml  jaspic-providers.xsd  logging.properties  server.xml  tomcat-users.xml  tomcat-users.xsd  web.xml
[root@ee98698a0fc5 conf]#


전체적인 구성이 완료된 것을 확인할 수 있습니다.

Kibana Visualize

이제 수집된 데이터를 확인해 보도록 하겠습니다.

Kibana Visulize Tool을 확인하기에 앞서 전체 Flow를 다시한번 되짚어 보자면

1) 마이크로 서비스로 구축된 애플리케이션에 Spring Sleuth + logback으로 SpanID, TraceID를 LogFile에 출력하도록 개발한다.

2) 개발된 애플리케이션을 도커이미지로 구성하며, 이때 LogStash Forwarder를 함께 내장한다.

3) ELK + Redis를 구성한다.

4) 로그의 흐름과 상세 구성, 필터 등을 적절히 적용하여 로그 패턴을 도출해 낸다.

자 그럼 Kibana 화면을 살펴보겠습니다.

앞서 살펴본 대로 kibana.yml 파일에 지정한 http://ip:5601로 접속하면, 아래와 같은 화면에 접속할 수 있습니다.

Kibana 활용 가이드는 조만가 포스팅할 예정이니 본 포스팅에서는 로그 수집된 결과에 초점을 맞추시기 바랍니다.

왼쪽 하단에 톱니 바퀴 모양의 Management 버튼을 클릭하고 Kibana Index Patterns 선택하여 logstash-*라는 Index Pattern을 생성합니다.

왼쪽 메뉴의 최상단의 Discover를 선택합니다. 위와 같이 로그파일에 출력된 결과가 10초에 한번 (logstash forwarder에서 Redis로 전송하는 주기) 씩 출력되는 것을 확인할 수 있습니다.

마지막으로 Filters에 원하는 항목 또는 값을 기준으로 조회할 수 있으며, SpanID로 출력된 특정 사용자의 id를 조회한 결과 화면입니다.

주의할 사항은 Index Pattern에 노출되는 Index는 실제 로그가 유입되는 시점에 추가되어 로그를 발생 시킨 이후에 Index Pattern을 추가해야 합니다.

 

지금까지 살펴본 ELK + Redis + Spring Sleuth + Docker 환경에 대한 마이크로 서비스 추적 관리 시스템을 구축하여 분산 환경에서도 서비스간 병목 현상 등을 추적할 수 있도록 대응 방안을 마련해 두어야 할 것입니다.

이번 포스팅은 이것으로 마치고

이후에 Kibana 활용 가이드 및 ELK High Availability 방안, LogStash vs Filebeat, 마이크로 서비스 to 마이크로 서비스에 대한 추적 방안 (+zipkin) 등에 대한 포스팅을 이어서 나갈 예정이니 많은 관심 부탁드립니다.

728x90
반응형