24.03.12 - 13
어느정도 이해가 되었다.
이 친구는 로그를 생성하기 위해서 grafana-loki project에서 제공하는 무한 로그 생성기이다. 지속적으로 여러가지 http status code로 된 여러가지 rest api request log들을 생성한다. 그리고 해당 로그들은 logs에 저장된다.
promtail은 이 logs에 있는 정보들을 loki로 뿌려주는 역할을 한다. loki에 들어갈 label정보와 flog에서 어느 저장장치에 있는 logs를 가져올 것인지 여기에서 설정할 수 있고, loki와 어떻게, 어디로 통신할지도 여기에서 설정할 수 있다.
---
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: <http://gateway:3100/loki/api/v1/push>
tenant_id: tenant1
scrape_configs:
- job_name: flog_scrape
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
이게 promtail을 설정하는 부분인데, server 파트는 실행되는 port를 의미하고 grpc의 경우 (maybe?) MSA 관련 설정인 것 같으며, 0번 포트라고 되어있는 것은 랜덤 포트를 의미한다고 한다.
positions는 log file이 저장될 파일 경로
clients는 연결될 loki 서버를 의미한다. tenant는 get started에서는 중요하게 다루지 않았으나, 우리 서비스 내에서는 따로 관리해주어야 할 것 같다. 이는 여러개의 서비스가 하나의 loki cluster에 로그를 전송하는 경우 마치 서로 다른 loki에게 전송하는 것처럼 관리할 수 있게 해주는 것이다. 이름에 따라서 어는 tenant에 속하는 지가 달라진다. 우리는 서비스가 여러개이니가 이를 활용해야할 부분이 있다.
scrape_configs의 경우 조금 난해하게 되어있어서 정확하게 모르겠지만, 확실한 것은 여기에서 해당 task의 이름을 job의 형태로 붙여주고, 어느 path에서 log를 읽어올 것인지 설정할 수 있다.
찾아보니 docker_sd_configs의 경우 도커 컨테이너 끼리 소통할 때 이용하는 듯하다. 내 머릿속 구조에서는 promtail과 loki는 서로 다른 server일 것이기 때문에 이 부분은 나와 관계가 없다.
relabel_configs 는 수집한 로그의 메타 데이터를 수정하는 부분이다. 로그를 어떻게 저장할지 formatting 한다고 생각하면 편리할 듯 하다.
gateway는 왜 있어야 할까요?
이 생각이 계속 들었다. 왜 있어야 하지? 우선 공식 문서를 계속 읽어본 결과, loki는 read와 write를 원래 동시에 할 수 있지만, 해당 기능을 두 개로 나누어서 하나의 역할만 하게 할 수 있다. 그리고 그렇게 하기를 권장한다. (정확한 이유는 잘 모르겠다. 이것에 대한 레퍼런스를 열심히 찾아보았으나 찾을 수 없었다. 모듈화 정도의 의의를 갖지 않을까 라는 것이 나의 추측이다.) 그리고 이 component는 scalable해서 늘렸다 줄였다 할 수 있다. 그래서 늘렸다 줄였다 하기 편하기 위해서는 service들은 gateway만 알고 연결이 되어 있고 scale을 바꾸는 부분은 따로 관리를 하는 것이 좋기 때문인 것 같다.
신기한 점 두 가지가 있었는데, 한 가지는 read/write component가 나뉘더라고 서로 통신을 주고받아야 한다. 서로의 역할이 나누어지는 것이라 사용하는 부분이 갈리는 것이다. write의 경우에는 distributor로 로그를 받아서 ingestor를 이용해 인메모리로 가지고 있다가 저장소에 저장을 하게 되고, read의 경우 frontend에서 명령을 받고 querier가 로그를 찾는 명령을 실행하는데, 이 때 해당 로그가 ingestor에 캐시가 되어 있다면 굳이 저장소에서 찾지 않고 여기에서 찾는다. 이 기능을 지원하기 위해서 read/write component는 서로 통신할 수 있어야 한다. 이를 docker compose 환경에서는 network로 연결해서 지원했다. 나중에 해당 아키텍처를 설계할 때 하나의 머신에 그런식으로 구성만 해주면 될 것 같다. 여기서 드는 궁금증은 scalable 하게 component를 늘리는 과정에서 서로의 연결을 어떻게 신경을 써주어야 할까? 라는 것이다. 1:1 로 매핑하게 만들 것 같지는 않고, 그렇다고 스케줄링을 이용해서 큐잉을 할 것 같지도 않고.. 흠 자세한 로직은 모르겠지만 굳이 우리 서비스 내에서 이를 여러 개 두고 운영을 해야할까..? 라고 묻는다면 굳이..? 라는 생각이 들어 구성한다면 하나씩만 구성할 것 같다. 사실 그것보다 component를 나눌지 말지 그것부터 고민을 해보아야 한다.
나머지 한 가지는 loki는 scalable 한 것 뿐만아니라 monolithic과 msa 모드를 따로 지원해서 distributor, ingestor, querier 이런식으로 따로 오케스트라 처럼 관리하고 사용할 수 있다고 문서에 나와있었다. 어.. 하지만 이 부분은 굳이 우리 서비스에 이렇게까지 적용을 해야할까 싶어서 그렇게 자세하게 공부하진 않았다.