文章来源:https://c1n.cn/0wHvF

前言

在对公司容器云的日志方案进行设计的时候,发现主流的 ELK(Elasticsearch,Logstash,Kibana)或者 EFK(Elasticsearch,Filebeat or Fluentd,Kibana)比较重,再加上现阶段对于 ES 复杂的搜索功能很多都用不上,最终选择了 Grafana 开源的 Loki 日志系统。

下面我们来介绍下 Loki 的一些基本概念和架构,当然 EFK 作为业界成熟的日志聚合解决方案也是大家应该需要熟悉和掌握的。

简介

Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。

它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签,专门为 Prometheus 和 Kubernetes 用户做了相关优化。

该项目受 Prometheus 启发,官方的介绍就是:Like Prometheus,But For Logs。类似于 Prometheus 的日志系统。

项目地址:

https://github.com/grafana/loki/

与其他日志聚合系统相比,Loki 具有下面的一些特性:

  • 不对日志进行全文索引。通过存储压缩非结构化日志和仅索引元数据,Loki 操作起来会更简单,更省成本。

  • 通过使用与 Prometheus 相同的标签记录流对日志进行索引和分组,这使得日志的扩展和操作效率更高,能对接 alertmanager。

  • 特别适合储存 Kubernetes Pod 日志;诸如 Pod 标签之类的元数据会被自动删除和编入索引。

  • 受 Grafana 原生支持,避免 kibana 和 grafana 来回切换。

架构说明

图片

组件说明

说明如下:

  • Promtail 作为采集器,类比 filebeat

  • Loki 相当于服务端,类比 es

Loki 进程包含四种角色:

  • querier 查询器

  • inester 日志存储器

  • query-frontend 前置查询器

  • distributor 写入分发器

可以通过 Loki 二进制的 -target 参数指定运行角色。

read path

如下:

  • 查询器接受 HTTP/1 数据请求

  • 查询器将查询传递给所有 ingesters 请求内存中的数据

  • 接收器接受读取的请求,并返回与查询匹配的数据(如果有)

  • 如果没有接受者返回数据,则查询器会从后备存储中延迟加载数据并对其执行查询

  • 查询器将迭代所有接收到的数据并进行重复数据删除,从而通过 HTTP/1 连接返回最终数据集

write path

图片

如上图:

  • 分发服务器收到一个 HTTP/1 请求,以存储流数据

  • 每个流都使用散列环散列

  • 分发程序将每个流发送到适当的 inester 和其副本(基于配置的复制因子)

  • 每个实例将为流的数据创建一个块或将其追加到现有块中,, 每个租户和每个标签集的块都是唯一的

  • 分发服务器通过 HTTP/1 链接以成功代码作为响应

部署

本地化模式安装

下载 Promtail 和 Loki:

wget  https://github.com/grafana/loki/releases/download/v2.2.1/loki-linux-amd64.zip
wget https://github.com/grafana/loki/releases/download/v2.2.1/promtail-linux-amd64.zip
安装 Promtail:
$ mkdir /opt/app/{promtail,loki} -pv# promtail配置文件
$ cat <<EOF> /opt/app/promtail/promtail.yaml
server:http_listen_port: 9080grpc_listen_port: 0positions:filename: /var/log/positions.yaml # This location needs to be writeable by promtail.client:url: http://localhost:3100/loki/api/v1/pushscrape_configs:- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: varlogshost: yourhost__path__: /var/log/*.log
EOF# 解压安装包
unzip promtail-linux-amd64.zip
mv promtail-linux-amd64 /opt/app/promtail/promtail# service文件
$ cat <<EOF >/etc/systemd/system/promtail.service
[Unit]
Description=promtail server
Wants=network-online.target
After=network-online.target[Service]
ExecStart=/opt/app/promtail/promtail -config.file=/opt/app/promtail/promtail.yaml
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=promtail
[Install]
WantedBy=default.target
EOFsystemctl daemon-reload
systemctl restart promtail
systemctl status promtail

安装 Loki:

$ mkdir /opt/app/{promtail,loki} -pv# promtail配置文件
$ cat <<EOF> /opt/app/loki/loki.yaml
auth_enabled: falseserver:http_listen_port: 3100grpc_listen_port: 9096ingester:wal:enabled: truedir: /opt/app/loki/wallifecycler:address: 127.0.0.1ring:kvstore:store: inmemoryreplication_factor: 1final_sleep: 0schunk_idle_period: 1h       # Any chunk not receiving new logs in this time will be flushedmax_chunk_age: 1h           # All chunks will be flushed when they hit this age, default is 1hchunk_target_size: 1048576  # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached firstchunk_retain_period: 30s    # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m)max_transfer_retries: 0     # Chunk transfers disabledschema_config:configs:- from: 2020-10-24store: boltdb-shipperobject_store: filesystemschema: v11index:prefix: index_period: 24hstorage_config:boltdb_shipper:active_index_directory: /opt/app/loki/boltdb-shipper-activecache_location: /opt/app/loki/boltdb-shipper-cachecache_ttl: 24h         # Can be increased for faster performance over longer query periods, uses more disk spaceshared_store: filesystemfilesystem:directory: /opt/app/loki/chunkscompactor:working_directory: /opt/app/loki/boltdb-shipper-compactorshared_store: filesystemlimits_config:reject_old_samples: truereject_old_samples_max_age: 168hchunk_store_config:max_look_back_period: 0stable_manager:retention_deletes_enabled: falseretention_period: 0sruler:storage:type: locallocal:directory: /opt/app/loki/rulesrule_path: /opt/app/loki/rules-tempalertmanager_url: http://localhost:9093ring:kvstore:store: inmemoryenable_api: true
EOF# 解压包
unzip loki-linux-amd64.zip
mv loki-linux-amd64 /opt/app/loki/loki# service文件$ cat <<EOF >/etc/systemd/system/loki.service
[Unit]
Description=loki server
Wants=network-online.target
After=network-online.target[Service]
ExecStart=/opt/app/loki/loki -config.file=/opt/app/loki/loki.yaml
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=loki
[Install]
WantedBy=default.target
EOFsystemctl daemon-reload
systemctl restart loki
systemctl status loki

使用

grafana 上配置 loki 数据源

如下图:

图片

grafana-loki-dashsource

在数据源列表中选择 Loki,配置 Loki 源地址:

图片

grafana-loki-dashsource-config

源地址配置 http://loki:3100 即可,保存。

保存完成后,切换到 grafana 左侧区域的 Explore,即可进入到 Loki 的页面:

图片

grafana-loki

然后我们点击 Log labels 就可以把当前系统采集的日志标签给显示出来,可以根据这些标签进行日志的过滤查询:

图片

grafana-loki-log-labels

比如我们这里选择 /var/log/messages,就会把该文件下面的日志过滤展示出来,不过由于时区的问题,可能还需要设置下时间才可以看到数据:

图片

grafana-loki-logs

这里展示的是 promtail 容器里面 / var/log 目录中的日志。

promtail 容器 /etc/promtail/config.yml:

server:http_listen_port: 9080grpc_listen_port: 0positions:filename: /tmp/positions.yamlclients:- url: http://loki:3100/loki/api/v1/pushscrape_configs:
- job_name: systemstatic_configs:- targets:- localhostlabels:job: varlogs__path__: /var/log/*log

这里的 job 就是 varlog,文件路径就是 /var/log/*log。

在 grafana explore 上配置查看日志

查看日志 rate({job="message"} |="kubelet"

算 qps rate({job=”message”} |=”kubelet” [1m])

只索引标签

之前多次提到 loki 和 es 最大的不同是 loki 只对标签进行索引而不对内容索引。下面我们举例来看下。

静态标签匹配模式

以简单的 promtail 配置举例:

scrape_configs:- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: message__path__: /var/log/messages

配置解读:

  • 上面这段配置代表启动一个日志采集任务

  • 这个任务有 1 个固定标签 job=”syslog”

  • 采集日志路径为 /var/log/messages,会以一个名为 filename 的固定标签

  • 在 promtail 的 web 页面上可以看到类似 prometheus 的 target 信息页面

可以和使用 Prometheus 一样的标签匹配语句进行查询。

{job="syslog"}:

scrape_configs:- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: syslog__path__: /var/log/syslog- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: apache__path__: /var/log/apache.log

如果我们配置了两个 job,则可以使用job=~”apachesyslog”进行多 job 匹配;同时也支持正则和正则非匹配。

标签匹配模式的特点

原理如下:
  • 和 prometheus 一致,相同标签对应的是一个流 prometheus 处理 series 的模式

  • prometheus 中标签一致对应的同一个 hash 值和 refid(正整数递增的 id),也就是同一个 series

  • 时序数据不断的 append 追加到这个 memseries 中

  • 当有任意标签发生变化时会产生新的 hash 值和 refid,对应新的 series

loki 处理日志的模式和 prometheus 一致,loki 一组标签值会生成一个 stream。日志随着时间的递增会追加到这个 stream 中,最后压缩为 chunk。当有任意标签发生变化时会产生新的 hash 值,对应新的 stream。

查询过程
  • 所以 loki 先根据标签算出 hash 值在倒排索引中找到对应的 chunk?

  • 然后再根据查询语句中的关键词等进行过滤,这样能大大的提速

  • 因为这种根据标签算哈希在倒排中查找 id,对应找到存储的块在 prometheus 中已经被验证过了

  • 属于开销低

  • 速度快

动态标签和高基数

所以有了上述知识,那么就得谈谈动态标签的问题了。

两个概念:

  • 何为动态标签:说白了就是标签的 value 不固定

  • 何为高基数标签:说白了就是标签的 value 可能性太多了,达到 10 万,100 万甚至更多

比如 apache 的 access 日志:

11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

在 Promtail 中使用 regex 想要匹配 action 和 status_code 两个标签:

scrape_configs:- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: syslog__path__: /var/log/syslog- job_name: systempipeline_stages:static_configs:- targets:- localhostlabels:job: apache__path__: /var/log/apache.log- job_name: systempipeline_stages:- regex:expression: "^(?P<ip>\\S+) (?P<identd>\\S+) (?P<user>\\S+) \\[(?P<timestamp>[\\w:/]+\\s[+\\-]\\d{4})\\] \"(?P<action>\\S+)\\s?(?P<path>\\S+)?\\s?(?P<protocol>\\S+)?\" (?P<status_code>\\d{3}|-) (?P<size>\\d+|-)\\s?\"?(?P<referer>[^\"]*)\"?\\s?\"?(?P<useragent>[^\"]*)?\"?$"- labels:action:status_code:static_configs:- targets:- localhostlabels:job: apacheenv: dev__path__: /var/log/apache.log

那么对应 action=get/post 和 status_code=200/400 则对应 4 个流:

11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] "POST /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] "GET /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] "POST /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

那四个日志行将变成四个单独的流,并开始填充四个单独的块。

如果出现另一个独特的标签组合(例如 status_code =“500”),则会创建另一个新流。

高基数问题

就像上面,如果给 ip 设置一个标签,现在想象一下,如果您为设置了标签 ip,来自用户的每个不同的 ip 请求不仅成为唯一的流。可以快速生成成千上万的流,这是高基数,这可以杀死 Loki。

如果字段没有被当做标签被索引,会不会查询很慢,Loki 的超级能力是将查询分解为小块并并行分发,以便您可以在短时间内查询大量日志数据。

全文索引问题

大索引既复杂又昂贵。通常,日志数据的全文索引的大小等于或大于日志数据本身的大小。

要查询日志数据,需要加载此索引,并且为了提高性能,它可能应该在内存中。这很难扩展,并且随着您摄入更多日志,索引会迅速变大。

Loki 的索引通常比摄取的日志量小一个数量级,索引的增长非常缓慢。

加速查询没标签字段:以上边提到的 ip 字段为例 - 使用过滤器表达式查询。

{job="apache"} |= "11.11.11.11"

loki 查询时的分片(按时间范围分段 grep):

  • Loki 将把查询分解成较小的分片,并为与标签匹配的流打开每个区块,并开始寻找该 IP 地址。

  • 这些分片的大小和并行化的数量是可配置的,并取决于您提供的资源

  • 如果需要,您可以将分片间隔配置为 5m,部署 20 个查询器,并在几秒钟内处理千兆字节的日志

  • 或者,您可以发疯并设置 200 个查询器并处理 TB 的日志!

两种索引模式对比:

  • es 的大索引,不管你查不查询,他都必须时刻存在。比如长时间占用过多的内存

  • loki 的逻辑是查询时再启动多个分段并行查询

日志量少时少加标签:
  • 因为每多加载一个 chunk 就有额外的开销

  • 举例,如果该查询是 {app=”loki”,level!=”debug”}

  • 在没加 level 标签的情况下只需加载一个 chunk 即 app=“loki” 的标签

  • 如果加了 level 的情况,则需要把 level=info,warn,error,critical 5 个 chunk 都加载再查询

需要标签时再去添加:
  • 当 chunk_target_size=1MB 时代表 以 1MB 的压缩大小来切割块

  • 对应的原始日志大小在 5MB-10MB,如果日志在 max_chunk_age 时间内能达到 10MB,考虑添加标签

日志应当按时间递增:
  • 这个问题和 tsdb 中处理旧数据是一样的道理

  • 目前 loki 为了性能考虑直接拒绝掉旧数据

我们创建了一个高质量的技术交流群,与优秀的人在一起,自己也会优秀起来,赶紧点击加群,享受一起成长的快乐。另外,如果你最近想跳槽的话,年前我花了2周时间收集了一波大厂面经,节后准备跳槽的可以点击这里领取!

推荐阅读

  • 放弃密码模式吧!最先进的Spring Cloud认证授权方案在这里

  • 如何写出令人惊叹的设计文档?

  • 下载 145 部盗版视频,被法院判赔偿 70 万元!

··································

你好,我是程序猿DD,10年开发老司机、阿里云MVP、腾讯云TVP、出过书创过业、国企4年互联网6年。从普通开发到架构师、再到合伙人。一路过来,给我最深的感受就是一定要不断学习并关注前沿。只要你能坚持下来,多思考、少抱怨、勤动手,就很容易实现弯道超车!所以,不要问我现在干什么是否来得及。如果你看好一个事情,一定是坚持了才能看到希望,而不是看到希望才去坚持。相信我,只要坚持下来,你一定比现在更好!如果你还没什么方向,可以先关注我,这里会经常分享一些前沿资讯,帮你积累弯道超车的资本。

点击领取2022最新10000T学习资料

轻量级日志 Loki 全攻略相关推荐

  1. 轻量化日志Loki全攻略,再也不会整懵了

    文章来源:https://c1n.cn/0wHvF 目录 前言 简介 架构说明 部署 使用 前言 在对公司容器云的日志方案进行设计的时候,发现主流的 ELK(Elasticsearch,Logstas ...

  2. 阿里Redis最全面试全攻略,读完这个就可以和阿里面试官好好聊聊

    什么是Redis及其重要性? Redis是一个使用ANSI C编写的开源.支持网络.基于内存.可选持久化的高性能键值对数据库. Redis的之父是来自意大利的西西里岛的Salvatore Sanfil ...

  3. MySQL与优化有关的命令_MySQL优化全攻略-相关数据库命令

    MySQL优化全攻略-相关数据库命令 更新时间:2006年11月25日 00:00:00   作者: 接下来我们要讨论的是数据库性能优化的另一方面,即运用数据库服务器内建的工具辅助性能分析和优化. ▲ ...

  4. Retrofit全攻略——进阶篇

    最近事比较多,距离上次写文章已经过去了一个月了.上一篇文章Retrofit全攻略--基础篇 介绍了Retrofit的基础用法,这篇文章介绍点进阶的用法. 打印网络日志 在开发阶段,为了方便调试,我们需 ...

  5. [RHEL5企业级Linux服务攻略]--第3季 DHCP服务全攻略

    1 DHCP原理  1.1 DHCP概述 DHCP(Dynamic Host Configuration Protocal)就是动态主机配置协议哈,可以自动配置主机的IP地址.子网掩码.网关及DNS等 ...

  6. VSCode插件开发全攻略(六)开发调试技巧

    更多文章请戳VSCode插件开发全攻略系列目录导航. 前言 在介绍完一些比较简单的内容点之后,我觉得有必要先和大家介绍一些开发中遇到的一些细节问题以及技巧,特别是后面一章节将要介绍WebView的知识 ...

  7. netfilter/iptables全攻略

    netfilter/iptables全攻略 日期:2011-11-18 点击:113 来源: fp_moon 分享至: 转自:http://www.opsers.org/linux-home/vide ...

  8. Linux下架设邮件服务器全攻略(二)

    Linux下架设邮件服务器全攻略(二) (三)sendmail.cf难以配置,Sendmail的开发人员为sendmail的管理者提供了更加容易理解和配置的sendmail.mc文件. 一般情况下,要 ...

  9. SAP HANA Cloud Connector图文全攻略

    SAP HANA Cloud Connector图文全攻略 http://mp.weixin.qq.com/s?__biz=MjM5OTI2MjgyMA==&mid=2651785635&am ...

最新文章

  1. php把excel变成数组,PHP excel读取excel文件转换为数组
  2. 用开满鲜花的情怀对待每一份求知欲
  3. Problem 64 如何设置Linux系统内存回收的阀值?
  4. 北大计算机考研考什么时候,北大计算机考研复习计划有哪些
  5. config之安全(用户认证)
  6. linux通过yum安装vim,linux/centos系统如何使用yum安装vi/vim?
  7. java静默安装_jdk silent install - JDK的静默安装
  8. 阿里、Uber都在用的Flink你了解多少?
  9. 《智慧城市》顶层设计解读
  10. 三菱FX系列PLC以太网连接组态王软件
  11. 酒店抖音小程序开发方案
  12. CentOS7.6 安装Oracle12C(上)
  13. ion-slides 图片只能滑动一半、图片索引错误导致图片显示错误(缓存问题导致的)
  14. iOS 苹果内购详细步骤
  15. 情侣纪念日网站html5源码教程
  16. fail-fast 机制是什么?(详解)
  17. 帮派红包 概率_电子游戏如何教我关于连锁帮派
  18. 不再为Apache进程淤积、耗尽内存而困扰((转))
  19. pvq真值表_真值表在命题教学中的几个应用
  20. 二项式定理的应用(快速幂+组合数的计算)

热门文章

  1. linux 内功修炼之一 cpu
  2. 赠书!《R语言数据分析与可视化从入门到精通》
  3. 动态规划之最长回文子串
  4. 前后端整合+Request(请求转发)+respon(重定向)+get+post+Filter过滤器
  5. 7039s芯片(F4plus、M3 4K、M6 4K、F5PLUS、A1-4K)开机不进主界面的解决办法
  6. 基于Jsp的手机应用商店的设计与实现mysql
  7. 如何化解频临离婚边缘的婚姻危机
  8. root_path运用python_Python current_app.root_path方法代碼示例
  9. 微信小程序实现简单的点击切换功能(微信开发者工具)
  10. 高级查询(mysql)