使用loki+promtail+alertmanager+prometheusAlert實現(xiàn)自定義日志采集查看和監(jiān)控告警
1. 整體架構(gòu)
后面介紹部署方式都是二進制部署,這些應用都可以使用容器進行部署,思路都是一樣的,本文就不再介紹了。
2. 安裝loki
(1)下載地址
https://github.com/grafana/loki/releases
(2)安裝
[root@testqwe ~]# mkdir loki
[root@testqwe ~]# cd loki
[root@testqwe ~]# wget https://github.com/grafana/loki/releases/download/v2.7.1/loki-linux-amd64.zip
[root@testqwe ~]# unzip loki-linux-amd64.zip
[root@testqwe ~]# vi loki.yaml
(3)修改配置文件
主要修改 ruler 內(nèi)參數(shù)。
auth_enabled: false
server:
http_listen_port: 3100
common:
# 根據(jù)實際路徑修改
path_prefix: /home/xxx/Data/loki-stack/loki
storage:
filesystem:
# 根據(jù)實際路徑修改
chunks_directory: /home/xxx/Data/loki-stack/loki/chunks
# 根據(jù)實際路徑修改
rules_directory: /home/xxx/Data/loki-stack/loki/rules
replication_factor: 1
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
limits_config:
enforce_metric_name: false
reject_old_samples: true
reject_old_samples_max_age: 168h
retention_period: 720h
compactor:
retention_enabled: true
compaction_interval: 10m
retention_delete_delay: 5m
retention_delete_worker_count: 150
chunk_store_config:
max_look_back_period: 720h
ruler:
# 觸發(fā)告警事件后的回調(diào)查詢地址
# 如果用grafana的話就配置成grafana/explore,根據(jù)實際ip修改
alertmanager_url: http://10.xx.xx.xx:9093
external_url: http://10.xx.xx.xx:3000
enable_alertmanager_v2: true
# 啟用loki rules API
enable_api: true
# 對rules分片,支持ruler多實例,ruler服務的一致性哈希環(huán)配置,用于支持多實例和分片
enable_sharding: true
ring:
kvstore:
store: inmemory
# rules臨時規(guī)則文件存儲路徑,根據(jù)實際路徑修改
rule_path: /home/xxx/Data/loki-stack/loki/tmp_rules
# rules規(guī)則存儲
# 主要支持本地存儲(local)和對象文件系統(tǒng)(azure, gcs, s3, swift)
storage:
type: local
local:
# 根據(jù)實際路徑修改
directory: /home/xxx/Data/loki-stack/loki/rules
# rules規(guī)則加載時間
flush_period: 1m
analytics:
reporting_enabled: false
其中l(wèi)oki 配置文件詳解。
server:
http_listen_port: 3100 # http_listen_port: 配置HTTP監(jiān)聽端口號為3100。
graceful_shutdown_timeout: 60s # 配置優(yōu)雅停機的超時時間為60秒。
http_server_read_timeout: 60s # 配置HTTP服務器讀取超時時間為60秒。
http_server_write_timeout: 60s # 配置HTTP服務器寫入超時時間為60秒。
ingester: # 配置Loki的ingester部分,用于接收和處理日志數(shù)據(jù)。
lifecycler: # 配置生命周期管理器,用于管理日志數(shù)據(jù)的生命周期。
address: 10.0.0.8 # 配置生命周期管理器的地址
ring: # 配置哈希環(huán),用于將日志數(shù)據(jù)分配給不同的Loki節(jié)點
kvstore: # 配置鍵值存儲,用于存儲哈希環(huán)的節(jié)點信息。
store: inmemory # 配置存儲引擎為inmemory,即內(nèi)存中存儲
replication_factor: 1 # 配置復制因子為1,即每個節(jié)點只存儲一份數(shù)據(jù)。
final_sleep: 0s # 配置最終休眠時間為0秒,即關閉時立即停止。
chunk_idle_period: 1h # 配置日志塊的空閑時間為1小時。如果一個日志塊在這段時間內(nèi)沒有收到新的日志數(shù)據(jù),則會被刷新。
max_chunk_age: 1h # 配置日志塊的最大年齡為1小時。當一個日志塊達到這個年齡時,所有的日志數(shù)據(jù)都會被刷新。
chunk_target_size: 2048576 # 配置日志塊的目標大小為2048576字節(jié)(約為1.5MB)。如果日志塊的空閑時間或最大年齡先達到,Loki會首先嘗試將日志塊刷新到目標大小。
chunk_retain_period: 30s # 配置日志塊的保留時間為30秒。這個時間必須大于索引讀取緩存的TTL(默認為5分鐘)。
max_transfer_retries: 0 # 配置日志塊傳輸?shù)淖畲笾卦嚧螖?shù)為0,即禁用日志塊傳輸。
schema_config: # 配置Loki的schema部分,用于管理索引和存儲引擎。
configs: # 配置索引和存儲引擎的信息。
- from: 2020-10-24 # 配置索引和存儲引擎的起始時間。
store: boltdb-shipper # 配置存儲引擎為boltdb-shipper,即使用BoltDB存儲引擎。
object_store: filesystem # 配置對象存儲引擎為filesystem,即使用文件系統(tǒng)存儲。
schema: v11 # 配置schema版本號為v11。
index: # 配置索引相關的信息。
prefix: index_ # 配置索引文件的前綴為index_。
period: 24h # 配置索引文件的周期為24小時。
storage_config: # 配置Loki的存儲引擎相關的信息。
boltdb_shipper: # 配置BoltDB存儲引擎的信息。
active_index_directory: /tmp/loki/boltdb-shipper-active # 配置活動索引文件的存儲目錄為/tmp/loki/boltdb-shipper-active。
cache_location: /tmp/loki/boltdb-shipper-cache # 配置BoltDB緩存文件的存儲目錄為/tmp/loki/boltdb-shipper-cache。
cache_ttl: 240h # 配置BoltDB緩存的TTL為240小時。
shared_store: filesystem # 配置共享存儲引擎為filesystem,即使用文件系統(tǒng)存儲。
filesystem: # 配置文件系統(tǒng)存儲引擎的信息,即日志數(shù)據(jù)的存儲目錄為/tmp/loki/chunks
directory: /tmp/loki/chunks
compactor: # 配置日志壓縮器的信息。
working_directory: /tmp/loki/boltdb-shipper-compactor # 配置工作目錄為/tmp/loki/boltdb-shipper-compactor。
shared_store: filesystem # 配置共享存儲引擎為filesystem,即使用文件系統(tǒng)存儲。
limits_config: # 配置Loki的限制策略。
reject_old_samples: true # 配置是否拒絕舊的日志數(shù)據(jù)。
reject_old_samples_max_age: 168h # 配置拒絕舊的日志數(shù)據(jù)的最大年齡為168小時。
ingestion_rate_mb: 64 # 配置日志數(shù)據(jù)的最大攝入速率為64MB/s。
ingestion_burst_size_mb: 128 # 配置日志數(shù)據(jù)的最大攝入突發(fā)大小為128MB。
max_streams_matchers_per_query: 100000 # 配置每個查詢的最大流匹配器數(shù)量為100000。
max_entries_limit_per_query: 50000 # 配置每個查詢的最大條目限制為50000。
chunk_store_config: # 配置日志數(shù)據(jù)的存儲策略。
# max_look_back_period: 1440h
max_look_back_period: 240h # 配置最大回溯時間為240小時。
table_manager: # 配置Loki的表管理器。
retention_deletes_enabled: true # 配置是否啟用保留期刪除。
# retention_period: 1440h
retention_period: 240h # 配置保留期為240小時。
(4)編輯啟動文件
[root@testqwe ~]# cat /usr/lib/systemd/system/loki.service
[Unit]
Descriptinotallow=loki server
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/root/loki/loki-linux-amd64 -config.file=/root/loki/loki.yaml -target=all
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=loki
[Install]
WantedBy=default.target
(5)啟動服務
[root@testqwe ~]# systemctl daemon-reload
[root@testqwe ~]# systemctl start loki.service
3. 安裝promtail
(1)下載地址
https://github.com/grafana/loki/releases
(2)安裝
[root@testqwe ~]# mdkir promtail
[root@testqwe ~]# cd promtail
[root@testqwe ~]# wget https://github.com/grafana/loki/releases/download/v2.7.1/promtail-linux-amd64.zip
[root@testqwe ~]# unzip promtail-linux-amd64.zip
(3)修改配置文件
client:loki的地址.
scrape_configs:抓取日志配置。
詳細配置參考:https://cloud.tencent.com/developer/article/1824988。
[root@testqwe ~]# cat promtail/promtail.yaml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /var/log/positions.yaml # This location needs to be writeable by promtail.
client:
# 根據(jù)實際情況修改,添加本機ip地址
url: http://xx.xx.xx.xx:3100/loki/api/v1/push
# 可根據(jù)實際需要修改job中配置來匹配要采集的日志
scrape_configs:
- job_name: app-log
static_configs:
- targets:
- localhost
labels:
job: app-logs
host: 10.xx.11.xx
__path__: /home/xxx/Logs/*.xxx/*log
pipeline_stages:
- match:
selector: '{job="app-logs"}'
stages:
- multiline:
firstline: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{1,} '
max_lines: 256
max_wait_time: 30s
- regex:
source: filename
expression: "/home/xxx/Logs/(?P<appname>[a-z]*).*$"
- labels:
appname:
- job_name: nginx-log
static_configs:
- targets:
- localhost
labels:
job: nginx-logs
host: 10.xx.11.xx
__path__: /home/xxx/Logs/nginx/*/*log
pipeline_stages:
- match:
selector: '{job="nginx-logs"}'
stages:
- regex:
source: filename
expression: "/home/xxx/Logs/nginx/(?P<appname>[a-z1-9.]*)/([a-z1-9.]*)_(?P<logtype>[a-z]*).*$"
- labels:
appname:
logtype:
(4)編輯啟動文件
[root@testqwe ~]# cat /usr/lib/systemd/system/promtail.service
[Unit]
Descriptinotallow=promtail server
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/root/promtail/promtail-linux-amd64 -config.file=/root/promtail/promtail.yaml
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=promtail
[Install]
WantedBy=default.target
(5)啟動服務
[root@testqwe ~]# systemctl daemon-reload
[root@testqwe ~]# systemctl start promtail.service
4. 安裝grafana
(1)下載地址
https://github.com/grafana/grafana/releases
(2)安裝
[root@testqwe ~]# wget https://dl.grafana.com/enterprise/release/grafana-enterprise-9.3.2-1.x86_64.rpm
[root@testqwe ~]# yum install grafana-enterprise-9.3.2-1.x86_64.rpm
(3)啟動服務
[root@testqwe ~]# systemctl start grafana-server.service
5. 安裝alertmanager
(1)下載地址
https://github.com/prometheus/alertmanager/releases
(2)安裝
[root@testqwe ~]# wget https://github.com/prometheus/alertmanager/releases/download/v0.25.0/alertmanager-0.25.0.linux-amd64.tar.gz
[root@testqwe ~]# tar -zxvf alertmanager-0.25.0.linux-amd64.tar.gz
(3)修改配置文件
配置告警相關內(nèi)容:alertmanager.yml.
[root@testqwe alertmanager-0.24.0.linux-amd64]# cat alertmanager.yml
route:
group_by: ['alertname']
group_wait: 5s
group_interval: 5s
repeat_interval: 50m
receiver: 'web.hook'
receivers:
- name: 'web.hook'
webhook_configs:
# 該配置是prometheusalert的server地址,然后拼接的告警渠道webhook
- url: 'http://10.xx.11.xx:8080/prometheusalert?type=fs&tpl=loki&fsurl=http://open.feishu.cn/open-apis/bot/v2/hook/499f95e3-xxxxx'
send_resolved: true
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
(4)Alertmanager 配置文件參考內(nèi)容:
參考鏈接:https://prometheus.io/docs/alerting/latest/configuration/
## Alertmanager 配置文件參考
## Alertmanager 配置文件
global:
resolve_timeout: 5m
# smtp配置
smtp_from: "123456789@qq.com"
smtp_smarthost: 'smtp.qq.com:465'
smtp_auth_username: "123456789@qq.com"
smtp_auth_password: "auth_pass"
smtp_require_tls: true
# 路由分組
route:
receiver: ops
group_wait: 30s # 在組內(nèi)等待所配置的時間,如果同組內(nèi),30秒內(nèi)出現(xiàn)相同報警,在一個組內(nèi)出現(xiàn)。
group_interval: 5m # 如果組內(nèi)內(nèi)容不變化,合并為一條警報信息,5m后發(fā)送。
repeat_interval: 24h # 發(fā)送報警間隔,如果指定時間內(nèi)沒有修復,則重新發(fā)送報警。
group_by: [alertname] # 報警分組
routes:
- match:
team: operations #根據(jù)team標簽進行匹配,走不同的接收規(guī)則
receiver: 'ops'
- match_re:
service: nginx|apache
receiver: 'web'
- match_re:
service: hbase|spark
receiver: 'hadoop'
- match_re:
service: mysql|mongodb
receiver: 'db'
# 接收器指定發(fā)送人以及發(fā)送渠道
receivers:
# ops分組的定義
- name: ops
email_configs:
- to: '9935226@qq.com,10000@qq.com'
send_resolved: true
headers:
subject: "[operations] 報警郵件"
from: "警報中心"
to: "小煜狼皇"
# 釘釘配置
webhook_configs:
- url: http://localhost:8070/dingtalk/ops/send
# 企業(yè)微信配置
wechat_configs:
- corp_id: 'ww5421dksajhdasjkhj'
api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
send_resolved: true
to_party: '2'
agent_id: '1000002'
api_secret: 'Tm1kkEE3RGqVhv5hO-khdakjsdkjsahjkdksahjkdsahkj'
# web
- name: web
email_configs:
- to: '9935226@qq.com'
send_resolved: true
headers: { Subject: "[web] 報警郵件"} # 接收郵件的標題
webhook_configs:
- url: http://localhost:8070/dingtalk/web/send
- url: http://localhost:8070/dingtalk/ops/send
# db
- name: db
email_configs:
- to: '9935226@qq.com'
send_resolved: true
headers: { Subject: "[db] 報警郵件"} # 接收郵件的標題
webhook_configs:
- url: http://localhost:8070/dingtalk/db/send
- url: http://localhost:8070/dingtalk/ops/send
# hadoop
- name: hadoop
email_configs:
- to: '9935226@qq.com'
send_resolved: true
headers: { Subject: "[hadoop] 報警郵件"} # 接收郵件的標題
webhook_configs:
- url: http://localhost:8070/dingtalk/hadoop/send
- url: http://localhost:8070/dingtalk/ops/send
# 抑制器配置
inhibit_rules: # 抑制規(guī)則
- source_match: # 源標簽警報觸發(fā)時抑制含有目標標簽的警報,在當前警報匹配 status: 'High'
status: 'High'
target_match:
status: 'Warning' #
equal: ['alertname','operations', 'instance'] # 確保這個配置下的標簽內(nèi)容相同才會抑制,也就是說警報中必須有這三個標簽值才會被抑制。
inhibit_rules:
Alertmanager的抑制機制可以避免當某種問題告警產(chǎn)生之后用戶接收到大量由此問題導致的一系列的其它告警通知。例如當集群不可用時,用戶可能只希望接收到一條告警,告訴他這時候集群出現(xiàn)了問題,而不是大量的如集群中的應用異常、中間件服務異常的告警通知。
當已經(jīng)發(fā)送的告警通知匹配到target_match和target_match_re規(guī)則,當有新的告警規(guī)則如果滿足source_match或者定義的匹配規(guī)則,并且已發(fā)送的告警與新產(chǎn)生的告警中equal定義的標簽完全相同,則啟動抑制機制,新的告警不會發(fā)送。
通過上面的配置,可以在alertname/operations/instance相同的情況下,high的報警會抑制warning級別的報警信息。
(5)編輯啟動文件
[root@testqwe ]# cat /usr/lib/systemd/system/alertmanager.service
[Unit]
Descriptinotallow=alertmanager
Documentatinotallow=https://prometheus.io/
After=network.target
[Service]
Type=simple
User=root
ExecStart=/root/alertmanager-0.24.0.linux-amd64/alertmanager --config.file=/root/alertmanager-0.24.0.linux-amd64/alertmanager.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target
(6)啟動服務
[root@testqwe ~]# systemctl daemon-reload
[root@testqwe ~]# systemctl start alertmanager.service
6. 安裝prometheusAlert告警中心配置告警通道
告警明細上報到alertmanager后,alertmanager會調(diào)用統(tǒng)一告警中心prometheusAlert的webhook來接收告警內(nèi)容,并按上報內(nèi)容的標簽:告警級別--severity ,業(yè)務條線--bussiness,告警來源--type 來匹配在統(tǒng)一告警中心配置的告警通道,并將告警內(nèi)容推送到飛書群中的webhook機器人
(1)下載地址
#打開PrometheusAlert releases頁面,根據(jù)需要選擇需要的版本下載到本地解壓并進入解壓后的目錄
如linux版本(https://github.com/feiyu563/PrometheusAlert/releases/download/v4.9.1/linux.zip)
# wget https://github.com/feiyu563/PrometheusAlert/releases/download/v4.9.1/linux.zip && unzip linux.zip && cp -r linux /usr/local/prometheusAlert && chmod +x /usr/local/prometheusAlert/PrometheusAlert
(2)編輯啟動文件
[root@testqwe]# cat prometheusalert.service
[Service]
ExecStart=/usr/local/prometheusAlert/PrometheusAlert
WorkingDirectory=/usr/local/prometheusAlert
Restart=always
[Install]
WantedBy=multi-user.target
[Unit]
Descriptinotallow=Prometheus Alerting Service
After=network.target
[root@testqwe system]# pwd
/usr/lib/systemd/system
(3)啟動服務
啟動后可使用瀏覽器打開以下地址查看:http://127.0.0.1:8080。
默認登錄帳號和密碼在app.conf中有配置.
如果需要將日志輸出到控制臺,請修改 app.conf 中 logtype=console。
[root@testqwe ~]# systemctl daemon-reload
[root@testqwe ~]# systemctl start prometheusalert.service
(4)訪問服務
程序運行后,訪問默認地址 http://xxxx:8080 的效果如下。
7. loki配置日志告警
因為上面loki啟動參數(shù)中數(shù)據(jù)存儲是在: /home/xxx/Data/loki-stack/loki/
告警規(guī)則存儲目錄:/home/xxx/Data/loki-stack/loki/rules/fake
因此告警規(guī)則添加到該目錄即可,Loki每分鐘自動刷新規(guī)則生效,下面是幾個簡單的服務告警demo,可以根據(jù)實際情況進行添加對應服務的告警,為了區(qū)分服務,所以每個單獨配置的規(guī)則,expr規(guī)則,可以在grafana大盤,進行查詢,然后調(diào)整
- dzjava-app1-alerts.yml
groups:
- name: POC演示環(huán)境-dzjava-app1告警組
rules:
- alert: 【P1】POC演示環(huán)境dzjava-app1服務日志存在Error和Exception關鍵字告警
expr: sum by (host,appname)(count_over_time({appname="dzjava-app1"} |~ "ERROR|Exception" [3m])) > 0
for: 1m
labels:
severity: critical
type: loki
bussiness: POC
annotations:
summary: "服務:{{ $labels.appname }} 實例: {{ $labels.host }} 3分鐘內(nèi)觸發(fā)Error和Exception關鍵字告警次數(shù)統(tǒng)計閾值0 ,當前值:value: {{ $value}}"
- dzjava-app2-alerts.yml
[root@testqwe fake]# cat dzjava-app2-alerts.yml
groups:
- name: POC演示環(huán)境-dzjava-app2告警組
rules:
- alert: 【P1】POC演示環(huán)境dzjava-app2服務日志存在Error和Exception關鍵字告警
expr: sum by (host,appname)(count_over_time({appname="dzjava-app2"} |~ "ERROR|Exception" [3m])) > 0
for: 1m
labels:
severity: critical
type: loki
bussiness: POC
annotations:
summary: "服務:{{ $labels.appname }} 實例: {{ $labels.host }} 3分鐘內(nèi)觸發(fā)Error和Exception關鍵字告警次數(shù)統(tǒng)計閾值0 ,當前值:value: {{ $value}}"
- alert: 【P1】POC演示環(huán)境dzjava-app2服務日志存在handleBaseService.error關鍵字告警
expr: sum by(appname, host) (count_over_time({appname="dzjava-app2"} |= `handleBaseService.error` [3m])) > 0
for: 1m
labels:
severity: critical
type: loki
bussiness: POC
annotations:
summary: "服務:{{ $labels.appname }} 實例: {{ $labels.host }} 3分鐘內(nèi)觸發(fā)handleBaseService.error關鍵字告警次數(shù)統(tǒng)計閾值0 ,當前值:value: {{ $value}}"
- alert: 【P1】POC演示環(huán)境dzjava-app2服務日志存在502 Bad Gateway關鍵字告警
expr: sum by(appname, host) (count_over_time({appname="dzjava-app2"} |= "502 Bad Gateway" [3m])) > 0
for: 1m
labels:
severity: critical
type: loki
bussiness: POC
annotations:
summary: "服務:{{ $labels.appname }} 實例: {{ $labels.host }} 3分鐘內(nèi)觸發(fā)502 Bad Gateway關鍵字告警次數(shù)統(tǒng)計閾值0 ,當前值:value: {{ $value}}"
8. prometheusAlert配置告警模板
配置高級模版之后,需要修改alertmanager.yml配置文件中的webhook_configs的url地址,在模版的路徑后拼接上飛書機器人地址,然后重啟alertmanager,即可調(diào)試告警通道是否正常
- 添加模板
告警模板:
- 告警紅色
- 恢復綠色
- 告警級別我用的severity,可以修改為level。請自己定義labels
- 使用host,請自己定義labels
- summary是自定義的告警詳細信息
{{ $var := .externalURL}}{{ range $k,$v:=.alerts }}
{{if eq $v.status "resolved"}}
?**[Loki日志恢復通知]({{$v.generatorURL}})**
告警名稱:{{$v.labels.alertname}}
告警級別:{{$v.labels.severity}}
告警狀態(tài):{{$v.status}}
服務名稱:{{$v.labels.appname}}
開始時間:{{GetCSTtime $v.startsAt}}
結(jié)束時間:{{ GetCSTtime $v.endsAt }}
故障主機IP:{{$v.labels.host}}
**{{$v.annotations.summary}}**
{{else}}
??**[Loki日志報警通知]({{$v.generatorURL}})**
{{ if eq $v.labels.severity "warning" }}??告警名稱:{{$v.labels.alertname}}
告警級別??:{{$v.labels.severity}}
{{ else if eq $v.labels.severity "critical" }}?告警名稱:{{$v.labels.alertname}}
告警級別?:{{ $v.labels.severity }}
{{ else if eq $v.labels.severity "emergency" }}?????告警名稱:{{ $v.labels.alertname }}
告警級別?????:{{ $v.labels.severity }}
{{ end }}
告警狀態(tài):{{$v.status}} > {{$v.labels.severity}}
告警級別:{{$v.labels.severity}}
服務名稱:{{$v.labels.appname}}
開始時間:{{GetCSTtime $v.startsAt}}
結(jié)束時間:{{ GetCSTtime $v.endsAt }}
故障主機IP:{{$v.labels.host}}
**{{$v.annotations.summary}}**
{{end}}
{{ end }}
模板可以參考這個issues中的討論:https://github.com/feiyu563/PrometheusAlert/issues/30
(1)告警效果展示
飛書群中,收到告警如下,可以簡單的實現(xiàn)服務日志的采集和告警功能展示。
(2)日志效果展示
可以在grafana上添加數(shù)據(jù)源。
然后點擊側(cè)面欄的Explore就可以查看應用服務日志了。