본문 바로가기

mlops, devops

로깅 시스템 및 로그 설계

중앙 집중식 로깅

MSA에서는 각각의 마이크로서비스가 분산 환경에서 운영됨

각 서비스에서 발생한 로그 파일들은 파편화되어, 트랜잭션을 처음부터 끝까지 순서대로 추적하는 것이 불가능해짐

 

로그의 출처에 상관없이 모든 로그를 중앙 집중적으로 저장, 분석해야함

-> 서비스 실행 환경에서 분리하여 관리

 

장점) 로컬 장비의 디스크 공간을 사용하지 않음, 로컬 I/O나 디스크 쓰기 블로킹이 없음

 

중앙 집중식 로깅의 컴포넌트

 

  • 로그 스트림
    • 마이크로서비스가 만들어내는 로그 메시지의 스트림
    • ex) Log4j(메세지 스트리밍), DB 로그, Network 로그 등
  • 로그 적재기
    • 로그 메시지의 수집
    • 수집된 로그를 다른 종단점으로 보냄
    • ex) Logstash, Fluentd, Logspout
  • 로그 스트림 처리기
    • 신속한 의사 결정에 필요한 실시간 로그 이벤트 분석
    • 알람 공지 및 대시보드로 정보 전송 등
    • 자체 치유 시스템(self-healing system)에서는 스트림처리기가 문제점을 바로잡는 역할을 수행하기도 함
      • ex) 특정 서비스 호출에 대한 응답으로 404 오류가 지속적으로 발생하는 경우
    • ex) kafka, apache flume, spark streaming, storm
  • 로그 저장소
    • 모든 로그 메시지 저장
    • 로그 메세지는 인덱싱이 되어 검색 가능한 형식으로 저장됨
    • ex)
      • ElasticSearch : 실시간로그 저장
      • HDFS (NoSQL DB) : 아카이브된 로그 메세지 저장 - 대용량
      • MongoDB, Cassandra : 요약 데이터 저장 (ex-매월 집계되는 트랜잭션 수)
  • 로그 대시보드
    • 로그 분석 결과를 그래프나 차트로 표현
    • 운영, 관리 조직에서 사용
    • ex) Kibana, Graphite, Grafana

 

로깅 솔루션 종류

이름 클라우드 / 사내 구축형 특징
Loggly 클라우드 기반 가장 많이 사용

스프링부트와 호환성 좋음

AWS CloudTrail과 함께 사용 가능
Papertrail  
Logentries  
Logsene  
Sumo Logic  
Google Cloud Logging  
Splunk 클라우드 기반 / 사내 구축형 로그 수집 시, 스트리밍 방식이 아닌, 파일 적재 방식 사용

유료
Graylog 사내 구축형 오픈소스

로그 저장소로 ElasticSearch 를 사용하고, 메타데이터 저장소로 MongoDB 사용


Log4j 로그 스트리밍을 위해 GELF 라이브러리 사용
ELK 오픈소스

 

ELK를 활용한 테스트 환경 구축

대표적인 솔루션 elk 사용

docker container 활용

docker-compose로 ELK 구축

https://github.com/deviantony/docker-elk

cd docker-elk
docker-compose up -d
 
kibana port는 5601
 

python fastapi application 구현

- python logging 모듈 사용

 

- make_logger.py (logger 인스턴스를 생성해주는 모듈)

#!/usr/bin/python
import logging
import logstash
 
def make_logger(name=None):
    #1 logger instance를 만든다.
    logger = logging.getLogger(name)
 
    #2 logger의 level을 가장 낮은 수준인 DEBUG로 설정해둔다.
    logger.setLevel(logging.DEBUG)
 
    #3 formatter 지정
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
     
    #4 handler instance 생성
    console = logging.StreamHandler()
    file_handler = logging.FileHandler(filename="test.log")
     
    #5 handler 별로 다른 level 설정
    console.setLevel(logging.INFO)
    file_handler.setLevel(logging.DEBUG)
 
    #6 handler 출력 format 지정
    console.setFormatter(formatter)
    file_handler.setFormatter(formatter)
 
    #7 logger에 handler 추가
    logger.addHandler(console)
    logger.addHandler(file_handler)
 
    # logstash에 TCP로 전송하는 핸들러
    stash = logstash.TCPLogstashHandler('localhost',5000,version=1)
    stash.setFormatter(formatter)
    logger.addHandler(stash)
 
    return logger

 

- main.py

#!/usr/bin/python
from fastapi import FastAPI
from make_logger import make_logger
 
app = FastAPI()
test_logger = make_logger("test_log")
 
@app.get("/ping") 
async def ping():
    # 요청 실행 시 로깅
    test_logger.info({"msg":"request /ping"})
    return {"result": "server is alive"}
 
 
@app.on_event("startup")
def startup_event():
    # 서버 생성 시 로깅
    test_logger.info({"msg":"start server"})
    print("server is started")

 

- application 실행

uvicorn log_example:app --host 0.0.0.0 --port 8000

 

kibana를 통한 로그 조회

검색필터

 

분산 추적 (Distributed Tracing)

모든 마이크로서비스 사이에서 발생하는 트랜잭션을 추적 및 분석

- 분산추적을 이용하여 서비스 모니터링

 

 

Open Tracing

CNCF Open Tracing

CNCF에서 만든 분산추적 표준

해당 표준을 따르는 여러 트레이서 : Jaeger, Brave, Elastic APM, Zipkin 등

 

트레이서를 사용하는 이유 :

분산 추적이 없을 시, 마이크로 서비스들을 일일히 디버깅하면서 에러포인트를 찾아야했음

트레이싱 도구로 문제 지점을 좀 더 수월하게 모니터링 할 수 있음

어디서 작업 시간이 오래걸리는지, 에러가 많이 발생하는지 등등

 

Open Tracing 데이터 모델

오픈 트레이싱은 Span(구간), Trace(추적) 개념으로 동작함

- trace : 클라이언트가 서버로 호출한 하나의 요청

- span : 서비스 컴포넌트간의 호출

하나의 트렌잭션에 해당하는 span들은 모두 같은 trace_id를 가지고 있음

 

  • span
    • 분산 추적의 기본 논리 단위
    • 다른 span에 대한 참조를 포함함
    • 여러개의 span이 모여서 하나의 trace를 완성
    • span이 가지고있는 정보
      • 작업 이름
      • 작업 시작 시간, 종료 시간
      • key, value형태의 tag, logs
      • span contexts
        • ex) span id, trace id

 

span 데이터들은 트레이서(ex-jaeger, zipkin)의 데이터 저장소에 모이게 되고,

트레이서는 span의 trace id, span id를 구분해서 시간별로 정리하고 UI를 통해 분산 추적을 확인할 수 있게 됨

 

좋은 로그란?

이 글은 '좋은 로그란 무엇인가'를 참고하여 작성한 글입니다.

로그란?

이벤트에 대한 기록

- 시스템 로그 : 프로그램의 버그나 OS 레벨에서 시스템 이벤트를 추적하기 위해 남기는 로그

- 서비스 로그 : 서비스 수준에서 일어나는 상태 변화나 유저의 행동에 대한 로그

 

목표가 있는 로그

1. 목표를 한 문장으로 정의

ex) 재방문율 집계가 필요하다.

 

2. 하나의 지표에 대해서 다양한 각도의 고민

ex) 재방문율 집계시 '국가별', '레벨별', '직업별' 필터링이 필요할 것이다.

 

3. 목표에 따라 남겨야 할 이벤트와 그 항목들을 정의

ex) 목표들의 우선순위에 따라, 점진적으로 항목을 추가하는 방향도 고려

 

일관성 있는 로그

한 항목에 대한 로그는 일관성이 있어야함

[예시]

사용자의 행동 로그에서 inference 시도 로그 / 데이터 업로드 로그 두 가지가 있다고 하면,

만약 'inference 시도 로그'는 사용자에 대한 정보 중 사용자 id, 사용자 레벨 두 가지를 기록하고,

'데이터 업로드 로그'는 사용자 id, 사용자 닉네임 두 가지를 기록하면

일관성이 없는 로그로 판단.

사용자에 대한 로그라면 일관된 항목들을 기록해야함

 

구성요소 별로 로깅이 필요한 항목을 문서화하면, 로그의 일관성을 유지하는데 도움이 됨

ex) 사용자의 공통 항목 - 사용자 id, 사용자 레벨, 사용자 닉네임

 

로그 형식 및 메타 데이터 참조

주로 json, key/value 형태로 표기

서비스에 저장되어있는 메타데이터를 참조하는 로깅 시스템은 지양

    - 메타데이터가 변경되는 등의 상황과 관리가 추가됨. 따라서 메타데이터를 참조하지 않고 로그 자체 항목으로 추가하는걸 추천

    - 정적 데이터이고, 데이터 양이 많으면 메타데이터 참조도 고려할 필요가 있음

 

문맥 식별자 / 고유 식별자

문맥 식별자 (context_id)

하나의 행동으로 일어난 여러개의 로그는 같은 문맥 식별자를 갖게 함

인과관계나 선후 관계를 파악하는데 도움이 됨. 특히, 사용자가 많을 수록 필요성이 높아짐

ex) 로그에 context_id 항목을 추가함

 

고유 식별자 (id)

중복 로그를 쉽게 식별할 수 있음

특정 로그 하나를 기준으로 잡기 편리함

 

문서화에 필요한 요소들

- 로그의 목표 / 의미

- 로그의 정확한 발생 시점

- 각 항목들의 의미와 데이터 타입

- 항목의 추가/변경/삭제 이력

- 특이사항 기록(발생 일시, 내용)

- 로그가 사용되는 곳

 

로그 유실 모니터링

유실에 빠르게 대응할 수 있어야함

유실되었다면 언제, 얼마나, 어떤 데이터가 유실되었는지 기록해야함

 

로그 저장

데이터 웨어하우스에 저장

핫/콜드 데이터 분리

 

로그 추가/변경의 프로세스

1. 목표 정의

    - 추가 목표와 어떤 데이터가 필요한 것인지 정의

2. 로그 설계

    - 분석가 및 개발자와 이벤트, 항목, 우선 순위 등을 설계

3. 로그 추가 또는 변경 작업

4. 테스트

    - 의도한 시점에 제대로 발생하는지

    - 의도한 형태로 남는지

    - 값이 정확한지

5. 배포

 

 

 

참고

https://engineering.linecorp.com/ko/blog/line-ads-msa-opentracing-zipkin/

 

LINE 광고 플랫폼의 MSA 환경에서 Zipkin을 활용해 로그 트레이싱하기 - LINE ENGINEERING

안녕하세요. LINE Ads에서 DSP Manager를 담당하고 있는 김용훈입니다. LINE Ads는 일본과 태국, 대만 등 전 세계 LINE 사용자를 대상으로 하는 글로벌 광고 플랫폼을 개발하고 있습니다. LINE의 광고 플랫

engineering.linecorp.com

https://bravenamme.github.io/2021/01/28/elk-stack/

 

MSA 와 Log - 중앙 집중식 로깅 ELK stack 편

이 글은 MSA 에서의 로그 생태계와 중앙 집중식 로깅 솔루션 중 하나인 ELK stack 에 대해 설명합니다. 로그 관리의 난제 중앙 집중식 로깅 로깅 솔루션 종류 클라우드 서비스 내장 가능 (=사내 구축

bravenamme.github.io

https://sabarada.tistory.com/42

 

[MSA] MSA의 로깅과 트레이싱

안녕하세요. 오늘부터는 새로운 주제로 찾아뵙게 되었습니다. 바로 MSA입니다. 저희 회사에서 저는 요즘 프로젝트를 MSA의 기술들을 적용해가며 진행하고 있습니다. 오늘은 MSA의 기술 중 로그관

sabarada.tistory.com

https://jhhj424.tistory.com/66

 

[MSA] MSA 환경 분산 로그 트레이싱 (분산 트랜잭션&시스템 추적) - 개발하는 지토

마이크로 서비스 아키텍처 환경에서의 분산 로그 트레이싱 MSA 구조에서는 하나의 HTTP 호출이 내부적으로 여러 개의 서비스를 거쳐서 일어나게 되고, 트랜잭션이 여러 컴포넌트의 조합을 통해서

jhhj424.tistory.com

https://ksr930.tistory.com/112

 

[MSA] OpenTracing, 분산추적(Distributed Tracing) 과 Span context #jaeger #zipkin

분산 추적, Distributed Tracing 클라우드 환경이 대세가 되면서 자연스럽게 MSA 의 사용량 역시 증가하게 되었고 증가한 만큼 우리는 수많은 마이크로 서비스들의 트랜잭션에 대해 추적을 할 필요가

ksr930.tistory.com

https://speakerdeck.com/devinjeon/jamag-ndc19-joheun-rogeuran-mueosinga-joheun-rogeureul-wihae-goryeohaeya-hal-geosdeul

 

(자막)[NDC19] 좋은 로그란 무엇인가?: 좋은 로그를 위해 고려해야 할 것들

NDC19에서 발표하였습니다. 자막없이 보기 -> https://hyojun.me/~ndc19-slide

speakerdeck.com

https://www.slideshare.net/jeongsangbaek/ss-80795259

 

로그 기깔나게 잘 디자인하는 법

로그 기깔나게 잘 디자인하는 법 흔히 만나는 실제 사례를 중심으로 라인게임즈 백정상

www.slideshare.net

 

'mlops, devops' 카테고리의 다른 글

fastapi context 주입  (0) 2022.04.01
service 생성 후 systemd에 등록  (0) 2022.04.01
kubeflow를 활용한 모델 운영의 효율화  (0) 2022.03.19
컨테이너간 통신  (0) 2022.03.11
docker-compose에서 localhost 사용  (0) 2022.02.28