PLG日志系统详解:Promtail + Loki + Grafana一体化部署实践

前言

在当今云原生与微服务架构快速演进的背景下,日志作为系统可观测性的三大支柱之一(日志、指标、链路追踪),其重要性不言而喻。然而,传统日志方案往往依赖重量级组件(如ELK栈),存在资源消耗大、配置复杂、运维成本高等问题,难以满足轻量、高效、易维护的现代运维需求。

为此,由Grafana Labs推出的PLG栈(Promtail + Loki + Grafana)应运而生——它以“日志即事件流”的设计理念,摒弃全文索引,采用基于标签的高效查询机制,在显著降低存储与计算开销的同时,仍能提供流畅的日志检索与可视化体验。尤其适合中小型团队、边缘环境或对资源敏感的私有化部署场景。

本文将聚焦PLG日志系统的原理剖析与一体化部署实践,以CentOS 7为示例环境,手把手指导读者完成Promtail、Loki与Grafana的安装、配置、集成与验证全过程。无论您是 DevOps 工程师、系统管理员,还是希望构建轻量级日志平台的技术爱好者,都能通过本文快速掌握PLG栈的核心能力,迈出构建高效、简洁、可扩展日志体系的关键一步。

image-20260604172008353

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 -y
yum install -y wget tar curl vim net-tools

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

useradd -r -s /sbin/nologin loki

3.下载并安装Loki

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

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

image-20260603161956692

解压该压缩文件:

unzip loki-linux-amd64.zip

image-20260603162122303

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

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

image-20260603162320281

配置文件config.yaml

vi config.yaml
auth_enabled: false
server:
  http_listen_port: 8094
ingester:
  lifecycler:
    address: 192.168.42.140 #日志服务器ip,即本机地址
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_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: false
  reject_old_samples: true
  reject_old_samples_max_age: 168h
chunk_store_config:
  max_look_back_period: 168h

table_manager:
  retention_deletes_enabled: true
  retention_period: 168h   #表的保留期7天

image-20260603162608564

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

vi start.sh
#!/bin/bash
nohup ./loki-linux-amd64 -config.file=./config.yaml >./server.log 2>&1 &
echo "$!" > pid
vi shutdown.sh
#!/bin/bash
kill -9 `cat pid`
echo "关闭成功!"

image-20260603162821293

执行并查看日志

sh start.sh
tail -200f server.log

image-20260603163043277

4.下载并安装grafana

首先关闭centos防火墙和selinux

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

安装grafana:

Ubuntu and Debian(64 Bit):

sudo apt-get install -y adduser libfontconfig1 musl
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_12.1.0_amd64.deb
sudo dpkg -i grafana-enterprise_12.1.0_amd64.deb

Standalone Linux Binaries(64 Bit):

wget https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0.linux-amd64.tar.gz
tar -zxvf grafana-enterprise-12.1.0.linux-amd64.tar.gz

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

sudo yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

OpenSUSE and SUSE(64 Bit):

wget https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm
sudo rpm -Uvh grafana-enterprise-12.1.0-1.x86_64.rpm

我用的是CentOS在这里:

sudo yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

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

systemctl restart grafana-server
systemctl enable grafana-server

查看已安装的grafana版本号:

grafana-cli -version

image-20251202110921063

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

ip:3000

image-20251202113836526

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

image-20251202113858320

认证后修改密码:

image-20251202113955895

然后就登录成功啦!
image-20251202114409656

5.下载并安装 promtail

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

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

解压该压缩文件:

unzip promtail-linux-amd64.zip

image-20260603165616218

配置文件promtail.yaml

vi promtail.yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  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  #本机日志路径

image-20260603165853113

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

vi start.sh
#!/bin/bash
nohup ./promtail-linux-amd64 -config.file=./promtail.yaml >./server.log 2>&1 &
echo "$!" > pid
vi shutdown.sh

image-20260603170408988

执行并查看日志

sh start.sh
tail -200f server.log

image-20260603170429531

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

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

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

docker --version

image-20260507155742946

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

mkdir -p /docker/do
chmod -R 777 /do

执行前准备:

mkdir -p /docker/do/loki
# 创建配置文件
cat > /docker/do/loki/config.yml <<EOF
 auth_enabled: false

 server:
   http_listen_port: 3100

 common:
   path_prefix: /tmp/loki
   storage:
     filesystem:
       directory: /tmp/loki/chunks
   replication_factor: 1
   ring:
     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: 9080
   grpc_listen_port: 0

 positions:
   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: test
     static_configs:
       - targets:
           - localhost
         labels:
           job: test
           __path__: /var/log/test.log
 EOF

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

vi docker-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/datasources
        cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
        apiVersion: 1
        datasources:
        - name: Loki
          type: loki
          access: proxy
          orgId: 1
          url: http://loki:3100
          basicAuth: false
          isDefault: true
          version: 1
          editable: false
        EOF
        /run.sh
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - loki

image-20260604102017634

启动容器:

docker-compose up -d

image-20260604101932972

部署成功:

image-20260604104643933

7.测试

登录到grafana主页

image-20260603170616989

添加数据源

image-20260603170747907

搜索loki

image-20260603170813313

测试连接

image-20260604104816985

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

确保测试日志有内容

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

用正确语法查询

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

image-20260604114713871

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

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

image-20260604114612165

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

image-20260604155743914

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

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

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

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

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

scrape_configs:
  - job_name: test
    static_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

image-20260604155846952

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

然后重启 Promtail:

docker-compose restart promtail

高级 LogQL 查询测试

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

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

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

image-20260604160637754

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

image-20260604160714102

统计请求量(LogQL 聚合)

在 Grafana 中运行:

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

image-20260604160433301

多日志源测试

# 模拟 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

image-20260604163251555

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

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

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

scrape_configs:
  - job_name: test
    static_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

image-20260604164917170

重启后,你可以在 Grafana 中:

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

image-20260604164900549

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

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

9.1 什么是cpolar?

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

9.2 部署cpolar

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

❤️以下是安装cpolar步骤:

官网在此:https://www.cpolar.com

sudo curl https://get.cpolar.sh | sh

image-20250725093611926

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

sudo systemctl status cpolar

22e5adfaf290a17fc3384bb296055259

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

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

8a6698b1bf26d64ba3645827fbfb1c29

10.配置公网地址

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

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

image-20250725100328538

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

image-20250725100510154

访问成功。

image-20250725100605079

11.保留固定公网地址

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

1b5b18459db4d0a167e947c02c3e14aa

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

image-20250725100825658

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

image-20250724153922644

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

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

点击更新

image-20250725100857991

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

image-20250725100931603

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

image-20250725101019404

总结

PLG日志系统(Promtail + Loki + Grafana)是一套轻量级、高效率的云原生日志解决方案:Promtail负责采集日志并打上标签,Loki以极低存储成本聚合日志(仅索引元数据,不索引全文),Grafana则提供统一的可视化界面和基于LogQL的强大查询与告警能力。三者无缝集成,无需复杂配置即可实现从日志收集、存储到分析告警的一体化运维。

感谢您对本篇文章的喜爱,有任何问题欢迎留言交流。cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站

Share:

发表回复

目录

On Key

推荐文章