王先森2023-12-202023-12-20
对于生产环境以及一个有追求的运维人员来说,哪怕是毫秒级别的宕机也是不能容忍的。对基础设施及应用进行适当的日志记录和监控非常有助于解决问题,还可以帮助优化成本和资源,以及帮助检测以后可能会发生的一些问题。使用 Loki 收集日志是否可以根据采集的日志来进行报警呢?答案是肯定的,而且有两种方式可以来实现:Promtail 中的 metrics 阶段和 Loki 的 ruler 组件。
比如现在我们有一个如下所的 nginx 应用用于 Loki 日志报警:
cat > appv1.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
spec:
selector:
matchLabels:
app: appv1
template:
metadata:
labels:
use: test
app: appv1
spec:
containers:
- image: nginx:alpine
name: appv1
command: ["/bin/sh", "-c", "echo '你好, 这是(王先森)APP-v1服务中心'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
ports:
- containerPort: 80
name: portv1
---
apiVersion: v1
kind: Service
metadata:
name: appv1
spec:
selector:
app: appv1
ports:
- name: http
port: 80
targetPort: portv1
type: NodePort
EOF
为方便测试,我们这里使用 NodePort 类型的服务来暴露应用,直接安装即可:
$ kubectl apply -f appv1.yml
deployment.apps/appv1 unchanged
service/appv1 configured
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
appv1 NodePort 192.168.216.162 <none> 80:32062/TCP 63d
我们可以通过如下命令来来模拟每隔 10s 访问 Nginx 应用:
$ while true; do curl --silent --output /dev/null --write-out '%{http_code}' http://10.1.1.120:32062; sleep 10; echo; done
官方文档 Ruler storage
Grafana Loki
包含一个名为 ruler 的组件。Ruler
负责持续评估一组可配置查询并根据结果执行操作。在通过使用Loki实现高效日志分析和查询 部署的Loki开启了告警配置,我们需要添加新的告警规则。
apiVersion: v1
kind: ConfigMap
metadata:
name: loki-rule
namespace: logging
labels:
app: loki
data:
nginx.yaml: |
groups:
- name: nginx-rate
rules:
- alert: LokiNginxRate
expr: sum(rate({app="appv1"} |= "error" [1m])) by (job, pod) / sum(rate({app="appv1"}[1m])) by (job, pod) > 0.01
for: 1m
labels:
severity: critical
annotations:
summary: NGINX 实例 {{ $labels.pod }} 的请求错误率过高。
description: high request latency
kubectl edit -n logging statefulsets.apps loki
volumeMounts:
- name: config
mountPath: /etc/loki/config/loki.yaml
subPath: loki.yaml
- name: rule
mountPath: /etc/loki/rules/fake # 挂载到/etc/loki/rules/下fake目录中,
# 如果您有一个 Multi-Tenancy 集群,则规则文件应存储在子文件夹中 <rules-path>/<tenant-id> .如果您不使用 Multi-Tenancy ,则规则文件应位于 <rules-path>/fake 下,fake为默认用户目录。
..........
volumes:
- name: config
configMap:
defaultMode: 0640
name: loki
- name: rule # 添加告警规则configmap
configMap:
defaultMode: 0640
name: loki-rule
# 查看 loki 日志,日志关键字
$ kubectl logs -f -n logging loki-0 loki |grep rule
level=info ts=2023-12-20T06:48:05.448914358Z caller=mapper.go:47 msg="cleaning up mapped rules directory" path=/data/loki/rules-temp
level=info ts=2023-12-20T06:48:05.458968739Z caller=module_service.go:82 msg=initialising module=ruler
level=info ts=2023-12-20T06:48:05.459017096Z caller=ruler.go:528 msg="ruler up and running"
level=info ts=2023-12-20T06:48:05.460113433Z caller=mapper.go:160 msg="updating rule file" file=/data/loki/rules-temp/fake/nginx.yaml
上面日志显示,loki已经更新新的规则文件。 如果文件的格式有问题,将无法加载文件,日志会显示错误原因。 每次更新rule file,需要查看loki日志,确认配置更新。
Loki 的 rulers 规则和结构与 Prometheus 是完全兼容,唯一的区别在于查询语句(LogQL)不同,在 Loki 中我们用 LogQL
来查询日志,一个典型的 rules 配置文件如下所示:
groups:
# 组名称
- name: xxxx
rules:
# Alert名称
- alert: xxxx
# logQL查询语句
expr: xxxx
# 产生告警的持续时间 pending.
[ for: | default = 0s ]
# 自定义告警事件的label
labels:
[ : ]
# 告警时间的注释
annotations:
[ : ]
比如我们这里配置的规则 sum(rate({app="appv1"} |= "error" [1m])) by (job) / sum(rate({app="appv1"}[1m])) by (job) > 0.01
表示通过日志查到 nginx 日志的错误率大于 1%就触发告警:
同样在 1m
之内如果持续超过阈值,则会真正触发报警规则,触发后我们在 Alertmanager 也可以看到对应的报警信息了: