• loki日志收集系统部署

前言:本文整理Loki部署及使用方法,相较于ELK及EFK,LOKI比前两者更加轻量。部署更加简单,依赖更少,在资源占用,loki适合资源受限环境,ELK资源消耗大,推荐至少3节点集群,比ELK轻量,Fluentd内存占用约200-500MB(Logstash需1-2GB)。而且loki可以与prometheus集成,本文后续会增加prometheus部署方案。本次部署版本loki为v2.5.0

环境介绍:CentOS7.9 

一、部署架构:

架构1:Loki+promtail+grafana

架构2:Loki+logstash+grafana

二、组件功能介绍

loki:Loki is the logging engine. Promtail:轻量级日志代理,部署在应用节点上,负责收集本地日志文件或容器日志,通过标签化处理后发送至Loki‌ Grafana:可视化层,通过添加Loki数据源,提供日志查询界面、仪表板及告警功能‌ Logstash:功能同Promtail,但是相较于前者,Logstash支持200+插件,可同时从日志文件、数据库等来源采集数据,通过过滤器(如Grok解析)转换格式,其核心价值在于隔离业务系统与数据处理系统,降低耦合性。

三、loki搭建

前言:因为loki基于go语言,需要安装go环境,在配置lokiyaml文件时,需要注意数据文件存储路径。

1、准备环境

sudo yum install golang

sudo yum install unzip tar gzip

 

2、下载loki

wget https://github.com/grafana/loki/releases/download/v2.5.0/loki-linux-amd64.zip
离线部署将zip上传到需要部署的服务器中
unzip loki-linux-amd64.zip
​

3、配置loki

vi /opt/loki/loki-local-config.yaml
auth_enabled: false
​
# 服务器设置(保持你的配置不变)
server:
  http_listen_port: 3100
  grpc_listen_port: 9096
  log_level: debug
  grpc_server_max_concurrent_streams: 1000
​
# 存储基础配置(保持不变)
common:
  instance_addr: 127.0.0.1
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
      rules_directory: /tmp/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory
​
# 移除所有查询缓存配置(v2.5.0 不支持任何缓存字段)
query_range: {}  # 仅保留空节点,避免配置结构错误
​
# 索引配置(保持不变)
schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h
​
# 存储详细配置(保持不变)
storage_config:
  boltdb_shipper:
    active_index_directory: /tmp/loki/boltdb-shipper-active
    cache_location: /tmp/loki/boltdb-shipper-cache
    cache_ttl: 24h
    shared_store: filesystem
​
# 规则器配置(保持不变)
ruler:
  alertmanager_url: http://localhost:9093
​
# 禁用匿名统计(保持不变)
analytics:
  reporting_enabled: false

4、配置systemd服务文件

sudo vim /etc/systemd/system/loki.service
/home/sdnmuser/applications/loki/loki
​
​
[Unit]
Description=Loki Log Aggregation System
After=network.target
​
[Service]
User=<your-user>
Group=<your-group>
ExecStart=/path/to/loki-linux-amd64 -config.file=/path/to/loki.yaml
Restart=on-failure
​
[Install]
WantedBy=multi-user.target
​

5、启动

sudo systemctl daemon-reload
sudo systemctl enable loki.service
sudo systemctl start loki.service
​

四、搭建Grafana

wget https://dl.grafana.com/oss/release/grafana-7.3.7-1.x86_64.rpm
yum install grafana-7.3.7-1.x86_64.rpm
systemctl start grafana-server.service

五、部署Promtail

1、下载并解压

https://github.com/grafana/loki/releases/download/v2.1.0/promtail-linux-amd64.zip
wget https://raw.githubusercontent.com/grafana/loki/master/cmd/promtail/promtail-local-config.yaml
unzip promtail-linux-amd64.zip -d /opt/loki

2、配置Promtail

收集messages文件信息,lables设置3个,分别是varlogs、host、path
vim /opt/loki/promtail-local-config.yaml
# promtail-config.yaml
server:
  http_listen_port: 9080  # Promtail 自身的 HTTP 端口(用于健康检查、指标暴露)
  grpc_listen_port: 0     # 关闭 gRPC 端口(无需集群通信时用)
​
positions:
  filename: /var/lib/promtail/positions.yaml  # 存储采集偏移量的文件(需提前创建目录)
  sync_period: 10s                            # 偏移量同步到文件的周期
​
clients:
  - url: http://loki-server-ip:3100/loki/api/v1/push  # Loki 推送地址(替换为你的 Loki 地址)
    # 若 Loki 启用认证(如 Basic Auth),添加以下配置:
    # basic_auth:
    #   username: your-username
    #   password: your-password
    # 若用 HTTPS,url 改为 https://...,并可添加证书配置:
    # tls_config:
    #   insecure_skip_verify: false  # 生产环境不建议跳过证书验证
    #   ca_file: /path/to/ca.crt
​
scrape_configs:
  # 采集应用日志(示例:Spring Boot 应用日志)
  - job_name: "app-logs"  # 采集任务名称(自定义,用于区分不同采集规则)
    static_configs:
      - targets:
          - localhost  # 目标主机(本地采集填 localhost,远程采集填目标主机 IP)
        labels:
          # 必选标签:__path__ 指定日志文件路径(支持通配符 *)
          __path__: /opt/app/logs/*.log
          # 自定义标签:用于 Loki 查询过滤(按需添加)
          env: "production"       # 环境标签
          app: "user-service"     # 应用名称
          host: "web-server-01"   # 主机名称
​
  # 采集系统日志(示例:CentOS/RedHat 系统日志)
  - job_name: "system-logs"
    static_configs:
      - targets:
          - localhost
        labels:
          __path__: /var/log/messages  # 系统日志路径
          # 或采集所有系统日志:/var/log/*.log
          env: "production"
          log_type: "system"
          host: "web-server-01"
​
  # 采集 Nginx 日志(示例:access.log + error.log)
  - job_name: "nginx-logs"
    static_configs:
      - targets:
          - localhost
        labels:
          __path__: /var/log/nginx/*.log  # 匹配 Nginx 所有日志
          env: "production"
          app: "nginx"
          host: "web-server-01"
    # 可选:解析 Nginx 日志为结构化数据(方便 Loki 按字段查询)
    pipeline_stages:
      - regex:
          expression: '^(?P<remote_addr>\S+) \S+ \S+ \[(?P<time_local>[^\]]+)\] "(?P<request_method>\S+) (?P<request_uri>\S+) \S+" (?P<status>\d+) \S+ "(?P<http_referer>[^"]*)" "(?P<http_user_agent>[^"]*)"'
      - timestamp:
          source: time_local
          format: "02/Jan/2006:15:04:05 -0700"  # 匹配 Nginx 日志的时间格式
      - labels:
          remote_addr:  # 将解析出的 remote_addr 作为标签(可选,用于过滤)
          status:       # 将状态码作为标签

3、添加管理

vim /etc/systemd/system/promtail.service
[Unit]
Description=Loki Log Aggregation System
After=network.target
​
[Service]
User=root
Group=root
ExecStart=/root/loki/promtail -config.file=/root/loki/promtail.yaml
Restart=on-failure
​
[Install]
WantedBy=multi-user.target
​

4、脚本批量配置job_name

#!/bin/bash
​
# Promtail配置生成脚本
# 功能:扫描指定目录下的所有run.log文件并生成Promtail配置
​
# 获取当前服务器的完整IP地址
SERVER_IP=$(hostname -I | awk '{print $1}')
​
# 获取当前服务器的IP地址(后两位)
SERVER_IP_SUFFIX=$(hostname -I | awk '{print $1}' | awk -F. '{print $3"."$4}')
​
# 配置文件路径
CONFIG_FILE="/home/sdnmuser/applications/promtail/promtail-local-config.yaml"
​
# 创建目录(如果不存在)
mkdir -p $(dirname "$CONFIG_FILE")
​
# 开始生成配置文件
cat > "$CONFIG_FILE" << EOF
# promtail-config.yaml
server:
  http_listen_port: 9080  # Promtail 自身的 HTTP 端口(用于健康检查、指标暴露)
  grpc_listen_port: 0     # 关闭 gRPC 端口(无需集群通信时用)
​
positions:
  filename: /var/lib/promtail/positions.yaml  # 存储采集偏移量的文件(需提前创建目录)
  sync_period: 10s                            # 偏移量同步到文件的周期
​
clients:
  - url: http://11.31.0.6:3100/loki/api/v1/push  # Loki 推送地址(替换为你的 Loki 地址)
    # 若 Loki 启用认证(如 Basic Auth),添加以下配置:
    # basic_auth:
    #   username: your-username
    #   password: your-password
    # 若用 HTTPS,url 改为 https://...,并可添加证书配置:
    # tls_config:
    #   insecure_skip_verify: false  # 生产环境不建议跳过证书验证
    #   ca_file: /path/to/ca.crt
​
scrape_configs:
  # 采集系统日志(示例:CentOS/RedHat 系统日志)
  - job_name: "${SERVER_IP_SUFFIX}system_log"
    static_configs:
      - targets:
          - localhost
        labels:
          __path__: /var/log/messages  # 系统日志路径
          # 或采集所有系统日志:/var/log/*.log
          env: "${SERVER_IP}"
          log_type: "system"
          host: "${SERVER_IP}"
​
EOF
​
# 扫描/home/sdnmuser/applications/目录下的所有run.log文件
find /home/sdnmuser/applications/ -name "run.log" -type f | while read logfile; do
    # 提取应用程序名称(logs目录的上一级目录)
    APP_NAME=$(basename $(dirname $(dirname "$logfile")))
    
    # 生成job_name:IP后两位+应用名称
    JOB_NAME="${SERVER_IP_SUFFIX}${APP_NAME}"
    
    # 添加到配置文件
    cat >> "$CONFIG_FILE" << EOF
  # 采集应用日志 ($APP_NAME)
  - job_name: "$JOB_NAME"
    static_configs:
      - targets:
          - localhost
        labels:
          __path__: $logfile
          env: "${SERVER_IP}"
          app: "$APP_NAME"
          host: "${SERVER_IP}"
​
EOF
done
​
echo "Promtail配置文件已生成: $CONFIG_FILE"
echo "配置文件包含以下日志采集任务:"
grep "job_name:" "$CONFIG_FILE" | sed 's/.*job_name: "\([^"]*\)".*/\1/'

5、使用ansible批量操作

---
- name: 完整部署Promtail(Root权限)
  hosts: all
  gather_facts: true
  become: true          # 以root权限执行所有任务
  become_user: root
  vars:
    # 核心路径配置
    promtail_zip_path: "/home/sdnmuser/applications/promtail-linux-amd64.zip"
    config_yaml_src: "/home/sdnmuser/applications/promtail/promtail-local-config.yaml"
    promtail_service_src: "/etc/systemd/system/promtail.service"
    # 添加脚本文件路径变量
    pro_script_src: "/home/sdnmuser/applications/promtail/pro.sh"
    # 目标路径
    target_base_dir: "/home/sdnmuser/applications"
    promtail_work_dir: "{{ target_base_dir }}/promtail"  # promtail主工作目录
    unzip_temp_file: "{{ target_base_dir }}/promtail-linux-amd64"  # 解压后的原始文件名
    promtail_bin_name: "{{ promtail_work_dir }}/promtail"  # 重命名后的二进制文件
    positions_file: "{{ promtail_work_dir }}/positions.yaml"  # positions.yaml最终路径
    pro_script_dest: "{{ promtail_work_dir }}/pro.sh"  # pro.sh目标路径
​
  tasks:
    ###########################################################################
    # 前置检查:控制节点源文件是否存在
    ###########################################################################
    - name: 检查控制节点源文件
      stat:
        path: "{{ item }}"
      register: src_file_check
      delegate_to: localhost
      failed_when: not src_file_check.stat.exists
      loop:
        - "{{ promtail_zip_path }}"
        - "{{ config_yaml_src }}"
        - "{{ promtail_service_src }}"
        - "{{ pro_script_src }}"
      tags:
        - file_check
        - promtail_deploy
​
    ###########################################################################
    # 前置依赖:先安装unzip(关键!确保解压前已安装工具)
    ###########################################################################
    - name: 安装unzip依赖(适配Debian/Ubuntu/CentOS)
      package:
        name: unzip
        state: present
      tags:
        - unzip_install
        - promtail_deploy
​
    ###########################################################################
    # 目录准备:确保所有目标目录存在且权限正确
    ###########################################################################
    - name: 确保promtail工作目录存在
      file:
        path: "{{ promtail_work_dir }}"
        state: directory
        owner: sdnmuser
        group: sdnmuser
        mode: '0755'
        recurse: true  # 递归创建父目录(如有需要)
      tags:
        - dir_prepare
        - promtail_deploy
​
    ###########################################################################
    # 文件传输:核心文件推送到目标节点
    ###########################################################################
    - name: 传输promtail压缩包到目标节点
      copy:
        src: "{{ promtail_zip_path }}"
        dest: "{{ target_base_dir }}/"
        owner: sdnmuser
        group: sdnmuser
        mode: '0644'
        backup: yes
      tags:
        - copy_zip
        - promtail_deploy
​
    - name: 复制promtail systemd服务文件
      copy:
        src: "{{ promtail_service_src }}"
        dest: "/etc/systemd/system/"
        owner: root
        group: root
        mode: '0644'
        backup: yes
      tags:
        - copy_service
        - promtail_deploy
​
    ###########################################################################
    # 解压+重命名:解压压缩包并将二进制文件重命名为promtail
    ###########################################################################
    - name: 解压promtail压缩包到基础目录
      unarchive:
        src: "{{ target_base_dir }}/promtail-linux-amd64.zip"
        dest: "{{ target_base_dir }}"
        remote_src: yes
        owner: sdnmuser
        group: sdnmuser
        mode: '0755'
        creates: "{{ unzip_temp_file }}"  # 避免重复解压
      tags:
        - unzip_promtail
        - promtail_deploy
​
    - name: 将解压后的二进制文件重命名为promtail并移动到工作目录
      copy:
        src: "{{ unzip_temp_file }}"
        dest: "{{ promtail_bin_name }}"
        remote_src: yes
        owner: sdnmuser
        group: sdnmuser
        mode: '0755'
        force: yes  # 覆盖已存在的同名文件
      tags:
        - rename_promtail
        - promtail_deploy
​
    - name: 删除解压后的原始临时文件(可选,清理冗余)
      file:
        path: "{{ unzip_temp_file }}"
        state: absent
      tags:
        - clean_temp
        - promtail_deploy
​
    ###########################################################################
    # 配置文件部署:将配置文件复制到promtail工作目录
    ###########################################################################
    - name: 复制promtail配置文件到工作目录
      copy:
        src: "{{ config_yaml_src }}"
        dest: "{{ promtail_work_dir }}/"
        owner: sdnmuser
        group: sdnmuser
        mode: '0644'
        backup: yes
      tags:
        - copy_config
        - promtail_deploy
​
    ###########################################################################
    # 复制并执行pro.sh脚本
    ###########################################################################
    - name: 复制pro.sh脚本到promtail工作目录
      copy:
        src: "{{ pro_script_src }}"
        dest: "{{ pro_script_dest }}"
        owner: sdnmuser
        group: sdnmuser
        mode: '0755'  # 设置为可执行
        backup: yes
      tags:
        - copy_pro_script
        - promtail_deploy
​
    - name: 执行pro.sh脚本
      shell: "{{ pro_script_dest }}"
      args:
        chdir: "{{ promtail_work_dir }}"  # 在promtail工作目录中执行
      become: true
      become_user: sdnmuser
      register: pro_script_output
      ignore_errors: yes  # 脚本执行错误不中断整个playbook
      tags:
        - execute_pro_script
        - promtail_deploy
​
    - name: 显示pro.sh脚本执行结果
      debug:
        var: pro_script_output.stdout_lines
      when: pro_script_output.stdout_lines is defined
      tags:
        - execute_pro_script
        - promtail_deploy
​
    - name: 显示pro.sh脚本执行错误(如有)
      debug:
        var: pro_script_output.stderr_lines
      when: pro_script_output.stderr_lines is defined
      tags:
        - execute_pro_script
        - promtail_deploy
​
    ###########################################################################
    # 创建positions.yaml:在指定目录创建空文件
    ###########################################################################
    - name: 在promtail工作目录创建positions.yaml空文件
      file:
        path: "{{ positions_file }}"
        state: touch
        owner: sdnmuser
        group: sdnmuser
        mode: '0644'
        modification_time: preserve
        access_time: preserve
      tags:
        - create_positions
        - promtail_deploy
​
    ###########################################################################
    # Systemd重载:确保服务配置生效
    ###########################################################################
    - name: 重载systemd守护进程
      systemd:
        daemon_reload: true
      tags:
        - systemd_reload
        - promtail_deploy
​
    ###########################################################################
    # 完整性验证:检查所有关键文件是否部署成功(修复mode属性问题)
    ###########################################################################
    - name: 验证部署结果
      stat:
        path: "{{ item }}"
      register: deploy_verify
      loop:
        - "{{ promtail_bin_name }}"                  # 重命名后的二进制文件
        - "{{ promtail_work_dir }}/promtail-local-config.yaml"  # 配置文件
        - "{{ positions_file }}"                    # positions.yaml
        - "{{ pro_script_dest }}"                   # pro.sh脚本
        - "/etc/systemd/system/promtail.service"    # 服务文件
        - "{{ target_base_dir }}/promtail-linux-amd64.zip"  # 压缩包
      tags:
        - verify
        - promtail_deploy
​
    - name: 输出验证结果(修复mode属性未定义问题)
      debug:
        msg: |
          文件 {{ item.item }} 
          存在状态: {{ item.stat.exists }}
          {% if item.stat.exists %}权限: {{ item.stat.mode }}{% else %}权限: 无(文件不存在){% endif %}
      loop: "{{ deploy_verify.results }}"
      tags:
        - verify
        - promtail_deploy
​

六、251210新增Grafana界面配置

Grafana官网:Grafana dashboards | Grafana Labs

按照图示查看

选择prometheus和Loki地址

按照需要查看日志

更多推荐