쿠버네티스 doc을 살펴보면 여러가지 로깅 아키텍쳐가 존재한다.
- 모든 노드에서 실행되는 노드-레벨 로깅 에이전트를 사용한다.
- 애플리케이션 파드에 로깅을 위한 전용 사이드카 컨테이너를 포함한다.
- 애플리케이션 내에서 로그를 백엔드로 직접 푸시한다.
필자는 애플리케이션에서 직접 로그를 노출하는 방법3을 활용했다.
https://kubernetes.io/ko/docs/concepts/cluster-administration/logging/
1의 방법의 경우 해당 게시글을 참고하자. (helm을 활용한 EFK 구축 feat fluent-bit)
https://sh970901.tistory.com/152
Fluentd는 다양한 소스에서 로그를 수집해 중앙화할 수 있는 오픈소스 데이터 컬렉터이다. 즉 다양한 시스템에서 들어오는 여러 로그들을 fluentd 하나로 수집하고 파싱하고 포워딩할 수 있다.
발생하는 로그들은 Fluentd에서 로그를 수집하고 elasticsearch에서 로그를 저장한다. Fluentd는 queue같은 역할을 하며 로그를 수집 후 전달하는 역할을 한다. Fluentd가 로그를 모두 수집했다면 저장할 공간이 필요하다. elasticsearch가 이 역할을 수행해준다.
Kibana는 이 로그를 보여주는 대시보드의 역할로 사용하려고 한다.
추가로 elasticsearch 알럿이나 로그 설정을 Slack이나 Grafana를 통해 볼 수도 있다.
https://docs.fluentd.org/container-deployment/docker-compose
먼저 해당 doc을 참고해서 docker-compose로 Fluentd, elasticsearch, kibana를 띄워보도록 하자.
doc에 나온 버전을 활용하면 다음과 같다.
Dockerfile (변경 전)
# fluentd/Dockerfile
FROM fluent/fluentd:v1.12.0-debian-1.0
USER root
RUN ["gem", "install", "fluent-plugin-elasticsearch", "--no-document", "--version", "5.0.3"]
USER fluent
docker-compose.yml (변경 전)
version: "3"
services:
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
links:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.1
container_name: elasticsearch
environment:
- "discovery.type=single-node"
expose:
- "9200"
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:7.13.1
links:
- "elasticsearch"
ports:
- "5601:5601"
이 상태로 docker-compose up을 하게되면 fluent-plugin-elasticsearch와 elasticsearch와 버전이 맞지 않고 gem과도 버전 충돌이 발생하게 되어 필자는 모두 최신 버전으로 변경하였다.
Dockerfile (변경 후)
FROM fluent/fluentd:v1.17-1
# Use root account to use apk
USER root
# below RUN includes plugin as examples elasticsearch is not required
# you may customize including plugins as you wish
RUN apk add --no-cache --update --virtual .build-deps \
sudo build-base ruby-dev \
&& sudo gem install fluent-plugin-elasticsearch \
&& sudo gem sources --clear-all \
&& apk del .build-deps \
&& rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem
USER fluent
~
docker-compose.yml (변경 후)
version: "3"
services:
fluentd:
build: ./
volumes:
- ./conf/fluentd.conf:/fluentd/etc/fluentd.conf
- ./conf/fluent.conf:/fluentd/etc/fluent.conf
links:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elasticsearch
environment:
- "discovery.type=single-node"
expose:
- "9200"
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:8.15.0
links:
- "elasticsearch"
ports:
- "5601:5601"
elasticsearch enrollment 토큰 발급과 계정 생성은 하기 글이 짧고 간단하니 참고하도록 하자.
https://sh970901.tistory.com/149
fluentd/conf/fluentd.conf
# fluentd/conf/fluentd.conf
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<match *.**>
@type copy
<store>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix fluentd
logstash_dateformat %Y%m%d
include_tag_key true
type_name access_log
tag_key @log_name
flush_interval 1s
</store>
<store>
@type stdout
</store>
</match>
이 상태에서 docker-compose up 하게 되면 정상기동은 되나 24224포트로 로그 수집이 정상적으로 이루어지지 않았다.
fluentd 컨테이너안에서 config 설정을 주고 다음 명령어로 로그를 확인해보았다.
fluentd --config /fluentd/etc/fluentd.conf
로그를 확인해보니 24224 포트가 사용 중이라는 에러가 떨어지고 있었다. /etc/fluentd/log안에 data파일에는 실시간으로 로그가 잘 쌓이고 있었는데 말이다. 문제는 fluentd.conf 보다 fluent.conf가 우선순위가 높았고 여기서 24224 포트를 사용 중이였다. 다시 살펴보니 공식 doc에서도 fluent.conf로 가이드하고 있었다. 기존 default fluent.conf에서 해당 data 파일에 로그를 남기고 있었다.
24224를 24225로 변경 후 정상 설정 확인이 완료되었다.
추가로 fluent.conf 에서
logstash_prefix fluentd
logstash_dateformat %Y%m%d
해당 설정을 통해 엘라스틱에서 fluentd-날짜로 인덱스가 생성될 것이다.
24224포트의 FluentD로 로그를 보내는 방법은 다양하겠지만 필자는 커스텀한 로깅 환경에서 멀티라인을 잡는 엔지니어링의 고충이 있어애플리케이션에서 Logback, LogAppender를 활용하여 바로 FluentD로 로그를 Strem으로 보내도록 설정하였다.
Pom.xml에 추가
<dependency>
<groupId>com.sndyuk</groupId>
<artifactId>logback-more-appenders</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.fluentd</groupId>
<artifactId>fluent-logger</artifactId>
<version>0.3.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
LogAppender Class 생성
@Slf4j
@Component
public class CustomLogAppender extends DataFluentAppender<ILoggingEvent> {
String customRegex = "\\[(.*),(.*)\\] (.*)";
Pattern pattern = Pattern.compile(customRegex, Pattern.DOTALL);
@Override
public void start() {
setTag("dev");
setLabel("log");
setRemoteHost(FluentD 주소);
setPort(24224);
super.start();
}
@Override
protected Map<String, Object> createData(ILoggingEvent event) {
Matcher matcher = pattern.matcher(event.getFormattedMessage());
if(event.getFormattedMessage().contains("privacy")){
setLabel("privacy");
}else {
setLabel("log");
}
Map<String, Object> data = super.createData(event);
if (matcher.matches()) {
data.put("method", matcher.group(1));
data.put("tagging", matcher.group(2));
data.put("content", matcher.group(3));
}
if(event.getLevel().levelStr.equals(Level.ERROR.levelStr)){
if(event.getFormattedMessage().length() > 400){
data.put("msg", event.getFormattedMessage().substring(0, 400)+"...");
}else {
data.put("msg", event.getFormattedMessage());
}
}
data.put("project", ~);
data.put("hostname", ~);
data.put("ip", ~);
data.put("datetime", ~);
return data;
}
}
LogAppender에서 Tag, Label을 추가하거나 넣고 싶은 data 필드를 넣을 수 있으니 필요한 값을 환경, 상황에 맞게 설정하면 될 거 같다.
logback-spring.yml
<appender name="FLUENTD" class="com.package 경로.CustomLogAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%message%n</pattern>
</layout>
</appender>
<appender name="ASYNC_FLUENTD" class="ch.qos.logback.classic.AsyncAppender">
<!-- Logback의 AsyncAppender 옵션 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<param name="includeCallerData" value="false"/>
<param name="queueSize" value="2048"/>
<param name="neverBlock" value="true"/>
<param name="maxFlushTime" value="5000"/>
<appender-ref ref="FLUENTD" />
</appender>
<root level="INFO">
<appender-ref ref="ASYNC_FLUENTD" />
</root>
Logback 설정까지 완료되었다면 정상적으로 FluentD-> ElasticSearch & Kibana로 인덱스 및 로그를 확인할 수 있을 것이다.
Kibana에서 인덱스가 생성되었다면 data-view를 만들어 확인해보자.
'IT' 카테고리의 다른 글
Pinpoint-docker 설치하고 적용하기 [ agent 분리 ] (0) | 2024.08.25 |
---|---|
ElasticSearch&Kibana v8.15 docker 설치 & 토큰 발급 (0) | 2024.08.24 |
AWS EKS Cluster 접근하기 (0) | 2024.08.24 |
node, npm version up (0) | 2024.04.19 |
maven multi pom.xml, pom-dev.xml, pom-prod.xml 다중 분리 (0) | 2024.03.22 |