企业级实战模块五:Prometheus+Grafana企业级监控系统(下)
7.1 创建Alertmanager配置文件
cat <<EOF> alertmanager-cm.yaml
kind
alertmanager配置文件解释说明:
smtp_smarthost: 'smtp.qq.com:25'
# 163 邮箱的 SMTP 服务器地址+端口
smtp_from: '1366***563@163.com'
# 这是指定从哪个邮箱发送报警
smtp_auth_username: '158****55**'
# 这是发送邮箱的认证用户,不是邮箱名
smtp_auth_password: 'BGWHYUOSOOHWEUJM'
# 这是发送邮箱的授权码而不是登录密码
smtp_require_tls: false
route:
# 用于设置告警的分发策略
group_by: [alertname]
# alertmanager 会根据 group_by 配置将 Alert 分组
group_wait: 10s
# 分组等待时间。也就是告警产生后等待 10s ,如果有同组告警一起发出
group_interval: 10s
# 上下 两组 发送 告警的间隔时间
repeat_interval: 10m
# 重复 发送 告警的时间,减少相同邮件的发送频率 ,默认是 1h
receiver: default-receiver
# 定义谁来收告警
email_configs:
- to: '2900***889@qq.com'
# 后面指定发送到哪个邮箱
Prometheus一条告警的触发流程、等待时间
7.2 报警处理流程如下:
-
Prometheus Server 监控目标主机上暴露的 http 接口(这里假设接口 A ),通过 Promethes 配置的'scrape_ 定义的时间间隔,定期采集目标主机上监控数据。
-
当接口 A 不可用的时候, Server 端会持续的尝试从接口中取数据,直到 "scrape_ 时间后停止尝试。这时候把接口的状态变为 “ 。
-
Prometheus 同时根据配置的 "evaluation_ 的时间间隔,定期(默认 1min )的对 AlertRule 进行评估;当到达评 估周期的时候,发现接口 A 为 DOWN ,即 UP=0 为真,激活 Alert ,进入“ 状态,并记录当前 active 的时间;
-
当下一个 alert rule 的评估周期到来的时候,发现 UP=0 继续为真,然后判断警报 Active 的时间是否已经超出 rule 里的 ‘for’ 持续时间,如果未超出,则进入下一个评估周期;如果时间超出,则 alert 的状态变为 “ FIRING”;同时调用 Alertmanager 接口,发送相关报警数据。
-
AlertManager 收到报警数据后,会将警报信息进行分组,然后根据 aler tmanager 配置的“group_ 时间先进行等待。等 wait 时间过后再发送报警信息。
-
属于同一个 Alert Group 的警报,在等待的过程中可能进入新的 alert ,如果之前的报警已经成功发出,那么间隔 “group_ 的时间间隔后再重新发送报警信息。比如配置的是邮件报警,那么同属一个 group 的报警信息会汇总在一个邮件里进行发送。
-
如果 Alert Group 里的警报一直没发生变化并且已经成功发送,等待 ‘repeat_ 时间间隔之后再重复发送相同的报警邮件 ;如果之前的警报没有成功发送,则相当于触发第 6 条条件,则需要等待 group_interval 时间间隔后重复发送。同时最后至于警报信息具体发给谁,满足什么样的条件下指定警报接收人,设置不同报警发送频率,这里有 alertmanager 的 route 路由规则进行配置。
7.3 创建configmap配置文件
# 删除之前的cm配置文件
kubectl delete -f /opt/k8s-cfg/prometheus/prometheus-configmap.yaml
kubectl delete -f /opt/k8s-cfg/prometheus/prometheus-deploy.yaml
kubectl delete -f /opt/k8s-cfg/prometheus/prometheus-svc.yaml
# 创建新的cm文件,拉取后注意修改对应的节点IP
wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/prometheus-alertmanager-cfg.yaml
kubectl apply -f prometheus-alertmanager-cfg.yaml
7.4 创建deploy文件
# 生成一个etcd-certs ,这个在部署 prometheus 需要
kubectl -n monitor-sa create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/server.key --from-file=/etc/kubernetes/pki/etcd/server.crt --from-file=/etc/kubernetes/pki/etcd/ca.crt
cat <<EOF> prometheus-alertmanager-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-server
namespace: monitor-sa
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
component: server
#matchExpressions:
#- {key: app, operator: In, values: [prometheus]}
#- {key: component, operator: In, values: [server]}
template:
metadata:
labels:
app: prometheus
component: server
annotations:
prometheus.io/scrape: 'false'
spec:
securityContext:
runAsUser: 0
serviceAccountName: monitor
containers:
- name: prometheus
image: prom/prometheus:v2.2.1
imagePullPolicy: IfNotPresent
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention=24h"
- "--web.enable-lifecycle"
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: /etc/prometheus
name: prometheus-config
- mountPath: /prometheus/
name: prometheus-storage-volume
- name: k8s-certs
mountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/
- name: alertmanager
image: prom/alertmanager:v0.14.0
imagePullPolicy: IfNotPresent
args:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--log.level=debug"
ports:
- containerPort: 9093
protocol: TCP
name: alertmanager
volumeMounts:
- name: alertmanager-config
mountPath: /etc/alertmanager
- name: alertmanager-storage
mountPath: /alertmanager
- name: localtime
mountPath: /etc/localtime
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
- name: prometheus-storage-volume
nfs:
server: 192.168.5.8
path: /data/nfs
- name: k8s-certs
secret:
secretName: etcd-certs
- name: alertmanager-config
configMap:
name: alertmanager
- name: alertmanager-storage
nfs:
server: 192.168.5.8
path: /data/nfs/alertmanager
- name: localtime
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
EOF
kubectl apply -f prometheus-alertmanager-deploy.yaml
7.5 创建service文件
cat <<EOF> alertmanager-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
labels:
name: prometheus
kubernetes.io/cluster-service: 'true'
name: alertmanager
namespace: monitor-sa
spec:
ports:
- name: alertmanager
nodePort: 30066
port: 9093
protocol: TCP
targetPort: 9093
selector:
app: prometheus
sessionAffinity: None
type: NodePort
EOF
kubectl apply -f alertmanager-svc.yaml
kubectl apply -f /opt/k8s-cfg/prometheus/prometheus-svc.yaml
查看部署情况
kubectl get pods,svc -n monitor-sa
需要修改下proxy访问范围
kubectl edit configmap kube-proxy -n kube-system
# 把metricsBindAddress 这段修改成 metricsBindAddress: 0.0.0.0:10249
# 然后重新启动kube-proxy 这个 pod
kubectl get pods -n kube-system | grep kube-proxy | awk '{print$1}' | xargs kubectl delete pods -n kube-system
7.6 报警信息发送到钉钉
官方文档:
报警流程:
群设置→智能群助手→添加机器人→自定义→添加
1)在钉钉群中创建自定义机器人(生成Webhook)
参考文档:
https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.62846573jmFRhY#topic-2026027
2)安装钉钉的webhook插件
tar -zxvf prometheus-webhook-dingtalk-0.3.0.linux-amd64.tar.gz
3)启动钉钉报警插件
cd prometheus-webhook-dingtalk-0.3.0.linux-amd64
nohup ./prometheus-webhook-dingtalk --web.listen-address="0.0.0.0:8060" --ding.profile="关键字= webhook地址 "
4)修改alertmanager-cm.yaml 文件
cat <<EOF> alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: alertmanager
namespace: monitor-sa
data:
alertmanager.yml: |-
global:
resolve_timeout: 1m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '136***@qq.com'
smtp_auth_username: '158***8098'
smtp_auth_password: 'pcoe***aeg'
smtp_require_tls: false
route:
group_by: [alertname]
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: 创建机器人时的关键字
receivers:
- name: 创建机器人时的关键字
webhook_configs:
- url: 'http://192.168.5.8:8060/dingtalk/cluster1/send'
send_resolved: true
EOF
kubectl apply -f alertmanager-cm.yaml
7.7 报警信息发送到企业微信
1)创建应用
找到应用管理,创建应用
应用名字wechat
2)修改alertmanager-cm.yaml 文件
cat <<EOF> alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: alertmanager
namespace: monitor-sa
data:
alertmanager.yml: |-
global:
resolve_timeout: 1m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '136***63@qq.com'
smtp_auth_username: '1583***8'
smtp_auth_password: 'pco***aeg'
smtp_require_tls: false
route:
group_by: [alertname]
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: prometheus
receivers:
- name: prometheus
wechat_configs:
- corp_id: ww***bb15
to_user: '@all
agent_id: 1***
api_secret: Ov5SWq_Jq***9qaMu1TTaDzVTCrXHcjlFs
EOF
kubectl apply -f alertmanager-cm.yaml
参数说明:
-
secret:企业微信 企业应用 自定应用 "[ Prometheus]----> "Secret")
-
wechat:是本人自创建应用名称
-
corp_id:企业信息 我的企业 ""------>" 在底部
-
agent_id:企业微信 企业应用 自定应用 "[ Prometheus]----> "AgentId ")
-
wechat:是自创建应用名称 在这创建的应用名字是 wechat ,那么在配置 route 时, receiver 也应该 是 Prometheus
-
to_user: '@all' :发送报警到所有人
3)配置自定义告警模板
cat template_wechat.tmpl
{{ define "wechat.default.message" }}
{{ range .Alerts }}
========start==========
告警程序:node_exporter
告警名称:{{ .Labels.alertname }}
故障主机:{{ .Labels.instance }}
告警主题:{{ .Annotations.summary }}
告警信息:{{ .Annotations.description }}
========end==========
{{ end }}
{{ end }}
8 Prometheus PromQL 语法
PromQL表达式计算出来的值有以下几种类型:
-
瞬时向量(Instant vector): 一组时序,每个时序只有一个采样值
-
区间向量(Range vector): 一组时序,每个时序包含一段时间内的多个采样值
-
标量数据(Scalar): 一个浮点数
-
字符串(String): 一个字符串,暂时未用
8.1 瞬时向量选择器
瞬时向量选择器用来选择一组时序在某个采样点的采样值。
最简单的情况就是指定一个度量指标,选择出所有属于该度量指标的时序的当前采样值。比如下面的表达式:
apiserver_request_total
可以通过在后面添加用大括号包围起来的一组标签键值对来对时序进行过滤。比如下面的表达式筛 选出了 job 为 kubernetes apiserver s ,并且 resource 为 pod 的时序:
apiserver_request_total{job="kubernetes-apiserver",resource="pods"}
匹配标签值时可以是等于,也可以使用正则表达式。总共有下面几种匹配操作符:
=:完全相等
!=:不相等
=~:正则表达式匹配
!~:正则表达式不匹配
下面的表达式筛选出了container 是 kube scheduler 或 kube-proxy 或 kube-apiserver 的时序数据
container_processes{container=~"kube-scheduler|kube-proxy|kube-apiserver"}
8.2 区间向量选择器
区间向量选择器类似于瞬时向量选择器,不同的是它选择的是过去一段时间的采样值。可以通过在瞬时向量选择器后面添加包含在 [] 里的时长来得到区间向量选择器。比如下面的表达式选出了所有度量指标为 apiserver_request_total 且 resource 是 pod 的时序在过去 1 分钟的采样值。
apiserver_request_total{job="kubernetes-apiserver",resource="pods"}[1m]
这个不支持Graph ,需要选择 Console ,才会看到采集的数据
说明:时长的单位可以是下面几种之一:
s:seconds
m:minutes
h:hours
d:days
w:weeks
y:years
8.3 偏移向量选择器
前面介绍的选择器默认都是以当前时间为基准时间,偏移修饰器用来调整基准时间,使其往前偏移一段时间。偏移修饰器紧跟在选择器后面,使用offset 来指定要偏移的量。比如下面的表达式选择度量名称为 apiserver_request_total 的所有时序在 5 分钟前的采样值。
apiserver_request_total{job="kubernetes-apiserver",resource="pods"} offset 5m
下面的表达式选择apiserver_request_tota l 度量指标在 1 周前的这个时间点过去 5 分钟的采样值
apiserver_request_total{job="kubernetes-apiserver",resource="pods"} [5m] offset 1w
容器没有运行到一周的时间,故而没有图片演示
8.4 聚合操作符
PromQL的聚合操作符用来将向量里的元素聚合得更少。总共有下面这些聚合操作符:
-
sum:求和
-
min:最小值
-
max:最大值
-
avg:平均值
-
stddev:标准差
-
stdvar:方差
-
count:元素个数
-
count_values:等于某值的元素个数
-
bottomk:最小的 k 个元素
-
topk:最大的 k 个元素
-
quantile:分位数
示例:
计算k8s-master-01 节点 所有 容器总计内存
sum(container_memory_usage_bytes{instance=~"k8s-master-01"})/1024/1024/1024
计算k8s-master-01 节点 最近 1m 所有容器 cpu 使用率
sum (rate (container_cpu_usage_seconds_total{instance=~"k8s-master-01"}[1m])) / sum (machine_cpu_cores{ instance =~"k8s-master-01"}) * 100
计算最近1m 所有容器 cpu 使用率
sum (rate (container_cpu_usage_seconds_total{id!="/"}[1m])) by (id)
8.5 函数
Prometheus内置了一些函数来辅助计算,下面介绍一些典型的。
-
abs():绝对值
-
sqrt():平方根
-
exp():指数计算
-
ln():自然对数
-
ceil():向上取整
-
floor():向下取整
-
round():四舍五入取整
-
delta():计算区间向量里每一个时序第一个和最后一个的差值
-
sort():排序
9 Pushgateway介绍
9.1 介绍
Pushgateway 是 prometheus 的一个组件, prometheus server 默认是通过 exporter 主动获取数据(默认采取 pull 拉取数据), pushgateway 则是通过被动方式推送数据到 prometheus server用户可以写一些自定义的监控脚本把需要监控的数据发送给 pushgateway 然后 pushgateway 再把数据发送给 Prometheus server
1)Pushgateway优点:
Prometheus默认采用定时 pull 模式拉取 targets 数据,但是如果不在一个子网或者防火墙,prometheus 就拉取不到 targets 数据,所以可以采用各个 target 往 pushgateway 上 push 数据,然后 prometheus 去 pushgateway 上定时 pull 数据
在监控业务数据的时候,需要将不同数据汇总, 汇总之后的数据可以由 pushgateway 统一收集,然后由 Prometheus 统一拉取。
2)pushgateway缺点:
-
Prometheus拉取状态只针对 pushgateway, 不能对每个节点都有效;
-
Pushg ateway 出现问题,整个采集到的数据都会出现问题监控下线,
-
prometheus 还会拉取到旧的监控数据,需要手动清理 pushgateway 不要的数据。
9.2 安装
docker run -itd --name pushgateway -p 9091:9091 prom/pushgateway
9.3 验证
1)修改prometheus-alertmanager-cfg.yaml 文件
- job_name: 'pushgateway'
scrape_interval: 5s
static_configs:
targets: ['192.168.5.8:9091']
honor_labels: true
2)重新载入配置文件
kubectl apply -f prometheus-alertmanager-cfg.yaml
kubectl delete -f prometheus-alertmanager-deploy.yaml
kubectl apply -f prometheus-alertmanager-deploy.yaml
3)手动推送简单数据到Pushgateway
echo "metric 3.6" | curl --data-binary @- http://192.168.5.8:9091/metrics/job/test_job
注: --data-binary 表示发送二进制数据,注意:它是使用 POST 方式发送的!
4)添加复杂数据
cat <<EOF | curl --data-binary @- http://192.168.5.8:9091/metrics/job/test_job/instance/test_instance
#TYPE node_memory_usage gauge
node_memory_usage 36
# TYPE memory_total gauge
node_memory_total 36000
EOF
删除某个组下某个实例的所有数据
curl -X DELETE http://192.168.5.8:9091/metrics/job/test_job/instance/test_instance
删除某个组下的所有数据:
curl -X DELETE http://192.168.5.8:9091/metrics/job/test_job
9.4 实际场景演示
在被监控服务所在的机器配置数据上报想要把 192.168.5.9 这个机器的内存数据上报到pushgateway ,下面步骤需要在 192.168.5.9 操作
vim push
#!/bin/bash
node_memory_usages=$(free -m | grep Mem | awk '{print $3/$2*100}')
job_name="memory"
instance_name="192.168.5.9"
cat <<EOF | curl --data-binary @- http://192.168.5.8:9091/metrics/job/$job_name/instance/$instance_name
#TYPE node_memory_usages gauge
node_memory_usages $node_memory_usages
EOF
可以通过定时任务来进行定时上传