리눅스 로그 - system log, rsyslogd, 저널(journal) 로그, Logrotate, mongodb log rotate

정현우·2023년 1월 1일
8

Linux Basic to Advanced

목록 보기
12/16

[ 글의 목적: linux의 logging architecture 이해를 통해 depth있는 os trouble shotting과 고도화된 application log system 구축을 위해 ]

리눅스의 로그

Linux OS의 log는 커널, 서비스, 애플리케이션 등 시스템에 발생한 이벤트를 분류하여 기록한 파일이다. 크게 syslog, journal 2가지로 나뉘며 시스템 이슈 트레킹, 모니터링 등에 중요한 지표가 된다. 기본적으로 리눅스 로그 아키텍쳐와 두 가지 로깅에 대해 조금 더 자세히 뜯어보자. 그리고 마지막으로 logrotate 까지 살펴보자.

mongodb log rotate 가 급하신 분은 글의 가장 밑을 확인해 주세요!

로그 활용

🔥 log는 진짜 중요하다.

  • application에 대한 log 중요성은 BE/System 개발자라면 익히 깨닫게된다. 하지만 배포 형태와 log 활용 방안에 대해 매번 고민이 있을 것 이다.

  • service로 등록해 관리한다면 systemd 에 의해 관리될텐데 리눅스 자체의 로그 시스템을 모른다면 트러블 슈팅에 불편함이 있을 수 있다. 특히 application web-server (nginx) 등과 같은 third-party 활용에도 journal log를 확인해야할 순간이 꼭 온다.

  • network와 관련된 로깅 활용으로 침해사고 발생 시 침해사고의 원인과 침입경로, 피해상황 등을 파악할 수 있는 중요한 단서가 될 수 있다.

  • 이 위의 모든 내용을 포괄하는 추적과 모니터링, 그에 따른 성능 개선에도 활용이 가능하다.

로그 아키텍처 (log architecture)

linux logging system

  • Linux Logging Types 은 크게 kernal logging & user logging으로 나뉜다.

  • Kernel logging : related to errors, warning or information entries that your kernel may write;

  • User logging : linked to the user space, those log entries are related to processes or services that may run on the host machine.

kernel logging

  • linux를 system을 나눌때 크게 [ user space <-> kernel space ] 분할해서 본다. kernel space에서 logging은 kernel의 "Ring Buffer" 를 통해 수행된다. 커널 링 버퍼는 시스템이 부팅될 때 로그 메시지를 저장하는 첫 번째 데이터 구조인 순환 버퍼이다.

  • 앞서 말한대로, 링 버퍼는 고정 크기의 순환 버퍼로 구성되어 있으며, "최신 데이터를 기록"하고 "오래된 데이터는 덮어쓰는" 방식으로 동작한다. 이를 통해 제한된 메모리 공간을 효율적으로 활용하면서도 중요한 로그 정보를 유지할 수 있다.

  • 더 자세하게 살펴볼 것 이지만 커널 메시지(printk)를 기록하는 dmesg 명령어는 링 버퍼를 통해 커널 메시지를 읽어오고, syslogd와 같은 로깅 데몬은 링 버퍼를 사용하여 로그를 수집하고 저장한다.

  • 커널 관련 로그는 dmesg 명령어를 통해 확인이 가능하다. (root 권한이 필요하다.)

  • linux는 모든 것이 파일이다. 즉 장치도 하나의 파일로 인식된다. linux에서 ring buffer는 /dev 디렉토리의 "kmsg" 라는 character device 에 의해 구체화 된다.

  • ls -l /dev/ | grep kmsg 명령어로 kmsg을 찾아보자. 그리고 cat 을 때려보면 커널 로그 내용인것을 확인할 수 있다.

출처: https://devconnected.com/linux-logging-complete-guide/
  • /dev/kmsg 는 ring buffer를 읽고 쓰기 위해 사용되는 추상화된 디바이스(virtual device)다. 이를 통해 user space 프로세스가 kernel ring buffer 접근 (읽기, 쓰기) 하기 위한 진입점이 된다. (또는 그 반대의 경우)

  • 그리고 우리는 dmesg cli 를 통해 커널 로깅메시지를 확인할 수 있다.

  • 그리고 ring buffer는 /proc/kmsg 로 data를 Dump 한다.

  • 원래 커널 로그의 경우 klogd 이 담당했지만 (커널은 klogd, 시스템로깅은 syslog) 지금은 rsyslogd 가 대체 했다.

User logging

  • user space에서 로그는 최근 배포판 기준으로 크게 syslog과 journal 2가지로 나눠서 비교가 된다. rsyslogd에 의해 수집되는 로그는 보통 syslog라고 부른다.

  • syslog & journal log 비교 표

항목syslog(rsyslog)journal비고
저장하는 정보syslog에 해당하는 특정 종류들부팅 이후 모든 메시지-
저장 여부/var/log저장하지 않음리눅스계열에 따라 저장 위치 바뀜
저장 메시지 타입일반 text, format은 다양바이너리 형태-
서비스(데몬)syslogd (rsyslogd)system-journald-
순환logrotate에 의해 4주저장하지 않아서 부팅마다 초기화-
  • 사실 대부분의 최신 linux 배포본에서 systemd를 적용하면서 로그 시스템도 syslog 에서 systemd 의 journald로 변경되었다. 하지만 기존 호환성을 고려하여 syslog 데몬이 같이 사용하도록 기본 설정되어 있다.

syslog, rsyslogd

출처: https://devconnected.com/linux-logging-complete-guide/
  • syslog는 정확하게는 "logging protocol" 이다. 이를 자신의 로그 파일로 저장하는 동시에 syslog 서버로 UDP 유니캐스트로 전송한다.

  • 위 사진은 syslog 아키텍쳐의 간단 도식화 이다.

  • syslog 서버가 존재하고 UDP 프로토콜 및 포트번호 514 사용하여 facility (로그 메세지 유형), severity (로그 메세지 중요도), 메시지 (로그 내용) 메시지 형태로 전송한다. (각 세부사항은 나중에 다시 살펴보자.)

  • syslog는 위에서 언급하였듯이, 최근 배포판에서는 멀티스레드 지원, TCP 지원, SSL/TLS 지원 및 보안이슈로 업데이트 된 rsyslogd를 사용한다. (정확하게는 syslogd 가 rsyslogd로 바뀐 것이고 syslog라는 용어는 아직 하나로 사용한다)

  • 시스템 내 수많은 커널 경고, 디버깅 정보, 각종 메시지 출력 등에 대한 로그 정보를 기록한다.

  • tail -f /var/log/syslog 로 실제 logging된 데이터 예시는 아래와 같다.

Jan  2 01:14:36 amkr-main kernel: [20220286.684301] [UFW BLOCK] IN=eth0 OUT= MAC=33:33:00:00:00:01:00:15:5d:3a:7b:5a:86:dd SRC=fe80:0000:0000:0000:1ce8:db1b:9a20:2b66 DST=ff02:0000:0000:0000:0000:0000:0000:0001 LEN=52 TC=0 HOPLIMIT=1 FLOWLBL=0 PROTO=UDP SPT=5678 DPT=5678 LEN=12
Jan  2 01:15:01 amkr-main CRON[2228318]: (root) CMD (/bin/bash -c 'if ! pgrep mongod; then /usr/sbin/service mongodb start; fi')
Jan  2 01:15:01 amkr-main CRON[2228319]: (copfirst) CMD (/usr/bin/python3.8 /home/copfirst/amnotifyKR-Renewal/crawler/schedule/crawler_health_checker.py 2>&1)
  • DATE | TIME | hostname | (user) process name | message (log content) 로 구분이 된다.

  • rsyslogd/etc/rsyslog.d 하위에 데몬 설정 파일이 존재한다. 20-ufw.conf 설정 파일을 보면 아래 사진과 같다.

rsyslogd 활용 및 로깅 등록하기

rsyslog 관련 파일 (ubuntu 기준)

  1. /etc/rc.d/init.rsyslog : rsyslogd 데몬을 동작시키는 스크립트
  2. /etc/rsyslog.conf : rsyslogd 데몬 환경 설정 파일
  3. /etc/sysconfig/rsyslog : rsyslogd 데몬 실행과 관련된 옵션 설정 파일
  4. /sbin/rsyslogd : 실제 rsyslogd 데몬 실행 명령

rsyslog 등록하기

  • 위에서 살펴본 ufw.conf 와 같이 conf 파일을 등록하고 재시작만 해주면 로깅 등록이 가능하다. 하지만 그 전에 기본적인 용어에 대한 이해가 필요하다.

Facility

  • 로그 메시지를 발생시키는 프로그램 유형이다. 아래와 같이 정해져 있다.
Facility NumberKeywordC codeFacility Description
0kernLOG_KERNkernel messages
1userLOG_USERuser-level messages
2mailLOG_MAILmail system
3daemonLOG_DAEMONsystem daemons
4authLOG_AUTHsecurity/authorization messages
5syslogLOG_SYSLOGmessages generated internally by syslogd
6lprLOG_LPRline printer subsystem
7newsLOG_NEWSnetwork news subsystem
8uucpLOG_UUCPUUCP subsystem
9clockLOG_CRONclock daemon
10authprivLOG_AUTHPRIVsecurity/authorization messages
11ftp.FTP daemon
12ntp.NTP subsystem
13security.Security log audit
14console.Console log alerts
15solaris-cron.Scheduling logs
16-23local0-7LOG_LOCAL0-7Locally used facilities use 0-7 (local0)

Priority(severity)

  • 로그 메시지의 성격, 위험도, 중요도를 나타낸다. rsyslog는 이 값에 따라 로그 메시지를 어느 파일에 기록할지 누구에게 이 사실을 알릴 것인지를 결정한다.
CodeSeverityKeywordC codeDescription
0Emergencyemerg (panic)LOG_EMERGSystem is unusable.
1AlertalertLOG_ALERTAction must be taken immediately.
2CriticalcritLOG_CRITCritical conditions.
3Errorerr (error)LOG_ERRError conditions.
4Warningwarning (warn)LOG_WARNINGWarning conditions.
5NoticenoticeLOG_NOTICENormal but significant condition.
6InformationalinfoLOG_INFOInformational messages.
7DebugdebugLOG_DEBUGDebug-level messages.

Action

  • 이러한 로그를 어떻게 처리할(저장할) 지에 대한 정보.

다시, rsyslog 등록하기

  • application을 통해서 말고 cli를 통해 logging을 할 수 있는 가장 단순한 방법은 logger cli를 활용하는 것이다.

  • logger log test | tail -1 /var/log/syslog 를 쳐보자. 그러면 다음과 같은 로그를 확인할 수 있다. Jan 2 01:59:23 amkr-main copfirst: log test

  • /etc/rsyslog.d/50-default.conf 파일 가장 하단에 아래 내용을 추가하자.

# for test rsyslog
local0.*    /var/log/test.log
  • 그리고 *.*;auth,authpriv.none -/var/log/syslog line을 찾아 local0.none 를 추가하는 *.*;auth,authpriv.none,local0.none -/var/log/syslog 와 같이 바꿔주자.

  • 이 줄의 의미는 모든 로그(.)를 /var/log/syslog에 기록하지만, 세미콜론(;) 이후의 facility들인 auth, authpriv, local0 은 제외(none)하라는 것이다. 파일이름 앞의 - 은 로그를 파일에 바로 쓰지 말고 메모리에 로그를 가지고 있다가 디스크에 입출력 여유가 있을 경우 쓰라는 의미이다. (http://shallowsky.com/blog/linux/rsyslog-conf-tutorial.html 의 Rules Section을 체크하자)

  • 적용을 위해 sudo service rsyslog restart (또는 sudo systemctl restart rsyslog.service) 통해 restart 하자

  • c 코드에서 다음과 같이 local0에 쓰도록 하면 /var/log/test.log 에 로그가 기록된다. (당연히, 다른 application을 통해서 /var/log/test.log 를 쓰게끔 하는 것도 방법이다.)

#include <syslog.h>

int main()
{
    syslog(LOG_INFO | LOG_LOCAL0, "write your log message");
    return 0;
}

journal log

  • 그래서 저널로그는? 위 kernel logging 에 대한 설명 도식화에서 systemd-journal 이 등장했다. 저널로그는 systemd-journal 의해 수집되는 로그를 말하며 최근 배포판에 등장하여 rsyslogd 와 공존하고 있는 상태다.

  • 사실 rsyslogd 와 핵심 차이는 "저장 여부" 정도로 볼 수 있다. 아래 도식화 그림에서 rsyslogsystemd-jurnal 의 차이를 살펴보자

출처: https://devconnected.com/linux-logging-complete-guide/
  • 로그 파일은 systemd에 의해 바이너리 파일 로 저장 되므로 일반적인 cat 또는 less 명령을 사용하여 파일을 검사할 수 없다.

  • 그래서 journalctl 이라는 cli를 사용한다. journalctl -r 을 통해 최신 저널 로그 중심으로 볼 수 있다.

  • journalctl -u ssh 와 같이 ssh 자리에 특정 service name을 넣어서 사용이 가능하다. 위 option과 같이 사용해 journalctl -r -u ssh 과 같은 cli를 가장 많이 사용한다.

  • 그 외에 journalctl -since '2022-12-30' or journalctl -since '2022-12-30' -until '2022-12-31' 과 같이 날짜 설정값도 가능하다.

  • 그 외 상세한 option은 journalctl(1) — Linux manual page 에서 확인하자.

systemd-journal 설정 파일 (ubuntu 기준)

  • /etc/systemd/journald.conf 에서 저널 로그 관련 설정이 존재하며 기본 설정값은 아래와 같다.

  • 임시 저장 파일은 /var/log/journal 하위에 존재하게 된다.

영구적 저장

  1. 위 설정파일에서 아래 부분을 바꾸자
[Journal]
Storage=persistent
SystemMaxFiles=500
  1. 특정 디렉터리 생성하고 해당 디렉터리에 대해 권한과 소유권을 설정하자. 예시로 /var/log/myjournal 을 활용하겠다.

    • sudo chown root:systemd-journal /var/log/myjournal
    • sudo chmod g+s /var/log/myjournal
  2. systemd 에게 tmpfile 의 경로를 알려 주자

    • sudo systemd-tmpfiles --create --prefix /var/log/myjournal
  3. 변경된 설정을 다시 읽도록 killall -USR1 systemd-journald signal 전송

  • 영구적 저장에 제한 사항이 있다. 기본 제한 사항은 file system 전체 사이즈 10% 초과하면 안되고, file system 여유 공간 중 15%를 초과하면 안된다.

  • 해당 값은 위 conf 에서 바꿀 수 있다. 자세한 사항은 official docs를 확인하자.


Logrotate

지정된 로그 파일에 계속해서 로그를 쌓게 되면 로그 파일의 크기가 과도하게 커질 수 있다. 이럴 경우 로그 파일을 읽어오기 위해 보다 많은 메모리가 필요할 뿐 아니라 로그를 확인하고 분석하는 것도 어려워진다. 이러한 문제를 해결하기 위해 일정시간 단위로 로그화일을 구분하여 저장하고 오래된 로그 파일을 정리하는, 일명 logging file-roation 을 해주는 logrotate 가 있다.

데몬의 로그파일 체크 과정

  • /usr/sbin/ 는 cli 라고 생각할 수 있다. (sbin 디렉토리에 대한 의문은 리눅스 파일 시스템 소유권과 권한 글에서 확인 가능하다.) logrotate cli를 실행하면서 /etc/logrotate.conf 파일을 인자로 넘겨주는 것이다. 그래서 매일 자정에 logrotate 데몬을 conf 파일과 같이 돌리는 것이다.

설정

logrotate 주요 디렉토리

  • /etc/logrotate.d : logrotate를 설정할 개별 프로세스 설정파일
  • /etc/logrotate.conf : logrotate 설정파일 (모드 로그들의 총괄적 설정)
  • /var/lib/logrotate.status : logrotate 작업내역 보관 파일
  • /etc/cron.daily/logrotate : logrotate cron
  • /usr/sbin/logrotate : logrotate 데몬 위치

logrotate.conf 파일

  • include 문단을 보면 logrotate 유틸리티는 /etc/logrotate.d 폴더에 있는 사용자가 정의한 파일들을 로드하여 로그를 관리하게 된다.

  • 즉 우리가 설정할 땐 conf를 바로 수정할 필요 없이 /etc/logrotate.d 폴더에다가 원하는 로그를 관리하기 위한 작업파일을 작성하면 된다.

logrotate.d 에 설정 등록

  • 핵심 설정은 아래와 같다.
  1. 작업 주기 : daily, weekly, monthly, yearly
  2. rotate <숫자> : 로그파일 개수
  3. create <option> | empty : 새로운 로그 파일 생성 여부와 create시 해당 logfile에 대한 설정
  4. dateext : 로그 파일명의 날짜 부여 여부
  5. dateformat : 파일명 date format 형태!
  6. compress : 로그 파일 압축 여부

mongodb log logrotate 작성하기

  • 실제 사용하는 예시이다. postrotate 에 대한 설명은 mongodb를 다루면서 더 자세하게 하겠다. 공식 홈페이지 설명 과 개인적 견해를 더해 logrotate file 로 처리해버렸다.
/var/log/mongodb/*.log {
    create 0644 nobody root # log파일 sudo 권한 없이 볼 수 있게 하기
    daily # 메일
    size 10000M
    dateext # 백업 파일명에 날짜가 기입되도록 함
    dateformat %Y-%m-%d-%s # 압축 파일명 date format 형태
    rotate 10 # 10개 까지만 저장, 나머지 삭제
    copytruncate
    delaycompress
    compress
    notifempty # 로그 내용이 없어도 rotate 진행
    missingok
    sharedscripts # 로그 파일이 여러 개 있어도 스크립트를 공유하여 postrotate 스크립트를 한 번만 실행
    postrotate # rotate 실행 후 스크립트 파일 실행
        /bin/kill -SIGUSR1 `${pidof mongod}`
    endscript
}

실행

  1. 일반적인 강제 실행은 cron에서 살펴본 바와 같이 /usr/sbin/logrotate -f /etc/logrotate.d/만든설정파일 로 할 수 있다.

  2. 디버그 모드는 실제 실행은 하지 않지만 잘 실행되는지, 어떻게되는지 체크할 수 있다. /usr/sbin/logrotate -d /etc/logrotate.d/만든설정파일

  3. "만든설정파일" 의 step by step 실행 과정이 궁금하면 -v option을 사용할 수 있다. /usr/sbin/logrotate -v /etc/logrotate.d/만든설정파일


마무리 및 활용 방안

  • "Centralized logging" 의 중요성을 다시 한 번 깨닫게 되는 계기였다. 개별의 application의 logging이 아무리 잘 되어 있어도, 특히 요즘과 같이 MSA가 대세가 되는 환경에서는, 분산된 logging에 대한 monitoring이 쉽지가 않다.

  • server 자체를 위한 logging과 application logging 은 모두 활용되어야 한다. linux 기반의 os가 활용하는 logging architecture 를 제대로 알고 어떻게 로그를 관리하고 활용할지에 대한 더 심도있는 고민이 필요하다.

  • 거시적으로 rsyslogd, systemd-journald + [ (1) application file logging + (2) application file logging .... ] + ogrotate config 가 하나의 server와 속하는 application (web, was server, agent ... etc) 들 Logging 관리를 위한 올바른 접근법이 아닐까 생각된다.

  • 그리고 관리되는 Log file들은 Logstash 등 활용으로 ELK (EFK), grafana loki 등의 stack과 결합 하여 활용되는 것이 아주 바람직한 로그 관리법이 아닐까 생각이 든다.

  • 이러한 에러 대응 및 로깅을 아주 쉽게 도와주는 third-party Sentry가 있다. Django - Sentry 도입과 적용 원리 글에서 한 번 살펴보자!


출처

profile
도메인 중심의 개발, 깊이의 가치를 이해하고 “문제 해결” 에 몰두하는 개발자가 되고싶습니다. 그러기 위해 항상 새로운 것에 도전하고 노력하는 개발자가 되고 싶습니다!

6개의 댓글

comment-user-thumbnail
2023년 1월 10일

좋은 글 감사합니다!

1개의 답글
comment-user-thumbnail
2023년 11월 22일

매우 좋은 글 감사합니다.
데몬 프로세스와 로그쪽 관련해서 궁금한 부분들이 많았는데 많이 해소된거같네요 :)

2개의 답글