Loki 실 적용 내역 공유

Jerry(이정훈)
10 min readApr 25, 2021

오늘도 얇디 얇은 습자지, Getting Started 수준입니다 ^^ (언제쯤 우아하게 아키텍쳐 까지 잘 전달이 가능할지) Kube 환경 Logging 솔루션 Loki 소개해 드립니다. 현재 잘 사용 중인데 실 적용 시 고려했던 사항 위주로 실습과 함께 전달해 드립니다.

TL;DR

  • kube 환경 로그는 기존 legacy 시스템과 다르게 application 로그가 사라지고(pod 재시작), pod 수도 너무 많고 (1,000개 pod 넘는건 일도 아님) 또 여러 pod 로그를 동시에 보아야 하는 제약 사항이 있다. 새로운 log aggregation 시스템 필요.
    : 하지만 k logs -f {pod 이름} 동일 명령어로 모든 pod 로그 볼 수 있는 장점이 있다. (application 별 로그 파일 찾는 것도 일이다)
  • Loki 사용하면 편하고 쉽다. (ELK에 비하여) 자원도 많이 안 먹고.
    : 로그 저장 기간(rotate), disk 용량 설정(초기 설치 시) 필요
    : LogQL, 기본 Regular Expression query 명령어 몇개는 알고 있어야 함

기존 Legacy 로그 시스템 차이점

(VM 환경에 Elastic 사용하시면 해당없지만) 기존 VM 환경에서는 application 로그를 보기 위해서 개별 서버 접속해서 application 별 로그 파일을 일일이 봐야 합니다. 로그 파일은 사라지지 않고 항상 그자리에 있습니다.

하지만 Kube, 컨테이너는 다릅니다. 먼저 Application, 즉 POD 로그는 파일이 아니라 STDOUT로 처리됩니다. (권고 사항) STDOUT 형태로 출력되는 로그는 tail -f {application 별 로그 파일} 아니라 간단히 k logs -f {POD 이름} 하시면 됩니다.

컨테이너의 로그 설정은 Container Runtime(docker, crio, containerd 등)을 따라 갑니다. 도커 기준 로그 파일 위치는 /var/log/container 입니다. kube 역시 로그를 관리하는데 /var/log/pods(kubelet 설정) 입니다. 위 POD의 STDOUT 로그가 저장되는 위치입니다. 추가로 kubelet 기본 로그 용량은 10Mi 입니다. (kubelet 설정, — container-log-max-size string Default: `10Mi`) 10Mi 넘어가는 POD 로그는 처음 로그가 조회되지 않습니다.

(의아하게(?) 2개 로그 파일이 동일한 것 같습니다. 아마도 컨테이너와 kubelet 별도 시스템이라 그런 것 같습니다.)

(참고로 도커 실행 파일 위치는 /var/lib/docker)[admin@node1 docker]$ sudo du -hs /var/lib/docker
307G /var/lib/docker

컨테이너는 휘발성이라 로그 역시 컨테이너가 리스타트 되면 사라집니다. POD가 리스타트되어 POD 죽은 이유를 찾아야 되는데, 로그가 없는 경우가 발생하여 난감합니다.

[spkr@erdia22 ~ (scluster:msademo)]$ k delete pod adservice-6b74979749-rbj58
pod "adservice-6b74979749-rbj58" deleted
[spkr@erdia22 ~ (scluster:msademo)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
adservice-6b74979749-ppxvs 0/1 Running 0 7s 10.10.100.42 dia02 <none> <none>
adservice-6b74979749-rbj58 0/1 Terminating 0 3h42m <none> dia02 <none> <none>
POD가 사라져서 k logs -f 할 수 없습니다.

추가로 kube는 특성 상 pod 떠다 죽었다, node 살았다 죽었다가 자유(?)롭습니다. 그래서 POD는 항상 복수로 띄우는 것을 권고합니다. 여러 POD가 동시에 실행 중이므로 로그 역시 여러 POD LOG를 동시에 보셔야 합니다.

[spkr@erdia22 ~ (spkn02:nginx)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-hello-c97cdb45c-5v9xq 1/1 Running 1 3d8h 10.233.90.61 node1 <none> <none>
nginx-hello-c97cdb45c-bkdxd 1/1 Running 1 3d8h 10.233.90.62 node1 <none> <none>
nginx-hello-c97cdb45c-twsf2 1/1 Running 1 3d8h 10.233.90.60 node1 <none> <none>
nginx-hello-c97cdb45c-zqt74 1/1 Running 3 3d7h 10.233.92.41 node3 <none> <none>
(하나의 로그가 아닌 복수 POD 로그 보셔야 합니다. k log 대신 kubetail 추천합니다.)

이러한 특성에 맞게 새로운 로그 시스템이 필요 합니다.

Loki for Prometheus for Logging

Loki는 kubernetes 환경에서 사용할 수 있는 logging 시스템 입니다. 기존에 많이 사용하시는 Elastic에 비하여 사용하기 쉽고 리소스를 적게 사용하는 것이 가장 큰 장점입니다.

참조

또한 Grafana Loki는 Prometheus에 영감을 받아 탄생한 클라우드 네이티브 인프라를 위한 로깅 서비스입니다. Like Prometheus, but for logs!라는 문구를 사용하며 그 상징성을 다시금 보여줍니다.

Loki의 경우 단일 로그 라인을 그대로 처리한다는 아이디어를 기반으로 만들어져 있어 전체 텍스트를 인덱싱하는 방식이 아닌 Label을 사용하여 로그를 그룹화하는 방식을 사용합니다. 이 방식의 경우 로그 처리에 대해 인덱싱을 하는 기존의 Elasticsearch와 비교하였을 때 훨씬 효율적이며 확장성이 좋습니다. 복잡한 작업이 필요 없고 로그들을 그룹화시켜 즉각적인 확인을 하고자 하였을 때 빛을 발휘합니다.

설치는 Helm 차트를 이용하여 쉽게 가능하므로 생략 하겠습니다. 한가지 주의 사항으로 로그 데이터의 보관 주기(retention)를 미리 지정하시는 게 낫습니다. 아래는 4주(24*7*4) 설정 입니다.

https://grafana.com/docs/loki/latest/operations/storage/retention

저같은 경우는 4주 보관 설정인데, 약 635G 사용 중 이네요. 각 회사의 로그 보관 기관, 백업 및 이중화 정책 등에 맞게 수정이 필요합니다.

: LOKI PVC로 openebs localpv 사용 하였습니다.

  • 4주 전 로그까지 보이네요.

설치가 완료되면 아래와 같이 POD 확인이 가능합니다.

[spkr@erdia22 ~ (dz-group:loki)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
loki-0 1/1 Running 0 20d 192.168.90.98 node1 <none> <none>
loki-grafana-7866bbcc8b-nnp8x 1/1 Running 0 35d 192.168.90.63 node1 <none> <none>
loki-promtail-nb47x 1/1 Running 2 21d 192.168.90.82 node1 <none> <none>
loki-promtail-q86h7 1/1 Running 0 21d 192.168.92.92 node3 <none> <none>
loki-promtail-vp5cg 1/1 Running 0 21d 192.168.96.13 node2 <none> <none>
loki-promtail-wlpx4 1/1 Running 0 21d 192.168.105.30 node4 <none> <none>

현재 운영 중인 시스템인데, 메모리 사용량 4.5G로 Resource 사용량이 양호 합니다.

Promtail이 daemonset으로 모든 노드마다 실행됩니다. loki POD가 중앙에서 Promtail 로그를 Pull 방식으로 가져 옵니다.

Grafana 에서 Datasource를 Loki를 선택합니다. 이제 각 POD의 로그 확인이 가능합니다. 아래와 같이 시간을 선택하시면 해당 시간 대 전체 POD 로그가 선택됩니다. 아래 화면 중앙 ‘Unique labels’ 선택하시면 POD 별 구분이 가능한데 종료된 POD 로그도 같이 포함된 걸 확인 가능합니다.

늘 그렇지만 문제는 로그가 너무 많다는 것입니다. 따라서 적절한 filter를 통한 검색이 필수적입니다. Log 검색을 위하여 Loki는 LogQL(Query Language)를 사용합니다. Kube Label을 기준으로 POD 로그를 grep 하는 툴 정도라 생각하시면 됩니다.

참조

https://megamorf.gitlab.io/cheat-sheets/loki/

간단한 예시로 알아 보겠습니다.

Error log만 전체 보고 싶다

  • pod, namespace 등 선택하고 |= “error” 등으로 Filtering

전체 pod의 error 검색하려면?

  • 정규 표현식 =~”.*” 사용

특정 단어 포함하지 않도록

  • prometheus만 포함하지 않도록 검색하기
    : !~ 사용

컨테이너 별, POD 별 검색

기타 정규표현식 사용 가능

이상 Loki 101 입니다.

Diamanti 및 Managed Kubernetes Service 문의
: leejunghoon@spkr.co.kr

--

--

Jerry(이정훈)

DevOps/Automation Engineer 60살까지 콘솔 잡는 엔지니어를 목표로 느리게 생각하고 있습니다.