一、日志系统平台选择
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
评论区