news 2026/9/4 14:48:23

告别臃肿 ELK:使用 Loki + Promtail + Grafana 搭建轻量级日志平台

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
告别臃肿 ELK:使用 Loki + Promtail + Grafana 搭建轻量级日志平台

告别臃肿 ELK:使用 Loki + Promtail + Grafana 搭建轻量级日志平台

前言

做日志平台,很多人的第一反应还是 ELK。

Elasticsearch 负责索引,Logstash 负责处理,Kibana 负责展示,功能确实成熟。但问题也很明显:当服务器规模不大,只是想集中收集应用日志、快速查错误、看趋势和做一些基础告警时,为全文索引准备大量内存、CPU 和存储,有时候反而把日志系统本身变成了需要重点维护的对象。

PLG 走的是另一条路线。

Promtail 负责从服务器和应用目录持续采集日志并添加标签,Loki 不对日志全文建立完整索引,而是围绕标签组织日志流,Grafana 再负责查询、可视化和告警。对于“先按服务、主机、环境筛选,再查具体内容”的运维场景,这种结构会轻不少。

这篇文章会在 CentOS 7 上完整搭一遍 Promtail + Loki + Grafana,既演示二进制安装,也提供 Docker Compose 一体化部署方式,并通过测试日志、JSON 结构化日志、Nginx 与认证日志实际验证采集链路,再进一步使用 LogQL 做错误过滤和日志统计。

最后还会通过 cpolar 把 Grafana 的3000端口增加公网入口。

所以这篇真正要回答的问题不是“PLG 能不能替代 ELK”,而是:当你的日志需求没有复杂到必须使用全文索引时,能不能用更轻的方式把采集、查询和可视化先跑起来。

1.Promtail + Loki + Grafana可以做什么?

集中化日志收集

  • Promtail作为日志采集代理,可部署在每台服务器上,实时监控指定路径的日志文件(如/var/log/*.log、应用日志、容器日志等)。
  • 支持自动发现、多行日志合并、标签注入,便于后续分类查询。

高效低成本的日志存储

  • Loki是日志聚合系统,不索引日志全文,而是基于 标签(labels) 廻溯日志流(类似 Prometheus 的时间序列模型)。
  • 日志内容以压缩块形式存储,可使用本地磁盘、对象存储(如S3、MinIO)等后端,存储成本远低于 ELK。
  • 特别适合“先过滤再查内容”的使用模式,对大多数运维和排错场景已足够高效。

强大的日志查询与分析

  • 使用 LogQL(Loki Query Language),一种类似 PromQL 的查询语言,支持:
    • 过滤:{job=“app”} |= “error”
    • 正则匹配:{job=“nginx”} |~ “404|500”
    • 统计:rate({job=“api”}[5m])
    • 提取结构化字段(通过解析表达式)
  • 可进行日志速率统计、错误趋势分析、关键词告警等。

无缝集成Grafana,实现统一可视化

  • Grafana 原生支持 Loki 数据源,无需插件。
  • 在同一个面板中,可将日志(Loki)、指标(Prometheus)、链路(Tempo)联动展示,构建完整的可观测性视图。
  • 支持:
    • 实时日志流查看
    • 日志与 CPU/内存等指标关联分析
    • 创建日志告警规则(通过 Grafana Alerting)
    • 构建运维仪表盘(如“近1小时错误日志 Top 10”)

典型应用场景

  • 微服务日志集中管理:统一收集多个服务实例的日志,按服务名、环境、版本等标签快速筛选。
  • 容器/ Kubernetes 日志:通过 DaemonSet 部署 Promtail,收集 Pod 日志并打上 namespace、pod 名等标签。
  • 系统运维排障:快速定位某台服务器在特定时间段内的异常日志(如 SSH 登录失败、服务崩溃)。
  • 安全审计:监控关键日志(如 sudo 操作、防火墙拒绝记录)并设置告警。
  • 轻量级替代 ELK:在不需要全文搜索或复杂分析的场景下,PLG 更节省资源、更易维护。

优势总结

特性PLG 栈ELK 栈
资源占用低(无全文索引)高(Elasticsearch 内存/CPU 密集)
部署复杂度简单(3个组件,配置直观)复杂(需调优 ES、Logstash、Kibana)
存储成本低(压缩 + 仅索引标签)高(全文索引占用大量空间)
与指标系统集成原生支持 Prometheus + Grafana需额外桥接

2.环境准备

  • 操作系统:CentOS Linux release 7.x(建议最小安装)
  • 用户权限:root 或具有 sudo 权限的用户
  • 网络:确保服务器可访问外网(用于下载软件包)
  • 建议关闭防火墙或开放相应端口(3100、9080、3000):
systemctl stop firewalld systemctl disable firewalld# 或使用 iptables/firewalld 开放端口

安装必要工具

yum update-yyuminstall-ywgettarcurlvimnet-tools

创建专用用户(可选但推荐)

useradd-r-s/sbin/nologin loki

3.下载并安装Loki

下载Loki二进制文件(以v3.0.0为例,请根据 官方 GitHub 替换最新版)

cd/app/lokicurl-O-L"https://github.com/grafana/loki/releases/download/v1.5.0/loki-linux-amd64.zip"

解压该压缩文件:

unziploki-linux-amd64.zip

在日志服务器 上创建目录,用于文件存储和索引存储。

mkdir/data/lokimkdir/data/loki/{chunks,index}

配置文件config.yaml

viconfig.yaml
auth_enabled:falseserver: http_listen_port:8094ingester: lifecycler: address:192.168.42.140#日志服务器ip,即本机地址ring: kvstore: store: inmemory replication_factor:1final_sleep: 0s chunk_idle_period: 5m chunk_retain_period: 30s schema_config: configs: - from:2024-04-01 store: boltdb object_store: filesystem schema: v11 index: prefix: index_ period: 168h#每张表的时间范围7天storage_config: boltdb: directory: /data/loki/index#索引文件存储地址filesystem: directory: /data/loki/chunks#块存储地址limits_config: enforce_metric_name:falsereject_old_samples:truereject_old_samples_max_age: 168h chunk_store_config: max_look_back_period: 168h table_manager: retention_deletes_enabled:trueretention_period: 168h#表的保留期7天

创建启动脚本start.sh和关闭脚本shutdown.sh

vistart.sh
#!/bin/bashnohup./loki-linux-amd64-config.file=./config.yaml>./server.log2>&1&echo"$!">pid
vishutdown.sh
#!/bin/bashkill-9`catpid`echo"关闭成功!"

执行并查看日志

shstart.sh
tail-200fserver.log

4.下载并安装grafana

首先关闭centos防火墙和selinux

systemctl stop firewalld systemctl disable firewalld setenforce0sed-i's/SELINUX=enforcing/SELINUX=disabled/g'/etc/selinux/config

安装grafana:

Ubuntu and Debian(64 Bit):

sudoapt-getinstall-yadduser libfontconfig1 muslwgethttps://dl.grafana.com/enterprise/release/grafana-enterprise_12.1.0_amd64.debsudodpkg-igrafana-enterprise_12.1.0_amd64.deb

Standalone Linux Binaries(64 Bit):

wgethttps://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0.linux-amd64.tar.gztar-zxvfgrafana-enterprise-12.1.0.linux-amd64.tar.gz

Red Hat, CentOS, RHEL, and Fedora(64 Bit):

sudoyuminstall-yhttps://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

OpenSUSE and SUSE(64 Bit):

wgethttps://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpmsudorpm-Uvhgrafana-enterprise-12.1.0-1.x86_64.rpm

我用的是CentOS在这里:

sudoyuminstall-yhttps://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

启动grafana,并设置其开机自启:

systemctl restart grafana-server systemctlenablegrafana-server

查看已安装的grafana版本号:

grafana-cli-version

浏览器打开服务器的3000端口,如:http://ip:3000/

ip:3000

第一次登录,默认账号密码:admin/admin

认证后修改密码:

然后就登录成功啦!

5.下载并安装 promtail

在服务器上创建目录 /app/promtail用于安装promtail

cd/app/promtailcurl-O-L"https://github.com/grafana/loki/releases/download/v1.5.0/promtail-linux-amd64.zip"

解压该压缩文件:

unzippromtail-linux-amd64.zip

配置文件promtail.yaml

vipromtail.yaml
server: http_listen_port:9080grpc_listen_port:0positions: filename: ./positions.yaml clients: - url: http://192.168.42.140:8094/loki/api/v1/push#日志服务器loki地址和端口scrape_configs:#ucenter1- job_name: zcbackend-172.29.21.22-1 static_configs: - targets: -192.168.42.140 - labels: job: zcbachend-172.29.21.22-1 host:192.168.42.140 __path__: /jiuqi/zichan/zichanyitihuazhenghexiangmu-8084/backend/server.log#本机日志路径

创建启动脚本start.sh和关闭脚本shutdown.sh

vistart.sh
#!/bin/bashnohup./promtail-linux-amd64-config.file=./promtail.yaml>./server.log2>&1&echo"$!">pid
vishutdown.sh

执行并查看日志

shstart.sh
tail-200fserver.log

6.docker一键部署Loki+grafana+promtail

本文也可以选择docker一键部署

在开始部署之前,确保你的系统已经安装了Docker。可以通过以下命令检查Docker是否已安装:

docker--version

首先创建一下安装的目录并进入到该目录:

mkdir-p/docker/dochmod-R777/do

执行前准备:

mkdir-p/docker/do/loki# 创建配置文件cat>/docker/do/loki/config.yml<<EOF auth_enabled:falseserver: http_listen_port:3100common: path_prefix: /tmp/loki storage: filesystem: directory: /tmp/loki/chunks replication_factor:1ring: kvstore: store: inmemory schema_config: configs: - from:2020-10-24 store: boltdb-shipper object_store: filesystem schema: v11 index: prefix: index_ period: 24h EOF# 创建目录mkdir-p/docker/do/promtail# 创建配置文件# 创建配置文件cat>/docker/do/promtail/config.yml<<EOF server: http_listen_port:9080grpc_listen_port:0positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: system static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*.log - job_name:teststatic_configs: - targets: - localhost labels: job:test__path__: /var/log/test.log EOF

创建并编辑docker-compose.yml文件:

vidocker-compose.yml
version:"3"networks: loki: services: loki: image: grafana/loki:2.9.10 ports: -"3100:3100"volumes: - ./loki/config.yml:/etc/loki/config.yml# 👈 挂载配置command:-config.file=/etc/loki/config.yml# 👈 路径匹配networks: - loki promtail: image: grafana/promtail:2.9.10 volumes: - /var/log:/var/log - ./promtail/config.yml:/etc/promtail/config.yml# 👈 挂载配置command:-config.file=/etc/promtail/config.yml# 👈 路径匹配networks: - loki user:"root"# 👈 关键!避免权限问题grafana: environment: -GF_PATHS_PROVISIONING=/etc/grafana/provisioning -GF_AUTH_ANONYMOUS_ENABLED=true -GF_AUTH_ANONYMOUS_ORG_ROLE=Admin entrypoint: -sh--euc-|mkdir-p/etc/grafana/provisioning/datasourcescat<<EOF>/etc/grafana/provisioning/datasources/ds.yaml apiVersion:1datasources: - name: Loki type: loki access: proxy orgId:1url: http://loki:3100 basicAuth:falseisDefault:trueversion:1editable:falseEOF /run.sh image: grafana/grafana:latest ports: -"3000:3000"networks: - loki

启动容器:

docker-composeup-d

部署成功:

7.测试

登录到grafana主页

添加数据源

搜索loki

测试连接

现在验证日志是否真的被采集

确保测试日志有内容

echo"Test log entry at$(date)">>/var/log/test.log

用正确语法查询

curl-g'http://localhost:3100/loki/api/v1/query?query={job="test"}&limit=5'

如果看到 values 数组中有内容,说明 日志已成功从 Promtail → Loki!

  • 打开浏览器访问:http://<你的服务器IP>:3000
  • 进入Explore
  • 数据源选择 Loki
  • 在查询框输入:
{job="test"}
  • 点击 Run query
  • 你应该能看到日志!

8.模拟真实应用

准备结构化日志

# 模拟一个 Web 服务日志cat>/var/log/app.json<<'EOF' {"level":"info","ts":"2026-06-04T12:00:00Z","msg":"User login","user_id":1001,"ip":"192.168.1.10","method":"POST","path":"/login","status":200} {"level":"error","ts":"2026-06-04T12:01:05Z","msg":"DB timeout","user_id":1002,"ip":"192.168.1.11","method":"GET","path":"/profile","status":500,"error":"context deadline exceeded"} {"level":"warn","ts":"2026-06-04T12:02:30Z","msg":"Rate limit hit","user_id":1003,"ip":"192.168.1.12","method":"POST","path":"/api/v1/send","status":429} EOF

😎Loki本身不解析JSON,但可以通过Promtail的pipeline提取字段作为标签或结构化日志内容。

升级Promtail配置:支 JSON 解 + 标签提取

编辑/docker/do/promtail/config.yml:

server: http_listen_port:9080grpc_listen_port:0positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name:teststatic_configs: - targets: - localhost labels: job:test__path__: /var/log/test.log - job_name: app-json pipeline_stages: - json: expressions: level: level msg: msg static_configs: - targets: - localhost labels: job: app __path__: /var/log/app.json

  • 这样:level 和 status 会变成 可查询的标签
  • 原始 JSON 内容仍保留在日志行中

然后重启 Promtail:

docker-composerestart promtail

高级 LogQL 查询测试

使用解析表达式(在 Grafana 中更强大)

虽然 API 不直接支持,但在 Grafana Explore 中可以写:

{job="app"}|json|level="error"

{job="app"}|json|status>=500

统计请求量(LogQL 聚合)

在 Grafana 中运行:

sumby(path)(count_over_time({job="app"}[5m]))

多日志源测试

# 模拟 nginx 日志echo'192.168.1.10 - - [04/Jun/2026:12:10:00 +0000] "GET /api/v1/data HTTP/1.1" 200 1024'>>/var/log/nginx-access.log# 模拟 auth 服务日志echo"$(date-Iseconds)[AUTH] User 1001 logged in from 192.168.1.10">>/var/log/auth.log

然后在 promtail/config.yml 中增加:

server: http_listen_port:9080grpc_listen_port:0positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name:teststatic_configs: - targets:[localhost]labels: job:test__path__: /var/log/test.log - job_name: app-json pipeline_stages: - json: expressions: level: level msg: msg static_configs:# ← 必须在这里!- targets:[localhost]labels: job: app __path__: /var/log/app.json - job_name: nginx static_configs: - targets:[localhost]labels: job: nginx __path__: /var/log/nginx-access.log - job_name: auth static_configs: - targets:[localhost]labels: job: auth __path__: /var/log/auth.log

重启后,你可以在 Grafana 中:

  • 切换不同 job
  • 跨服务关联查询(如:先查 auth 登录,再查 nginx 访问)

Grafana本身提供强大的可视化与告警能力,但默认仅限于内网访问。通过与cpolar结合,可轻松实现Grafana服务的安全外网穿透:cpolar基于TLS加密隧道,无需公网IP或复杂网络配置,只需一条命令即可将本地Grafana实例映射到全球可访问的HTTP地址,支持自定义域名、身份验证和流量审计,让运维人员随时随地通过浏览器安全查看监控面板,极大提升了远程运维与应急响应的灵活性与效率。

9.安装cpolar实现随时随地开发

9.1 什么是cpolar?

cpolar是一款安全高效的内网穿透工具,无需公网IP或复杂配置,只需一条命令,即可将本地服务器、Web服务或任意端口映射到公网,让你随时随地远程访问内网应用,特别适合开发调试、远程运维和应急部署等场景。

9.2 部署cpolar

cpolar 可以将你本地电脑中的服务(如 SSH、Web、数据库)映射到公网。即使你在家里或外出时,也可以通过公网地址连接回本地运行的开发环境。

❤️以下是安装cpolar步骤:

sudocurlhttps://get.cpolar.sh|sh

安装完成后,执行下方命令查看cpolar服务状态:(如图所示即为正常启动)

sudosystemctl status cpolar

Cpolar安装和成功启动服务后,在浏览器上输入虚拟机主机IP加9200端口即:【http://192.168.42.101:9200】访问Cpolar管理界面,使用Cpolar官网注册的账号登录,登录后即可看到cpolar web 配置界面,接下来在web 界面配置即可:

打开浏览器访问本地9200端口,使用cpolar账户密码登录即可,登录后即可对隧道进行管理。

10.配置公网地址

登录cpolar web UI管理界面后,点击左侧仪表盘的隧道管理——创建隧道:

  • 隧道名称:可自定义,本例使用了:grafana,注意不要与已有的隧道名称重复
  • 协议:http
  • 本地地址:3000
  • 域名类型:随机域名
  • 地区:选择China Top

创建成功后,打开左侧在线隧道列表,可以看到刚刚通过创建隧道生成了公网地址,接下来就可以在其他电脑或者移动端设备(异地)上,使用地址访问。

访问成功。

11.保留固定公网地址

使用cpolar为其配置二级子域名,该地址为固定地址,不会随机变化。

点击左侧的预留,选择保留二级子域名,地区选择china top,然后设置一个二级子域名名称,我这里演示使用的是grafana3,大家可以自定义。填写备注信息,点击保留。

登录cpolar web UI管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到所要配置的隧道grafana,点击右侧的编辑

修改隧道信息,将保留成功的二级子域名配置到隧道中

  • 域名类型:选择二级子域名
  • Sub Domain:填写保留成功的二级子域名
  • 地区: China Top

点击更新

更新完成后,打开在线隧道列表,此时可以看到随机的公网地址已经发生变化,地址名称也变成了保留和固定的二级子域名名称。

最后,我们使用固定的公网地址在任意设备的浏览器中访问,可以看到成功访问本地部署的grafana页面,这样一个永久不会变化的二级子域名公网网址即设置好了。

总结

把整套链路跑通以后,PLG 和 ELK 的区别其实会变得更直观。

如果业务需要复杂全文检索、大规模字段分析以及非常重的数据处理能力,Elasticsearch 依然有它适合的位置;但如果主要目标是收集服务器和应用日志,按照jobhost、服务名称等标签快速定位问题,再通过 LogQL 查询错误、统计请求量和观察趋势,那么 Loki 这种“索引标签、不全文索引日志内容”的方式会更轻一些。

Promtail 负责把日志送进来,Loki 负责保存和查询,Grafana 则把原始日志变成真正可以使用的运维界面。

从本文测试来看,这套链路不仅可以处理普通文本日志,也可以继续通过 pipeline 和 LogQL 解析 JSON 日志,再把 Nginx、认证服务以及不同应用的日志集中到一个入口中查看。

如果 Grafana 只需要在服务器所在网络中使用,本地访问已经足够;通过 cpolar 增加公网入口以后,则可以在外部网络继续进行日志查询和故障排查。由于 Grafana 中可能包含主机名称、日志内容甚至业务信息,开放公网后应设置好账号、权限和访问保护,不能把管理页面直接裸露出去。

因此 PLG 真正吸引人的,并不是“三个组件比 ELK 少”。

而是它把日志系统的思路做了一次取舍:

不追求把每一行日志都建立复杂索引,而是先把日志集中起来,让你在真正出问题的时候,能够更快找到那几行最重要的信息。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 14:45:47

对话机器人-会话记忆

对话机器人-会话记忆 1、定义会话的存储方式 对每一条对话都有一个id以及对应的内容参数&#xff08;spring中提供了一个ChatMemory接口&#xff09;2、如果上面的接口有了&#xff0c;要使用它就要定义bean 3、有了上面的实现&#xff0c;就可以配置环绕增强&#xff1a;会话记…

作者头像 李华
网站建设 2026/9/4 14:45:43

SpringBoot3+Spring AI+微信小程序全栈开发助农电商平台实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:38:55

可穿戴开发核心链路:传感器、BLE、端侧AI与云端

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:34:56

物流仓储机器人缺有效数据?关键在数据飞轮与主动学习设计

“物流仓储机器人的项目做久了&#xff0c;总会遇到一个绕不开的问题&#xff1a;原始数据明明一天能攒好几个T&#xff0c;为什么做算法的同事还是一直喊缺数据&#xff1f;在被这个问题反复追问之后&#xff0c;我现在的观点越来越确定&#xff1a;它缺的不是数据&#xff0c…

作者头像 李华
网站建设 2026/9/4 14:30:54

华通H6-1高拍仪驱动安装与配置全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:30:30

C/OpenCV双目相机标定工具箱:从原理到实践的完整指南

简介&#xff1a;本资源是一套基于OpenCV与C语言开发的双目立体视觉相机标定工具集&#xff0c;面向计算机视觉初学者、嵌入式视觉开发者及三维重建研究者&#xff0c;解决单目内参与双目外参联合标定这一核心工程难题。工具集完整覆盖棋盘格图像采集、角点自动检测、相机矩阵与…

作者头像 李华