공부 목적으로 설치해 보는 과정을 정리한 것이기 때문에 실제 운영과 다릅니다.
Loki 소개
https://github.com/grafana/loki
Loki에 대한 소개를 보면 다음과 같다.
"Like Prometheus, but for logs"
Prometheus가 metric을 시계열 데이터로 저장하기 위해 사용된다면 Loki는 log 데이터를 저장하기 위해 사용된다.
https://grafana.com/docs/loki/latest/fundamentals/overview/
Loki는 log data를 효율적으로 보관하기 위해 최적화된 데이터 저장소이다.
다른 logging system과 다르게 Loki index는 label에서 작성되며 원래 log message는 색인화되지 않는다.
Prometheus가 저장과 polling을 담당한 것과 달리 Loki는 저장을 담당하고 application에서 push를 해주는 역할을 해주는 agent가 필요하다.
Promtail agent는 Loki를 위해 설계되었지만 그 외에 다른 많은 agent가 Loki와 원활하게 통합된다.
Loki는 stream을 indexing 한다.
각 steam은 고유한 label set과 연결된 log 집합을 식별한다.
label의 quality set은 간결하고 효율적인 query 실행을 허용하는 index 생성의 핵심이다.
LogQL은 Loki의 query language이다.
Loki의 특징은 다음과 같다.
- log indexing을 위한 효율적인 memory 사용
- multi-tenancy
- LogQL - Prometheus의 query language인 PromQL과 유사하며, log data에서 metric을 생성하는 것이 용이함.
- Scalability - 단일 바이너리로 사용할 수도 있으나 component 별 microservice로 실행될 수도 있음
- Flexibility - 많은 agent가 플러그인을 지원
- Grafana 통합
https://grafana.com/docs/loki/latest/operations/storage/
Loki는 chunk와 index라는 두 가지 유형의 데이터를 저장해야 한다.
Loki는 별도의 stream으로 log를 수신하며 각 steam은 tenant ID와 label set으로 고유하게 식별된다.
stream의 log 항목이 도착하면 chunk로 압축되어 chunk 저장소에 저장된다.
index는 각 steam의 label set를 저장하고 개별 chunk에 연결한다.
index에 대해 다음 저장소가 지원된다.
- Single Store (boltdb-shipper)
- Amazon DynamoDB
- Google Bigtable
- Apache Cassandra
- BoltDB
chunk에 대해 다음 저장소가 지원된다.
- Amazon DynamoDB
- Google Bigtable
- Apache Cassandra
- Amazon S3
- Google Cloud Storage
- FlieSystem
- Baidu Object Storage
기본 설정은 storage가 filesystem이며 Amazon S3의 경우 로컬에서 개발 시 minio를 사용할 수도 있다.
https://blog.min.io/how-to-grafana-loki-minio/
설정 파일에 대한 자세한 내용은 아래 링크에서 확인할 수 있다.
https://grafana.com/docs/loki/latest/configuration/
common 아래에 설정을 하면 전체가 공통으로 사용할 설정을 하게 된다.
Loki는 component 별 microservice로 구성할 수 있기 때문에 공통 설정에 대한 항목이 있는 듯하다.
https://grafana.com/docs/loki/latest/fundamentals/architecture/components/
Loki의 component는 대략 아래와 같이 있다.
- Distributor - client가 수신하는 stream을 처리하는 역할, steam의 유효성을 확인하고 여러 ingester로 병렬로 전송을 적절하게 제어
- Ingester - storage에 log data를 저장하고 write path 및 read path의 memory 내 쿼리에 대한 log data를 반환
- Query frontend - query 발송의 API endpoint를 제공하는 선택적 서비스
- Querier - LogQL을 사용하여 query를 처리하고 ingester와 storage에서 log를 가져옴
loki 설치하기
https://grafana.com/docs/loki/latest/installation/
로컬에서 개발을 위해 다음과 같이 구성하였다.
기존에 설치했었던 minio에 bucket을 추가하고 loki storage로 지정하였다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: loki-deployment
labels:
app: loki
spec:
replicas: 1
selector:
matchLabels:
app: loki
template:
metadata:
labels:
app: loki
spec:
securityContext:
runAsUser: 0
containers:
- name: loki
image: grafana/loki:latest
args:
- "-config.file=/etc/loki/loki.yaml"
ports:
- name: loki
containerPort: 3100
volumeMounts:
- name: loki-config
mountPath: /etc/loki
- name: loki-data
mountPath: /loki
volumes:
- name: loki-config
configMap:
name: loki-configmap
items:
- key: loki.yaml
path: loki.yaml
- name: loki-data
persistentVolumeClaim:
claimName: loki-data-pvc
---
apiVersion: v1
kind: ConfigMap
metadata:
name: loki-configmap
data:
loki.yaml: |
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
replication_factor: 1
storage:
s3:
endpoint: minio-service:9000
s3forcepathstyle: true
bucketnames: loki
access_key_id: minio_access_key
secret_access_key: minio_secret_key
insecure: true
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: s3
schema: v11
index:
prefix: index_
period: 24h
---
apiVersion: v1
kind: Service
metadata:
name: loki-service
labels:
app: loki
spec:
selector:
app: loki
ports:
- port: 3100
targetPort: 3100
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: loki-data-pv
labels:
app: loki-data-pv
spec:
storageClassName: ""
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/f/dev/data/loki-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: loki-data-pvc
spec:
volumeName: loki-data-pv
storageClassName: ""
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
/metrics 주소를 호출하여 확인할 수 있다.
# HELP cortex_consul_request_duration_seconds Time spent on consul requests.
# TYPE cortex_consul_request_duration_seconds histogram
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.005"} 10156
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.01"} 10158
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.025"} 10160
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.05"} 10161
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.1"} 10161
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.25"} 10161
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="0.5"} 10161
cortex_consul_request_duration_seconds_bucket{kv_name="ingester-ring",operation="CAS loop",status_code="200",le="1"} 10161
// ... 이하 생략
Promtail 소개
Loki가 로그를 저장하는 역할을 하면 Promtail은 application에서 로그를 전달하는 agent의 역할을 한다.
Promtail 이외에도 Bit, Fluentd, LogStash 등을 사용할 수 있다.
kubernetes는 node 별로 /var/log/pods 아래에 모든 pod의 로그가 기록된다.
daemonset으로 설정하고 node별로 로그를 수집하도록 처리를 하면 된다.
promtail의 설치는 아래 가이드 문서를 참고하면 된다.
https://grafana.com/docs/loki/latest/clients/promtail/installation/
설치 방식은 sidecar, daemonset 방식이 있는데 daemonset 방식을 추천한다고 한다.
- daemonset - 각 노드마다 promtail pod가 실행되어 해당 노드 장비에서 실행 중인 파드의 로그를 추적
- sidecar - 각 파드에 container로 추가되어 실행, 해당 파드 내부에서 로그 파일을 읽어서 Loki로 전송
pod마다 agent 형태로 설정하는 것보다 daemonset을 하나 띄워 해당 node의 pod들을 찾아 로그를 수집하는 것이 훨씬 편한 것 같다.
Prometheus가 저장소와 polling 역할을 같이 담당하는 반면 Promtail은 저장소의 역할은 하지 않고 로그를 찾아 저장소로 push 하는 역할을 한다.
하지만 설정 방식이나 문법은 크게 차이가 없다.
Promtail 설치하기
아래와 같이 설정하였다.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail-daemonset
labels:
app: promtail
spec:
selector:
matchLabels:
app: promtail
template:
metadata:
labels:
app: promtail
spec:
securityContext:
runAsUser: 0
containers:
- name: promtail
image: grafana/promtail
args:
- -config.file=/etc/promtail/promtail.yaml
ports:
- name: promtail
containerPort: 3101
volumeMounts:
- name: promtail-config
mountPath: /etc/promtail
- name: promtail-run
mountPath: /run/promtail
- name: promtail-containers
mountPath: /var/lib/docker/containers
readOnly: true
- name: promtail-pods
mountPath: /var/log/pods
readOnly: true
volumes:
- name: promtail-config
configMap:
name: promtail-configmap
items:
- key: promtail.yaml
path: promtail.yaml
- name: promtail-run
hostPath:
path: /run/promtail
- name: promtail-containers
hostPath:
path: /var/lib/docker/containers
- name: promtail-pods
hostPath:
path: /var/log/pods
---
apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-configmap
data:
promtail.yaml: |
server:
enable_runtime_reload: true
log_level: info
http_listen_port: 3101
clients:
- url: http://loki-service:3100/loki/api/v1/push
positions:
filename: /run/promtail/positions.yaml
target_config:
sync_period: 10s
scrape_configs:
# - job_name: system
# static_configs:
# - targets:
# - localhost
# labels:
# job: varlogs
# __path__: /var/log/pods/**/*.log
- job_name: bluesky-spring-job
pipeline_stages:
- docker: {}
kubernetes_sd_configs:
- role: pod
selectors:
- role: pod
# field: status.phase=Running
relabel_configs:
- source_labels: [__meta_kubernetes_pod_container_name]
action: keep
regex: spring
- source_labels: [__meta_kubernetes_pod_label_app]
target_label: application
- source_labels: [__meta_kubernetes_pod_name]
target_label: instance
- source_labels: [__meta_kubernetes_pod_container_name]
target_label: container
- replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_uid
- __meta_kubernetes_pod_container_name
target_label: __path__
---
apiVersion: v1
kind: Service
metadata:
name: promtail-service
labels:
app: promtail
spec:
selector:
app: promtail
ports:
- port: 3101
targetPort: 3101
Promtail에 웹으로 접근하면 Prometheus와 거의 유사한 UI로 검색된 서비스를 확인할 수 있다.
Grafana에서 로그 확인하기
Grafana Configuration에서 Add new data source로 Loki를 추가해 주고
explore에서 조회하면 로그가 정상적으로 수집되는 것을 확인할 수 있다.
여기까지 간단하게 Promtail과 Loki를 설치하고 Grafana에서 확인해 보았다.
이제까지의 글을 정리해 보면 Grafana를 대시보드로 사용하여
- log - Promtail + Loki
- metric - Prometheus
- trace - Spring Project(Zipkin, Micrometer, Otel exporter) + OpenTelemetry Collector + Tempo
와 같이 구성해 보았다.
Otel이 API에 대한 스펙을 공통화하려고 하고 있지만 현재로선 Promtail이나 Prometheus의 편리함을 버릴 만큼은 아닌 것 같다.
(이후엔 또 어떻게 바뀔지 모르겠지만...)
Loki와 Tempo를 연계해 좀 더 상세한 설정을 하는 부분에 대해서는 좀 더 찾아본 후 정리하려고 한다.
'Study > Docker & Kubernetes' 카테고리의 다른 글
OpenTelemetry Collector extension 사용해 보기 (0) | 2024.12.27 |
---|---|
spinnaker resource (component sizing) 설정해 보기 (0) | 2023.04.07 |
kubernetes pod에 resource 설정해 보기 (0) | 2023.04.06 |
kubernetes에 OpenTelemetry Collector, Grafana Tempo를 설치하고 tracing 구현해 보기 (2) | 2023.03.18 |
helm chart로 kubernetes yaml 파일 만들기 (0) | 2023.03.17 |
kubernetes에 sonarqube 설치 & jenkins에서 사용해 보기 (0) | 2023.03.16 |
kubernetes에 Prometheus, Grafana 설치하고 metric 정보 수집해 보기 (1) | 2023.03.15 |
kubernetes ConfigMap, Secret 사용해 보기 (0) | 2023.03.11 |
kubernetes PersistentVolume, PersistentVolumeClaim 사용해 보기 (0) | 2023.03.11 |
Rancher Desktop에서 docker 명령어 사용하기 (0) | 2022.10.20 |