Rsyslog를 이용한 로그수집서버 구축

임상규·2024년 8월 3일
1

DevOps

목록 보기
2/3
post-thumbnail

우리 서비스에서는 로그 수집서버가 따로 구축되어있지 않았다.
따라서 아래와 같은 불편함이 있었다.

에러 로그 확인

애플리케이션 레벨에서 에러가 발생하였을 때 각각 서버에 직접 들어가 로그를 직접 확인해야했다.
예를들어 어드민 서버에서 에러가 발생하였을 경우 Scale Out 된 서버들을 직접 일일히 들어가서 확인해야했다.
또 로그별로 (액세스 로그, 애플리케이션 로그, 에러 로그, 결제 로그 등) 각각 다른 폴더에 위치하고 있어서 확인도 쉽지 않았다.

과도한 EBS 볼륨 크기

각각 서버에서 로그를 보관을하니 기본적으로 EBS 볼륨을 크게 생성하여야 했다.
이로 인해 서비스가 새로 생기거나 Scale Out 될 때마다 비용적인 문제도 증가하였다.

로그 보관 (소산 백업)

ISMS 증적용이나 사내 정보보호 정책등을 위해 로그를 일정 기간동안 보관 및 소산백업을 해야하는데 각각의 서버에서 스크립트 및 Cron을 적용해서 관리적인 측면에서도 좋지 못했다.

위에 이유들로 로그서버를 구축하기로 하였는데 처음 생각한 방법은 ELK 스택을 이용하는거였다.

방식은

  • 애플리케이션 서버에는 Filebeat 설치
  • 로그수집서버에는 ELK 설치
  • Filebeat가 애플리케이션 서버에서 로그 파일을 읽고 Logstash로 전송
  • Logstash는 로그 데이터를 필터링하고 변환한 후 ElasticSearch로 전송
  • ElasticSearch는 로그 데이터를 인덱싱하고 저장
  • Kibana로 로그 데이터를 시각화하고 분석

이었는데 우리는 Third-Party 솔루션으로 APM을 이용하고 있었기 때문에 로그데이터를 시각화와 분석을 할 필요까지는 없다고 생각했다.

Filebeat와 Logstash로 구현을 한다고해도 Logstash가 가져온 데이터는 ElasticSearch 인덱싱 없이는 확인하기 어려웠다.

따라서 리눅스 시스템에서 로그 메시지를 수집, 저장, 및 전송하는 데 사용되는 시스템 로그 데몬 rsyslog를 사용하여 로그서버를 구성하기로 했다.

Rsyslog란

rsyslog는 시스템이 동작하면서 발생하는 다양한 종류의 로그들을 rsyslogd 데몬을 통해서 로그파일을 저장하는 역할을 한다.
주로 커널, 데몬, 보안 등의 메시지를 수집하고 저장한다.

보통 시스템(OS)에서 문제가 발생할 때 확인하는 /var/log/messages 파일도 rsyslog를 통해서 저장한다.

로그수집서버 구성

rsyslog의 설정 파일은 /etc/rsyslog.conf에 위치하고있다.

먼저 고민한 부분은 '어떤 방식으로 원하는 로그들을 로그 수집서버로 보내고 각각 애플리케이션 로그를 원하는 디렉토리에 원하는 로그명으로 저장할까?'였다.

그래서 애플리케이션 서버에서는 아래와 같이 로그수집서버로 보낼 로그들을 설정하였다.

input(type="imfile"
      File="/path/to/logs/dir/localhost_access_log.*.txt
      Tag="access_log"
      Facility="local6"
...
input(type="imfile"
      File="/path/to/logs/dir/catalina.*.txt
...

이제 애플리케이션 서버로부터 받은 로그들을 로그 수집서버에서는 아래와 같은 방식으로 저장하였다.

$template APPWEBLogs,"/path/to/logs/dir/%PROGRAMNAME%-%$YEAR%%$MONTH%%$DAY%.log"
$template APPWASLogs,"/path/to/logs/dir/%PROGRAMNAME%-%$YEAR%%$MONTH%%$DAY%.log"

...

set $.lcHostName = tolower($hostname);

if ($syslogfacility-text == 'local6') then {
  if ($.lcHostName contains 'web' and not ($.lcHostName contains 'was')) then {
    if $.lcHostName contains 'app' then {
      action(type="omfile" dynaFile="APPWEBLogs" template="myCustomFormat")
    } else if $.lcHostName contains 'adin' then {

...

  } else if ($.lcHostName contains 'was') then {
    if $.lcHostName contains 'app' then {
      action(type="omfile" dynaFile="APPWASLogs" template="myCustomFormat")
    } else if $.lcHostName contains 'admin' then {

위 if문을 보면 $syslogfacility-text == 'local6' , template="myCustomFormat" 내용이 있는데 위와같이 설정한 이유는 다음과 같다.

rsyslog는 Facility를 통해 메시지 서비스 종류를 구분한다.

예를들어

  • kern: kernel 메시지
  • daemon: daemon에 의해 발생된 메시지
  • cron: cron같은 스케줄링 프로그램에 의해 발생되는 메시지
  • local0 ~ loacl7: 시스템 부팅 메시지 기록, 기타 여분 서비스에 사용하기 위한 메시지
    등이 있는데 local0~7은 사용자 정의 용도로 사용되어 메시지 종류를 구분할 수 있도록 사용된다.
    따라서 local6로 설정하여 local6는 애플리케이션 로그라는 종류로 구분지어 사용하였다.

다음 template="myCustomFormat"은 template은 디폴트로 사용할 경우 각 로그가 날라올 때 마다 앞에 너무 쓸데없는 내용이 포함된다.
예를들어 로그서버 이름 외에도 ip주소, 시간(이미 로그에 포함되어 있음)등이 붙어 용량 및 로그를 확인하는데도 어렵게 만들었다.

따라서 로그 템플릿을
template(name="myCustomFormat" type="string" string="<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag% %msg%\n") 와 같이 구성하여 정말 필요한 정보만 포함시켰다.

호스트명 같은 경우에는 애플리케이션 로그 서버에서
$LocalHostName WEB-2
와 같이 설정하여 로그를 저장할 때, 로그를 확인할 때 관리 및 사용의 편의성을 높였다.

프로토콜 및 보안그룹

rsyslog는 tcp, udp를 이용하여 로그를 전송한다.
또한 디폴트 포트번호는 514를 이용한다.

module(load="imudp")
module(load="imtcp")

...

$UDPServerRun 514
$InputTCPServerRun 514

action(type="omfwd" target="{로그서버 ip 주소}" port="514" protocol="tcp" template="myCustomFormat"

따라서 로그수집서버에서 해당하는 보안그룹을 수정해주어여한다.

이슈

/var/log/messages

로그서버를 구축하고 운영중 각각 애플리케이션 서버에 용량이 줄어들지 않고 오히려 늘어나서 이유를 확인해보니 로그들이 /var/log/messages에 저장되고 있었다.

rsyslogs.conf 파일 하단 디폴트 설정을 보면
*.info;mail.none;authpriv.none;cron.none /var/log/message
같이 설정되어 있는데 로그 Serverity를 info로 보내다보니 /var/log/message에 저장이 되고 있는 것이었다.

따라서 설정을 아래와 같이 수정하였다.
*.info;mail.none;authpriv.none;cron.none;local6.none /var/log/message

또 이미 저장된 메시지들은 awk, sed 명령어를 통해 삭제하였다.

Queue 설정

아직 해결 못했다...
Queue 설정을 제대로 하지 않으니 로그가 100중 1~2 정도가 유실되는 느낌이다.
해결하면 수정하겠다...

설정에 관련된 팁

Debug

나 같은 경우에는 하면서 수많은 시행착오를 겪었는데 디버깅을 통해서 해결을 많이 했다.
rsyslog.conf 파일에

$DebugFile /var/log/rsyslog.debug.log
$DebugLevel 2

를 포함하여 문제가 발생할 경우 어디서 어떻게 문제가 발생하였는지 확인했다.

관련 문서

https://www.rsyslog.com/doc/index.html 해당 사이트에서 도움을 정말 많이 받았다.

profile
Junior DevOps Engineer

0개의 댓글

관련 채용 정보