目 录CONTENT

文章目录

loki日志系统

简中仙
2023-05-25 / 0 评论 / 0 点赞 / 480 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2024-04-12,若内容或图片失效,请留言反馈。 本文如有错误或者侵权的地方,欢迎您批评指正!

一、日志系统平台选择

1、ELK

组件说明
Elasticsearch作为日志的存储和搜索系统,提供搜集、分析、存储数据三大功能
Logstash负责做日志的聚合和处理,灵活性, 插件丰富, 配置简洁适用于多种场景,性能与资源消耗大
Kibana作为可视化前端展示,为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志

2、EFK

由于 logstash 内存占用较大,灵活性相对没那么好, ELK 正在被 EFK 逐步替代 。使用了 fluentd 代替了 logstash 。当然,我们也可以使用 Fluentd 的插件( fluent-plugin-elasticsearch)直接将日志发送给 Elasticsearch ,可以根据自己的需要替换掉 Filebeat,也是官方现在比较推荐的一种方案。

组件说明
Filebeats轻量级的收集本地 log 数据的方案,功能比较单一,它仅仅只能收集本地的 log,但并不能对收集到的 Log 做什么处理
Fluentd具有收集并处理 log 的能力,设计简洁,pipeline内数据传递可靠性高,相较于Logstash,其插件支持相对少一些

3、Grafana Loki

1、特点

Loki 采用了一种独特的方法,它只索引元数据而不是日志行的全文,并且为每个日志流设置一组标签,Loki 的最小索引方法意味着在 Loki 中存储同一组日志所需的存储空间比其他解决方案少得多

2、Loki 优点介绍

  • 容易上手, 因为您可以使用各种客户端从任何来源以任何格式发送日志。

  • 对象存储持久化, 意味着您可以获得 PB 级规模、高吞吐量和经济高效且耐用的存储。

  • 告警通知, 可以通过采用的日志对比预定的告警阈值进行相应告警通知。

  • 灵活的日志格式, 为您提供更大的灵活性和在查询时进行格式设置的选项。

  • 实时跟踪应用日志, 以查看进入系统的日志、每隔特定时间更新日志、查看特定日期的日志等。

  • 云原生环境集成, 可以非常方便的与 Prometheus、Grafana 和 K8s 原生集成。

3、与其他日志聚合系统相比

  • 不像ELK对日志进行全文索引, 通过存储压缩的非结构化日志和仅索引元数据Loki 操作更简单,运行成本更低、效率也提升了。

  • 使用已在 Prometheus 中使用的相同标签对日志流进行索引和分组,使您能够使用已在 Prometheus 中使用的相同标签在指标和日志之间无缝切换。

  • 特别适合存储 Kubernetes Pod 日志, Pod 标签等元数据会被自动抓取和索引。

  • 在 Grafana 中有原生支持(需要 Grafana v6.0)。

  • 与ELK/EFK相比不支持复杂操作,技术论坛相对不活跃

二、Loki 部署

1、二进制安装

1、下载软件

# mkdir -p /data/loki/ && cd /data/loki/
# wget https://github.com/grafana/loki/releases/download/v2.9.7/loki-linux-amd64.zip
# wget https://raw.githubusercontent.com/grafana/loki/main/cmd/loki/loki-local-config.yaml -O loki.yaml
# unzip loki-linux-amd64.zip

2、systemctl 管理

cat <<EOF > /usr/lib/systemd/system/loki.service
[Unit]
Description=loki.service
Wants=network-online.target
After=network-online.target
 
[Service]
Type=simple
ExecStart=/data/loki/loki-linux-amd64 -log.level=info -target all -config.file=/data/loki/loki.yaml
WorkingDirectory=/data/loki/
LimitMEMLOCK=infinity
LimitNPROC=65536
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable loki
systemctl start loki
systemctl status loki
systemctl restart loki

2、docker-compose 安装

version: "3"

networks:
  loki:

services:
  loki:
    container_name: loki
    image: grafana/loki:2.9.7
    user: "0"
    volumes:
      - ./loki/conf:/etc/loki
      - ./loki/data:/tmp/loki
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    environment:
      - TZ=Asia/Shanghai
      - LANG=zh_CN.UTF-8
    networks:
      - loki

3、docker 插件

Grafana Loki 正式支持 Docker 插件,该插件将从 Docker 容器中读取日志并将它们发送到 Loki。

1、安装插件

Docker 插件必须安装在每个将运行要从中收集日志的容器的 Docker 主机上。安装完成后必须重新启动 Docker 才能使插件生效。

# docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions
# docker plugin ls
ID                  NAME         DESCRIPTION           ENABLED
ac720b8fcfdb        loki         Loki Logging Driver   true

2、升级插件

# docker plugin disable loki --force
# docker plugin upgrade loki grafana/loki-docker-driver:latest --grant-all-permissions
# docker plugin enable loki
# systemctl restart docker

3、卸载插件

# docker plugin disable loki --force
# docker plugin rm loki

4、启用插件

1、写入到docker守护文件
# vim /etc/docker/daemon.json
{
    "debug" : true,
    "log-driver": "loki",
    "log-opts": {
        "loki-url": "https://<user_id>:<password>@logs-us-west1.grafana.net/loki/api/v1/push",
        "loki-batch-size": "400",
        "loki-retries":"5"
    }
}
参数说明
log-driver指定日志驱动器为loki
loki-url指定了loki的url
loki-retries失败后重试次数
loki-batch-size每次发送多少条日志

更改daemon.json后,重启 Docker 守护进程以使更改生效。来自该主机的所有新创建的容器随后将通过驱动程序将日志发送到 Loki。

2、docker-compose/swarm 启用
version: "3"
services:
  grafana:
    image: grafana/grafana
    logging:
      driver: loki
      options:
        loki-url: "https://<user_id>:<password>@logs-prod-us-central1.grafana.net/loki/api/v1/push"
        loki-pipeline-stages: |
          - regex:
              expression: '(level|lvl|severity)=(?P<level>\w+)'
          - labels:
              level:
    ports:
      - "3000:3000"
3、docker run 启用
docker run --log-driver=loki \
    --log-opt loki-url="https://<user_id>:<password>@logs-us-west1.grafana.net/loki/api/v1/push" \
    --log-opt loki-retries=5 \
    --log-opt loki-batch-size=400 \
    grafana/grafana

三、promtail 部署

1、二进制安装

1、下载软件

# wget https://github.com/grafana/loki/releases/download/v2.9.7/promtail-linux-amd64.zip
# wget https://raw.githubusercontent.com/grafana/loki/main/clients/cmd/promtail/promtail-local-config.yaml -O promtail.yaml
# unzip promtail-linux-amd64.zip

2、systemctl 管理

cat <<EOF > /usr/lib/systemd/system/promtail.service
[Unit]
Description=promtail.service
Wants=network-online.target
After=network-online.target
 
[Service]
Type=simple
ExecStart=/data/promtail/promtail-linux-amd64 -config.file=/data/promtail/promtail.yaml
WorkingDirectory=/data/promtail/
LimitMEMLOCK=infinity
LimitNPROC=65536
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable promtail
systemctl start promtail
systemctl status promtail
systemctl restart promtail

2、docker-compose 安装

version: "3"

networks:
  loki:

services:
  promtail:
    image: grafana/promtail:2.9.7
    volumes:
      - /var/log:/var/log
      - $PWD:/etc/promtail
      - /loki:/loki
    command: -config.file=/etc/promtail/config.yml
    networks:
      - loki

四、配置详解

1、loki 配置

由于版本差异较大,本文只适用于loki2.9.* 版本,请查询官方文档https://grafana.com/docs/loki/v2.9.x/configure/

auth_enabled: false								# 禁用身份验证	

server:											# 服务器模块
  http_listen_port: 3100  						# http 端口
  grpc_listen_port: 9096  						# gRPC 端口

common:											# 通用配置
  instance_addr: 192.168.1.10					# 服务地址
  path_prefix: /data/loki
  storage:
    filesystem:
      chunks_directory: /data/loki/chunks		# 存储日志存储的目录
      rules_directory: /data/loki/rules			# 存储日志查询规则的目录
  replication_factor: 1							# 复制份数
  ring:											# 资源分配模块
    kvstore:									# 后端存储
      store: inmemory							# 内存,还支持consul, etcd, memberlist, multi  

query_range:									# 查询拆分和缓存
  results_cache:								# 缓存配置
    cache:
      embedded_cache:							# 嵌入式缓存
        enabled: true							# 启用
        max_size_mb: 100						# 缓存的最大内存大小,默认100mb

schema_config:
  configs:
    - from: 2024-04-12							# 应创建索引存储区的第一天的日期
      store: tsdb								# 仅支持 tsdb 或 boltdb-shipper
      object_store: filesystem					# 文件系统用于块的存储
      schema: v13								# 要使用的架构版本
      index:									# 配置如何更新和存储索引
        prefix: index_							# 所有索引表的表前缀
        period: 24h								# 表周期

ruler:											# 规则模块(可选)
  storage:										# 存储方法
    type: local									# 本地存储
    local:
      directory: /data/loki/rules				# 规则目录
  rule_path: /data/loki/rules-temp				# 用于存储临时规则文件的文件路径。
  alertmanager_url: http://localhost:9093		# Alertmanager地址
  
limits_config:									# 配置全局和每个租户的限制
  enforce_metric_name: false					# 强制每个样本都有一个度量名称
  reject_old_samples: true   					# 是否拒绝旧样本
  reject_old_samples_max_age: 168h   			# 168小时之前的样本被拒绝
  ingestion_rate_mb: 30  						# 修改每用户摄入速率限制,即每秒样本量,默认值为4M
  ingestion_burst_size_mb: 15  					# 修改每用户摄入速率限制,即每秒样本量,默认值为6M

chunk_store_config:								# 将如何缓存以及在将其保存到后备存储之前等待多长时间
  max_look_back_period: 168h  					# 为避免查询超过保留期的数据,必须小于或等于下方的时间值
table_manager:									# 块配置表管理器以进行保留
  retention_deletes_enabled: true   			# 保留删除开启
  retention_period: 720h  						# 超过168h的块数据将被删除,必须为24h的倍数

2、promtail 配置

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://192.168.1.10:3100/loki/api/v1/push  # 推送到loki地址 
  
scrape_configs:
  - job_name: demo1
    static_configs:
    - targets:
        - localhost
      labels:
        job: demo1
        env: prod
        __path__: /data/log/app-out/*log
    pipeline_stages:						# 需要收集跨行及多行日志时配置
    - match:
        selector: '{job="demo1"}'			# 需替换为targets中定义的标签键值,只有标签匹配时才会执行
        stages:
          - regex:
              expression: '.*'				# 匹配所有有字符的日志记录
          - multiline:
              firstline: '^\[\d{4}-\d{2}-\d{2}'		# 需替换为产生跨行或多行的日志行首正则表达式
              max_wait_time: 3s

  - job_name: demo2
    static_configs:
    - targets:
        - localhost
      labels:
        job: demo2
        env: dev
        __path__: /data/log/app-out/*log
    pipeline_stages:
    - match:
        selector: '{job="demo2"}'
        stages:
          - regex:
              expression: '.*'
          - multiline:
              firstline: '^\[\d{4}-\d{2}-\d{2}'
              max_wait_time: 3s

3、示例

1、Linux

scrape_configs:
  - job_name: journal
    journal:
      json: false
      max_age: 12h
      path: /var/log/journal
      matches: _TRANSPORT=kernel
      labels:
        job: systemd-journal
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'

2、syslog

1、接收方

scrape_configs:
  - job_name: syslog
    syslog:
      listen_address: 0.0.0.0:1514
      listen_protocol: tcp
      idle_timeout: 60s
      label_structured_data: yes
      labels:
        job: "syslog"
    relabel_configs:
      - source_labels: ['__syslog_message_hostname']
        target_label: 'host'

2、发送方

scrape_configs:
- job_name: syslog
  static_configs:
  - targets:
      - localhost
    labels:
      job: syslog
      env: prod
      location: xxxx   # 设备的机房或者所在的位置
      vendor: huawei   # 品牌
      hostname: 网络设备主机名  # 主机名
      __path__: /var/log/network/网络设备IP.log  # 日志的路径

配置rsyslog

# vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514

$ModLoad imtcp
$InputTCPServerRun 514

*.info;mail.none;authpriv.none;cron.none;local6.none;local5.none;local4.none                /var/log/messages

$template huawei,"/var/log/network/%FROMHOST-IP%.log"
local5.* ?huawei
# systemctl restart rsyslog

五、扩展

1、supervisor 管理进程

1、安装supervisor

yum install epel-release -y
yum install supervisor -y 
# 修改内存、进程、文件限制
sed -i '/forking/a LimitNOFILE=65536' /usr/lib/systemd/system/supervisord.service
sed -i '/forking/a LimitNPROC=65536' /usr/lib/systemd/system/supervisord.service
sed -i '/forking/a LimitMEMLOCK=infinity' /usr/lib/systemd/system/supervisord.service
# 设置开机启动,启动服务
systemctl daemon-reload 
systemctl enable supervisord
systemctl start supervisord

2、配置 supervisor 管理 loki 进程

cat <<EOF> /etc/supervisord.d/loki.ini
[program:loki]
command=/data/loki/loki-linux-amd64 -log.level=info -target all -config.file=/data/loki/loki.yaml
autorestart=true
autostart=true
stderr_logfile=/var/log/loki/loki_err.log
stdout_logfile=/var/log/loki/loki_out.log
user=root
stopsignal=INT
startsecs=10
startretries=3
directory=/data/loki/
EOF

3、配置 supervisor 管理 promtail 进程

cat << EOF > /etc/supervisord.d/promtail.ini
[program:promtail]
command=/data/promtail/promtail-linux-amd64 -config.file=/data/promtail/promtail.conf
autorestart=true
autostart=true
stderr_logfile=/var/log/loki/promtail_err.log
stdout_logfile=/var/log/loki/promtail_out.log
user=root
stopsignal=INT
startsecs=10
startretries=3
directory=/data/promtail/
EOF

2、loki 高可用方案

1、启用多节点

memberlist

memberlist:
  join_members: ["loki-1", "loki-2", "loki-3"]						# 节点名称
  dead_node_reclaim_time: 30s										# 死亡节点的名称多久可以用新地址回收
  gossip_to_dead_nodes_time: 15s
  left_ingesters_timeout: 30s
  bind_addr: ['0.0.0.0']
  bind_port: 7946

Loki的memberlist使用的是gossip协议来让集群内的所有节点达到最终一致性的。此部分的配置几乎都是协议频率和超时的控制,保持默认的就好

ingester

ingester:
  lifecycler:
    join_after: 60s
    observe_period: 5s
    ring:
      replication_factor: 2
      kvstore:
        store: memberlist
    final_sleep: 0s

ingester的状态通过gossip协议同步到集群的所有member当中,同时让ingester的复制因子为2。即一个日志流同时写入到两个ingster服务当中以保证数据的冗余。

2、使用第三方存储

将index和chunks的存储统一让S3对象存储纳管,让Loki彻底摆脱三方依赖,这里使用阿里云oss。


# This partial configuration uses Alibaba for chunk storage

schema_config:
  configs:
  - from: 2020-05-15
    object_store: alibabacloud
    schema: v11
    index:
      prefix: loki_index_
      period: 168h

storage_config:
  alibabacloud:
    bucket: <bucket>
    endpoint: <endpoint>
    access_key_id: <access_key_id>
    secret_access_key: <secret_access_key>

3、使用redis缓存

query_range:		# 在Loki查询前端配置查询拆分和缓存
  results_cache:
    cache:
      redis:
        endpoint: redis:6379
        expiration: 1h		# 过期时间
        #username: <string>
        #password: <string>
        enable_tls: false
  cache_results: true		# 缓存查询结果,默认关闭

index_queries_cache_config:		# 构建索引查询的缓存的配置
  redis:
    endpoint: redis:6379
    expiration: 1h
    #username: <string>
    #password: <string>
    enable_tls: false
    
chunk_store_config:		# 缓存以及在将其保存到后备存储之前等待多长时间
  chunk_cache_config:		# 用于存储块的缓存配置
    redis:
      endpoint: redis:6379
      expiration: 1h    
      #username: <string>
      #password: <string>
      enable_tls: false
  write_dedupe_cache_config:		# 用于重复数据消除写入的缓存配置
    redis:
      endpoint: redis:6379
      expiration: 1h
      #username: <string>
      #password: <string>
      enable_tls: false

4、ruler切分

ruler:
  storage:
    type: s3
    s3:
      s3: s3://<S3_ACCESS_KEY>:<S3_SECRET_KEY>@<S3_URL>/<S3_RULES_BUCKET>
      s3forcepathstyle: true
      insecure: true
      http_config:
        insecure_skip_verify: true
    enable_api: true
    enable_alertmanager_v2: true
    alertmanager_url: "http://<alertmanager>"
    ring:
      kvstore:
      store: memberlist
0

评论区