쿠버네티스 교육

18. Kube 교육 - Loki Logging System

Jerry_이정훈 2021. 6. 4. 16:48
728x90

실습

  • Loki Helm 설치
  • POD 로그 조회 및 Filtering 

Why Loki

kube 로그는 기존 VM legacy 시스템과 다르게 로그가 저장되지 않고, pod 수도 너무 많고 (1,000개 pod 넘는건 일도 아님) 또 여러 pod 로그를 동시에 보아야 하는 제약 사항이 있습니다. 이에, 기존 VM 환경 로그 시스템이 아닌 새로운 통합 log 시스템이 필요 합니다.

 

Loki는 기존에 많이 사용하시는 ELK, FluentD 로그 시스템에 비하여 resource 소비도 작고 설치도 간편하여 최근에 많이 사용하고 있습니다. 저희 고객사도 현재 잘 사용 중인데 적용 시 고려했던 사항 위주로 실습과 함께 알아 보겠습니다.

기존 VM Legacy 로그 시스템 차이점

(VM 환경에 Elastic 사용하시면 해당없지만) 기존 VM 환경에서는 application 로그를 보기 위해서 개별 서버 마다 접속해서 application 별 로그 파일을 일일이 확인해야 합니다. 각 Application 별로 저장하는 로그 파일 경로가 달라서 각 파일을 외우는 것도 쉽지 않았습니다. 물론 Application이 재시작 되어도 로그 파일은 사라지지 않고 항상 그자리에 있기는 합니다. 

 

하지만 Kube, 컨테이너 환경은 다릅니다. 먼저 Application, 즉 POD 로그를 STDOUT 으로 처리 하도록 이미지를 생성합니다.  STDOUT 형태로 출력되는 로그는  각 서버마다 접속하여 tail -f {application 별 로그 파일} 명령어로 확인하는 것이 아니라 원격 개인 PC에서 간단히 k logs -f {POD 이름} 하시면 개별 POD의 로그를 조회 할 수 있습니다. 

NGINX POD Log 조회

로그 관련 설정은 각 호스트 노드의 Container Runtime(docker, crio, containerd 등) 설정을 따라 갑니다. 도커 기준 개별 POD의 로그 파일은 /var/log/container 디렉토리에 저장 됩니다. kube 역시 Runtime과 별개로 로그를 관리하는데 위치는 /var/log/pods 입니다. 참고로 kubelet에 설정되어 있는 기본 로그 용량은 Max 10Mi 입니다.  (kubelet 설정, --container-log-max-size string, Default: `10Mi`) 만약 POD의 로그가 10Mi 넘어간다면 초과된 로그는 조회가 되지 않습니다.

 

(의아하게(?) 2개 로그 파일이 동일한 것 같습니다. 컨테이너와 kubernetes가 별도로 로그 관리해서 그런 것 같습니다.)

 

(참고로 도커 이미지가 실행되는 호스트 노드 디렉토리는 /var/lib/docker 입니다.)

[admin@node1 docker]$ sudo du -hs /var/lib/docker
307G    /var/lib/docker

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

[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 로그를 동시에 조회해야 하므로 여러 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 Logging

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

참조
https://www.notion.so/Prometheus-Grafana-Loki-676f31a0a24b4075a5499b31af3fa35d
 

Prometheus 와 Grafana Loki를 활용한 서버 모니터링 환경 구축

목차

www.notion.so

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

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

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

[spkr@erdia22 01.Loki (k3s:monitoring)]$ helm repo add grafana https://grafana.github.io/helm-charts
"grafana" already exists with the same configuration, skipping

[spkr@erdia22 01.Loki (k3s:monitoring)]$ helm pull grafana/loki-stack

[spkr@erdia22 01.Loki (k3s:monitoring)]$ tar xvfz loki-stack-2.4.1.tgz
loki-stack/Chart.yaml
(이하 생략)

[spkr@erdia22 01.Loki (k3s:monitoring)]$ mv loki-stack loki-stack-2.4.1

[spkr@erdia22 01.Loki (k3s:monitoring)]$ cd loki-stack-2.4.1/

[spkr@erdia22 loki-stack-2.4.1 (k3s:monitoring)]$

[spkr@erdia22 loki-stack-2.4.1 (k3s:monitoring)]$ k create ns loki
namespace/loki created

[spkr@erdia22 loki-stack-2.4.1 (k3s:monitoring)]$ kns loki
Context "k3s" modified.
Active namespace is "loki".

[spkr@erdia22 loki-stack-2.4.1 (k3s:loki)]$ helm install loki -f my-values.yaml .
NAME: loki
LAST DEPLOYED: Wed Jun 16 08:16:39 2021
NAMESPACE: loki
STATUS: deployed
REVISION: 1
NOTES:
The Loki stack has been deployed to your cluster. Loki can now be added as a datasource in Grafana.

See http://docs.grafana.org/features/datasources/loki/ for more detail.

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

 

Retention

Loki Storage Retention Retention in Loki is achieved through the Table Manager. In order to enable the retention support, the Table Manager needs to be configured to enable deletions and a retention period. Please refer to the table_manager_config section

grafana.com

 

 제 운영 시스템은 4주 보관 설정인데, 현재 약 635G 사용하고 있습니다. 각 회사의 로그 보관 기관, 백업 및 이중화 정책 등에 맞게 수정이 필요합니다. 

  • 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>           

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

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

 

Grafana 연동

중앙 관리를 위한 Grafana Loki 설정이 필요합니다. 먼저, Grafana 에서 Datasource로 Loki를 선택합니다. Loki를 추가하기 위해서는 Loki Service 이름을 확인 합니다.

 

이전 포스팅에서 생성한 Grafana 페이지에 다시 접속합니다. 포트는 monitoring 네임 스페이스 grafana 서비스를 참조합니다.

[spkr@erdia22 loki-stack-2.4.1 (k3s:loki)]$ k get svc -n monitoring
NAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)
 AGE
(생략)
prometheus-grafana                        NodePort    10.43.139.187   <none>        80:30414/TCP
 43m

먼저, 화면 좌측 Data Sources 선택 합니다.

화면 우측 'Add data source'를 클릭 하여 아래와 같이 화면 중앙 Loki를 선택합니다. 

Loki 선택 하시고 아래와 같이 화면 중앙 HTTP - URL 에 Loki Service 이름을 추가 합니다. (http://loki-headless.loki:3100)

아래 'Save & Test'를 클릭 하셔서 정상적으로 data loading되면 설정이 정상적으로 완료 된 것 입니다.

loki 서비스 이름은 아래와 같이 loki 네임스페이스의 이름으로 확인 합니다.

[spkr@erdia22 loki-stack-2.4.1 (kspray:loki)]$ k get svc
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
loki            ClusterIP   10.233.15.61   <none>        3100/TCP   2m38s
loki-headless   ClusterIP   None           <none>        3100/TCP   2m38s

이제 Loki 설정이 완료 되었습니다.

 

각 POD의 로그를  Grafana에서 확인 가능합니다. 먼저, 화면 좌측 Explore 선택합니다.

Loki 화면에서 화면 중앙 ‘Unique labels’ 선택하시면 POD 별 구분이 가능 합니다. 

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

 

참조

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

 

Cheat Sheet - Loki - Seb's IT blog

LogQL: Log Query Language Loki comes with its very own language for querying logs called LogQL. LogQL can be considered a distributed grep with labels for filtering. A basic LogQL query consists of two parts: the log stream selector and a filter expression

megamorf.gitlab.io


 

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

 

Error log만 전체 보고 싶다

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

전체 pod의 error 검색하려면? 

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

특정 단어 포함하지 않도록 

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



컨테이너 별, POD 별 검색

기타 정규표현식 사용 가능

 

이상 Loki 101 입니다. 

반응형