首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

运维加薪技术——日志采集方案loki

一、介绍

为什么需要日志采集

日志采集主要解决日志的统一存储和查询的问题:1. 避免非持久化日志的丢失 2. 避免频繁定位并登录宿主机查看

为什么需要Loki

Loki和常用的EFK(Elasticsearch + Filebeat + Kibana)日志采集方案类似,基本架构都是在应用节点有代理进程(Promtail)收集日志,传输到集中化的服务(Loki)存储和索引,最后通过图形化界面(Grafana)统一查询。

Loki与EFK的主要区别在于:1. Loki不会对原始的日志数据进行全文索引,而是采用了Prometheus的标签思想,只对标签索引 2. 日志数据本身也会被压缩,并以chunks(块)的形式存储在对象存储或者本地文件系统 3. Loki能够以微服务模式运行,也就是把自身的各个模块分解出单个进程运行。比如,通过横向扩展多个查询器(Querier)模块可提高查询性能。

这几点区别使Loki更加轻量和灵活,特别适合云原生环境。

二、实践

部署Loki

通过Helm可以快速在K8S中部署Loki,并有多种参数配置提供选择:

# 部署Loki和Promtail

helm upgrade --install loki --namespace=loki loki/loki

# 部署Loki,Promtail和Grafana

helm upgrade --install loki loki/loki-stack --set grafana.enabled=true

# 部署Loki,Promtail和Grafana 并配置持久化存储

helm upgrade --install loki loki/loki-stack --set grafana.enabled=true,loki.persistence.enabled=true,loki.persistence.storageClassName=nfs-client,loki.persistence.size=5Gi

这种方式部署Loki由StatefulSet控制,Promtail则由DaemonSet控制。另外,Promtail也可以以K8S常用的sidecar模式运行,为每个业务Pod单独配置。

部署完成后可修改Grafana的Service类型为NodePort,方便在本地浏览器访问:

kubectl edit service/loki-grafana -n loki使用Loki

浏览器访问Grafana,以admin登录,密码可从以下命令行获取:

kubectl get secret --namespace loki loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

在Grafana的侧边栏选择Configuration > Data Sources,点击Add data source按钮,选择Loki数据源,在URL中填写Loki的地址。因为是部署在K8S中,所以填写的是K8S内部域名形式。

配置好数据源之后,侧边栏选择Explore并且选择label就可以查看日志。

也可以自己输入Loki自己定义的日志查询语言LogQL查询。

# 查询所有包含cleaning的loki日志

{job="loki/loki"} |= "cleaning"

LogQL支持三种Parser(json,logfmt和regexp)。使用json格式的日志比较少见,而regexp又需要写正则表达式不太方便,所以推荐日志都统一使用logfmt的格式。Prometheus,Grafana,包括Loki自身都是使用logfmt格式的日志。

# 查询日志级别为info的loki日志

{job="loki/loki"} | logfmt | level="info"配置LokiLoki配置

Loki配置主要就是配置多租户模式,在配置文件中添加auth_enabled: true即可开启。开启后所有的请求(推送和查询)都必须带上一个租户的HTTP Header(X-Scope-OrgID)。租户之间的日志相互隔离,并且可以配置每个租户推送日志的速率,防止一个租户下的日志狂打从而拖慢其他租户的正常日志采集。

# Per-user ingestion rate limit in sample size per second. Units in MB.

# CLI flag: -distributor.ingestion-rate-limit-mb

[ingestion_rate_mb: <float> | default = 4]

# Per-user allowed ingestion burst size (in sample size). Units in MB.

# The burst size refers to the per-distributor local rate limiter even in the

# case of the "global" strategy, and should be set at least to the maximum logs

# size expected in a single push request.

# CLI flag: -distributor.ingestion-burst-size-mb

[ingestion_burst_size_mb: <int> | default = 6]

开启多租户模式后,Grafana的数据源也需要作相应配置,否则无法正常使用。

Promtail配置

Promtail配置主要就是配置抓取目标,Helm部署后默认抓取配置如下(取其中一个job):

scrape_configs:

- job_name: kubernetes-pods-name

pipeline_stages:

- docker: {}

kubernetes_sd_configs:

- role: pod

relabel_configs:

- source_labels:

- __meta_kubernetes_pod_label_name

target_label: __service__

- source_labels:

- __meta_kubernetes_pod_node_name

target_label: __host__

- action: drop

regex: ''

source_labels:

- __service__

- action: labelmap

regex: __meta_kubernetes_pod_label_(.+)

- action: replace

replacement: $1

separator: /

source_labels:

- __meta_kubernetes_namespace

- __service__

target_label: job

- action: replace

source_labels:

- __meta_kubernetes_namespace

target_label: namespace

- action: replace

source_labels:

- __meta_kubernetes_pod_name

target_label: pod

- action: replace

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__

kubernetes_sd_configs:

- role: pod

K8S服务发现配置,角色为pod时可发现所有的pod,并将k8s的一些元数据保存在原标签里,供relabel阶段使用。

# pod名

__meta_kubernetes_pod_name

# pod中某个label的值

__meta_kubernetes_pod_label_<labelname>

# pod所在宿主机名

__meta_kubernetes_pod_node_name:

...

pipeline_stages:

- docker: {}

pipeline是预置一些处理的集合,在K8S的环境下都会启用docker阶段,处理docker下的json-file日志。pipeline有个tenant阶段,在这里可配置租户ID,如:

# 静态租户ID

pipeline_stages:

- docker: {}

- tenant:

value: kubernetes-pods-name

# 动态租户ID

pipeline_stages:

- docker: {}

- tenant:

source: __meta_kubernetes_pod_name

在抓取配置之外还可以配置一个租户ID,作为这个Promtail进程的全局租户ID。

relabel_configs:

- source_labels:

- __meta_kubernetes_pod_label_name

target_label: __service__

relabel的配置和Prometheus的是一模一样的,可以基于已经发现的元标签,动态的添加或者覆盖新标签。详情可参考Prometheus文档。

Promtail也可以直接部署在物理机上,监听非容器进程的日志。配置里去掉了pipeline和K8S源标签的处理,并使用了一个静态标签(job=varlogs)。

server:

http_listen_port: 9080

grpc_listen_port: 0

positions:

filename: /tmp/positions.yaml

clients:

- url: http://localhost:3100/loki/api/v1/push

scrape_configs:

- job_name: system

static_configs:

- targets:

- localhost

labels:

job: varlogs

__path__: /var/log/*log多行日志的问题

经实践发现,Loki目前没有支持多行日志的处理,导致错误栈的每一行都被识别为一行日志,对错误日志的查询定位非常不友好。

这个问题暂时没有太好的解决方法,但Github Issues上官方已经跟进,并且进入了2.2的Milestone。

应该避免的问题

避免使用动态标签去匹配具有较大范围的可能值,比如ip值。这样会导致Loki建立一个巨大的索引,性能非常差。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O2nlWY1ZwjvGUKO7K3yBEO2A0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券