본문 바로가기

Infra

EC2 ELK 적용

이전 회사에서는 k8s 환경에서 EFK(Elasticsearch + Fluentd + Kibana) 를 구축했었는데, 

https://github.com/3jin-p/study/tree/master/infra/aws/efkstack

그 경험을 바탕으로 현재 회사에서 레거시 서버의 RDMBS 에 쌓는 어플리케이션 로그를 제거하기 위해서,

이번에는 로그수집기를 대세인 Logstash 를 이용해서 도입해보았습니다.

 

 

우선 EC2 인스턴스에 ssh 로 접속해줍니다.

접속을 했다면, 필요한 파일 설치부터 진행해보겠습니다.

 

Docker 설치 및 권한부여

sudo amazon-linux-extras install docker  # Docker 설치
sudo usermod -a -G docker ec2-user # Docker 그룹에 ec2-user 추가
sudo service docker start # service 로 docker 실행

 

Logstash 이미지 설치

docker pull docker.elastic.co/logstash/logstash-oss:7.10.2

버전은 DockerHub 에서 적절한 버전을 찾아 사용하시면 됩니다.

 

Logstash 설정 파일 생성

mkdir ~/logstash
vi ~/logstash/logstash.conf

input {
  tcp {
    port => 5000
    codec => json_lines
  }
}

output {
  elasticsearch {
    hosts => "ES-HOST:port"
    ssl => true
    index => "app-log-%{+YYYY.MM.dd}"
    ilm_enabled => false
  }
}

input은 logstash 에서 읽을 요청을 명시합니다. tcp 로 5000번 포트에 들어오는 요청을 json 코덱으로 읽습니다.

output 은 읽은 데이터를 내보낼 곳을 명시합니다. 저 같은 경우는 AWS 관리형 ES 인 Opensearch 를 이미 사용하고 있어 해당 호스트로 보냈습니다. Port 를 명시하지 않으면, ES 의 기본포트로 연결합니다.

 

더보기

관리형을 사용하지 않는 경우 ELK Stack docker-compose 파일을 사용하는 것이 더 쉽습니다.

Logstash 실행

sudo docker run --name logstash -p 5000:5000 -d 
\ -e LS_JAVA_OPTS="-Xms512M -Xmx512M -XX:ParallelGCThreads=1" -v 
\ ~/logstash/:/usr/share/logstash/pipeline/ docker.elastic.co/logstash/logstash-oss:7.10.2

-e 옵션은 환경변수를 지정합니다. logstash 는 java 기반의 오픈소스입니다. GC 메모리 관리를 위한 옵션을 전달합니다.

-p 옵션은 포트를 명시합니다 5000번 포트로 들어오는 요청이 컨테이너 내부의 5000번 포트로 전달됩니다.

-d 옵션은 백그라운드 실행 여부를 뜻합니다.

-v 옵션은 볼륨을 마운트합니다. 위의 예시에서는 ~/logstash 디렉토리를 컨테이너 내의 /usr/share/logstash/pipeline/ 으로 마운트하였습니다. 즉 컨테이너 내부에서 호스트의 logstash 디렉터리에 직접 접근하여 이용할 수 있습니다.

 

이제 서버에서의 준비는 모두 마쳤습니다. 

현재 logstash 로 로그를 전달할 API 서버는 Spring Boot 로 구현되어있습니다.

 

Logstash 는 Logback 에서 Logstash 로 로그를 보낼 수 있는 Appender 를 지원합니다.

 

의존성

implementation 'net.logstash.logback:logstash-logback-encoder:7.0.1'

logback-spring.xml

    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>127.0.0.1:5000</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"profile": "${spring.profiles.active}"}</customFields>
        </encoder>
    </appender>
    
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="LOGSTASH"/>
        </root>
    </springProfile>

LogstashTcpSocketAppender 는 로그를 TCP 로 Logstash 에 전송합니다.

destination 에는 Logstash 의 네트워크 상 위치를 명시합니다.

저는 profile 을 로그에서 구분하기 위해서 customField 로 profile 을 명시했습니다. 

아예 별도의 인덱스로 관리하는 것이 좋지만, 커스텀 필드를 넣을 수 있다.. 는 것을 보여드리기 위해 넣었습니다.

마지막으로 프로파일 별로 어펜더를 등록합니다.

 

이제 어플리케이션을 배포하고, Opensearch 콘솔 (Kibana) 에 접속해봅시다.

 

Index Pattern 생성

Index Pattern 은 데이터를 시각화 할 인덱스와 필드를 지정합니다.

우선 간단히 와일드카드를 사용해 app-* 에 대한 패턴을 시각화 해보겠습니다.

 

확인

Dashboards - Discover 에 들어가보면 로그가 잘 쌓이고 있는걸 확인할 수 있습니다.


이미 관리형 ES 가 존재하고, VM 환경이라 k8s 환경에서 구현할때보다 훨씬 쉽게 구현할 수 있었습니다. 

여기서 많은 서버의 로그를 모두 중앙화 하고싶다면, 해당 VM 들과 Opensearch 와의 네트워크가 뚫려있는 새 인스턴스를 생성하고

해당 서버에 logstash 를 설치하여 해당 서버로 로그를 append 하거나,

FileBeat 을 통하여 로그 전송 속도를 조율하여 logstash 서버가 병목이 되지 않도록 하는 방법이 주로 사용됩니다.

'Infra' 카테고리의 다른 글

[Docker][MySQL] Access denied for user 'root'@'172.17.0.xx'  (0) 2022.06.26