Prometheus Operator自定义监控项

运维 系统运维
Prometheus Operator默认的监控指标并不能完全满足实际的监控需求,这时候就需要我们自己根据业务添加自定义监控

[[357469]]

 Prometheus Operator默认的监控指标并不能完全满足实际的监控需求,这时候就需要我们自己根据业务添加自定义监控。添加一个自定义监控的步骤如下:

1、创建一个ServiceMonitor对象,用于Prometheus添加监控项

2、为ServiceMonitor对象关联metrics数据接口的Service对象

3、确保Services对象可以正确获取到metrics数据

下面本文将以如何添加redis监控为例

部署redis

k8s-redis-and-exporter-deployment.yaml

  1. --- 
  2. apiVersion: v1 
  3. kind: Namespace 
  4. metadata: 
  5.   name: redis 
  6. --- 
  7. apiVersion: apps/v1 
  8. kind: Deployment 
  9. metadata: 
  10.   namespace: redis 
  11.   name: redis 
  12. spec: 
  13.   replicas: 1 
  14.   selector: 
  15.     matchLabels: 
  16.       app: redis 
  17.   template: 
  18.     metadata: 
  19.       annotations: 
  20.         prometheus.io/scrape: "true" 
  21.         prometheus.io/port: "9121" 
  22.       labels: 
  23.         app: redis 
  24.     spec: 
  25.       containers: 
  26.       - name: redis 
  27.         image: redis 
  28.         resources: 
  29.           requests: 
  30.             cpu: 100m 
  31.             memory: 100Mi 
  32.         ports: 
  33.         - containerPort: 6379 
  34.       - name: redis-exporter 
  35.         image: oliver006/redis_exporter:latest 
  36.         resources: 
  37.           requests: 
  38.             cpu: 100m 
  39.             memory: 100Mi 
  40.         ports: 
  41.         - containerPort: 9121 

 部署redis的同时,我们把redis_exporter以sidecar的形式和redis服务部署在用一个Pod

另外注意,我们添加了annotations:prometheus.io/scrape: "true" 和 prometheus.io/port: "9121"

创建 Redis Service

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4.   name: redis-svc 
  5.   namespace: redis 
  6.   labels: 
  7.     app: redis 
  8. spec: 
  9.   type: NodePort 
  10.   ports: 
  11.   - name: redis 
  12.     port: 6379 
  13.     targetPort: 6379 
  14.   - name: redis-exporter 
  15.     port: 9121 
  16.     targetPort: 9121 
  17.   selector: 
  18.     app: redis 

 检查下部署好的服务并验证metrics能够获取到数据

  1. [root@]# kubectl get po,ep,svc -n redis 
  2. NAME                         READY   STATUS    RESTARTS   AGE 
  3. pod/redis-78446485d8-sp57x   2/2     Running   0          116m 
  4.  
  5. NAME                  ENDPOINTS                               AGE 
  6. endpoints/redis-svc   100.102.126.3:9121,100.102.126.3:6379   6m5s 
  7.  
  8. NAME                TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE 
  9. service/redis-svc   NodePort   10.105.111.177   <none>        6379:32357/TCP,9121:31019/TCP   6m5s 
  10.  
  11. 验证metrics 
  12. [root@qd01-stop-k8s-master001 MyDefine]# curl 10.105.111.177:9121/metrics 
  13. # HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles. 
  14. # TYPE go_gc_duration_seconds summary 
  15. go_gc_duration_seconds{quantile="0"} 0 
  16. go_gc_duration_seconds{quantile="0.25"} 0 
  17. go_gc_duration_seconds{quantile="0.5"} 0 
  18. go_gc_duration_seconds{quantile="0.75"} 0 
  19. go_gc_duration_seconds{quantile="1"} 0 
  20. go_gc_duration_seconds_sum 0 
  21. go_gc_duration_seconds_count 0 
  22. # HELP go_goroutines Number of goroutines that currently exist. 
  23. # TYPE go_goroutines gauge 
  24. go_goroutines 8 
  25. # HELP go_info Information about the Go environment. 
  26. # TYPE go_info gauge 
  27. ............ 

 创建 ServiceMonitor

现在 Prometheus 访问redis,接下来创建 ServiceMonitor 对象即可

  1. apiVersion: monitoring.coreos.com/v1 
  2. kind: ServiceMonitor 
  3. metadata: 
  4.   name: redis-k8s 
  5.   namespace: monitoring 
  6.   labels: 
  7.     app: redis 
  8. spec: 
  9.   jobLabel: redis 
  10.   endpoints: 
  11.   - port: redis-exporter 
  12.     interval: 30s 
  13.     scheme: http 
  14.   selector: 
  15.     matchLabels: 
  16.       app: redis 
  17.   namespaceSelector: 
  18.     matchNames: 
  19.     - redis 

 执行创建并查看-serviceMonitor

  1. [root@]# kubectl apply -f prometheus-serviceMonitorRedis.yaml 
  2. servicemonitor.monitoring.coreos.com/redis-k8s created 
  3.  
  4. [root@]# kubectl get serviceMonitor -n monitoring 
  5. NAME                      AGE 
  6. redis-k8s                 11s 

 现在切换到PrometheusUI界面查看targets,会发现多了刚才创建的redis-k8s监控项

 现在就可以查询redis-exporter收集到的redis监控指标了


配置 PrometheusRule

我们现在能收集到redis的监控指标了,但是现在并没有配置监控报警规则。需要我们自己根据实际关心的指标添加报警规则

首先我们看下Prometheus默认的规则,大概如下。


现在我们就来为redis添加一条规则,在 Prometheus的 Config 页面下面查看关于 AlertManager 的配置:


上面 alertmanagers 实例的配置我们可以看到是通过角色为 endpoints 的 kubernetes 的服务发现机制获取的,匹配的是服务名为 alertmanager-main,端口名为 web 的 Service 服务,我们查看下 alertmanager-main 这个 Service:

  1. [root@]# kubectl describe svc alertmanager-main -n monitoring 
  2. Name:              alertmanager-main 
  3. Namespace:         monitoring 
  4. Labels:            alertmanager=main 
  5. Annotations:       <none> 
  6. Selector:          alertmanager=main,app=alertmanager 
  7. Type:              ClusterIP 
  8. IP:                10.111.141.65 
  9. Port:              web  9093/TCP 
  10. TargetPort:        web/TCP 
  11. Endpoints:         100.118.246.1:9093,100.64.147.129:9093,100.98.81.194:9093 
  12. Session Affinity:  ClientIP 
  13. Events:            <none> 

可以看到服务名就是 alertmanager-main,Port 定义的名称也是 web,符合上面的规则,所以 Prometheus 和 AlertManager 组件就正确关联上了。而对应的报警规则文件位于:/etc/prometheus/rules/prometheus-k8s-rulefiles-0/目录下面所有的 YAML 文件。可以进入 Prometheus 的 Pod 中验证下该目录下面是否有 YAML 文件:


这个YAML文件实际上就是我们之前创建的一个 PrometheusRule 文件包含的:

这里的 PrometheusRule 的 name 为 prometheus-k8s-rules,namespace 为 monitoring,我们可以猜想到我们创建一个 PrometheusRule 资源对象后,会自动在上面的 prometheus-k8s-rulefiles-0 目录下面生成一个对应的-.yaml文件,所以如果以后我们需要自定义一个报警选项的话,只需要定义一个 PrometheusRule 资源对象即可。至于为什么 Prometheus 能够识别这个 PrometheusRule 资源对象呢?这就查看我们创建的 prometheus( prometheus-prometheus.yaml) 这个资源对象了,里面有非常重要的一个属性 ruleSelector,用来匹配 rule 规则的过滤器,要求匹配具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 资源对象,现在明白了吧?

  1. ruleSelector: 
  2.    matchLabels: 
  3.      prometheus: k8s 
  4.      role: alert-rules 

 所以要想自定义一个报警规则,只需要创建一个具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 对象就行了,比如现在我们添加一个redis是否可用的报警,我们可以通过redis_up这个指标检查redis是否启动,创建文件 prometheus-redisRules.yaml:

  1. apiVersion: monitoring.coreos.com/v1 
  2. kind: PrometheusRule 
  3. metadata: 
  4.   labels: 
  5.     prometheus: k8s 
  6.     role: alert-rules 
  7.   name: redis-rules 
  8.   namespace: monitoring 
  9. spec: 
  10.   groups: 
  11.   - name: redis 
  12.     rules: 
  13.     - alert: RedisUnavailable 
  14.       annotations: 
  15.         summary: redis instance info 
  16.         description: If redis_up == 0, redis will be unavailable 
  17.       expr: | 
  18.         redis_up == 0 
  19.       for: 3m 
  20.       labels: 
  21.         severity: critical 

 创建prometheusrule后,可以看到我们自己创建的redis-rules

  1. kubectl apply -f prometheus-redisRules.yaml 
  2.  
  3. kubectl get prometheusrule -n monitoring 
  4. NAME                   AGE 
  5. etcd-rules             4d18h 
  6. prometheus-k8s-rules   17d 
  7. redis-rules            15s 

注意 label 标签一定至少要有 prometheus=k8s 或 role=alert-rules,创建完成后,隔一会儿再去容器中查看下 rules 文件夹:


现在看到我们创建的 rule 文件已经被注入到了对应的 rulefiles 文件夹下面了。然后再去 Prometheus的 Alert 页面下面就可以查看到上面我们新建的报警规则了:


配置报警

现在我们知道了怎么去添加一个报警规则配置项,但是这些报警信息用怎样的方式去发送呢?

这个就需要我们配置alertmanager

这里我以邮件和微信为例

alertmanager的配置文件alertmanager.yaml使用 alertmanager-secret.yaml 文件创建,这里看下默认的配置

cat alertmanager-secret.yaml

  1. apiVersion: v1 
  2. kind: Secret 
  3. metadata: 
  4.   name: alertmanager-main 
  5.   namespace: monitoring 
  6. stringData: 
  7.   alertmanager.yaml: |- 
  8.     "global"
  9.       "resolve_timeout""5m" 
  10.     "inhibit_rules"
  11.     - "equal"
  12.       - "namespace" 
  13.       - "alertname" 
  14.       "source_match"
  15.         "severity""critical" 
  16.       "target_match_re"
  17.         "severity""warning|info" 
  18.     - "equal"
  19.       - "namespace" 
  20.       - "alertname" 
  21.       "source_match"
  22.         "severity""warning" 
  23.       "target_match_re"
  24.         "severity""info" 
  25.     "receivers"
  26.     - "name""Default" 
  27.     - "name""Watchdog" 
  28.     - "name""Critical" 
  29.     "route"
  30.       "group_by"
  31.       - "namespace" 
  32.       "group_interval""5m" 
  33.       "group_wait""30s" 
  34.       "receiver""Default" 
  35.       "repeat_interval""12h" 
  36.       "routes"
  37.       - "match"
  38.           "alertname""Watchdog" 
  39.         "receiver""Watchdog" 
  40.       - "match"
  41.           "severity""critical" 
  42.         "receiver""Critical" 
  43. type: Opaque 

 现在我们需要修改这个文件,配置微信和邮件相关信息,前提你需要自行准备好企业微信相关信息,可以自行网上搜相关教程。

首先创建alertmanager.yaml文件

  1. global
  2.   resolve_timeout: 5m 
  3.   smtp_smarthost: 'smtp.51os.club:25' 
  4.   smtp_from: 'amos' 
  5.   smtp_auth_username: 'amos@51os.club' 
  6.   smtp_auth_password: 'Mypassword' 
  7.   smtp_hello: '51os.club' 
  8.   smtp_require_tls: false 
  9.   wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/' 
  10.   wechat_api_secret: 'SGGc4x-RDcVD_ptvVhYrxxxxxxxxxxOhWVWIITRxM' 
  11.   wechat_api_corp_id: 'ww419xxxxxxxx735e1c0' 
  12.  
  13. templates: 
  14. '*.tmpl' 
  15.  
  16. route: 
  17.   group_by: ['job''severity'
  18.   group_wait: 30s 
  19.   group_interval: 5m 
  20.   repeat_interval: 12h 
  21.   receiver: default 
  22.   routes: 
  23.   - receiver: wechat 
  24.     continuetrue 
  25.     match: 
  26.       alertname: Watchdog 
  27.  
  28. receivers: 
  29. name'default' 
  30.   email_configs: 
  31.   - to'10xxxx1648@qq.com' 
  32.     send_resolved: true 
  33. name'wechat' 
  34.   wechat_configs: 
  35.   - send_resolved: false 
  36.     corp_id: 'ww419xxxxxxxx35e1c0' 
  37.     to_party: '13' 
  38.     message: '{{ template "wechat.default.message" . }}' 
  39.     agent_id: '1000003' 
  40.     api_secret: 'SGGc4x-RDcxxxxxxxxY6YwfZFsO9OhWVWIITRxM' 

 我这里添加了两个接收器,默认的通过邮箱进行发送,对于 Watchdog 这个报警我们通过 webhook 来进行发送,这个 webhook 就是wechat。

说明我这里偷懒,因为现在系统刚好有一个报警Watchdog,所以我这里匹配了 Watchdog 这个报警,当然您可以换成我们自定义的redis的监控RedisUnavailable

 然后使用在创建一个templates文件,这个文件是发微信消息的模板wechat.tmpl:

  1. {{ define "wechat.default.message" }} 
  2. {{- if gt (len .Alerts.Firing) 0 -}} 
  3. {{- range $index, $alert := .Alerts -}} 
  4. {{- if eq $index 0 -}} 
  5. AlertTpye: {{ $alert.Labels.alertname }} 
  6. AlertLevel: {{ $alert.Labels.severity }} 
  7.  
  8. ===================== 
  9. {{- end }} 
  10. ===Alert Info=== 
  11. Alert Info: {{ $alert.Annotations.message }} 
  12. Alert Time: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }} 
  13. ===More Info=== 
  14. {{ if gt (len $alert.Labels.instance) 0 -}}InstanceIp: {{ $alert.Labels.instance }};{{- end -}} 
  15. {{- if gt (len $alert.Labels.namespace) 0 -}}InstanceNamespace: {{ $alert.Labels.namespace }};{{- end -}} 
  16. {{- if gt (len $alert.Labels.node) 0 -}}NodeIP: {{ $alert.Labels.node }};{{- end -}} 
  17. {{- if gt (len $alert.Labels.pod_name) 0 -}}PodName: {{ $alert.Labels.pod_name }}{{- end }} 
  18. ===================== 
  19. {{- end }} 
  20. {{- end }} 
  21.  
  22. {{- if gt (len .Alerts.Resolved) 0 -}} 
  23. {{- range $index, $alert := .Alerts -}} 
  24. {{- if eq $index 0 -}} 
  25. AlertTpye: {{ $alert.Labels.alertname }} 
  26. AlertLevel: {{ $alert.Labels.severity }} 
  27.  
  28. ===================== 
  29. {{- end }} 
  30. ===Alert Info=== 
  31. Alert Info: {{ $alert.Annotations.message }} 
  32. Alert Start Time: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }} 
  33. Alert Fix Time: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }} 
  34. ===More Info=== 
  35. {{ if gt (len $alert.Labels.instance) 0 -}}InstanceIp: {{ $alert.Labels.instance }};{{- end -}} 
  36. {{- if gt (len $alert.Labels.namespace) 0 -}}InstanceNamespace: {{ $alert.Labels.namespace }};{{- end -}} 
  37. {{- if gt (len $alert.Labels.node) 0 -}}NodeIP: {{ $alert.Labels.node }};{{- end -}} 
  38. {{- if gt (len $alert.Labels.pod_name) 0 -}}PodName: {{ $alert.Labels.pod_name }};{{- end }} 
  39. ===================== 
  40. {{- end }} 
  41. {{- end }} 
  42. {{- end }} 

 现在我们先删除原来的 alertmanager-main secret,然后再基于alertmanager.yaml和wechat.tmpl创建alertmanager-main secret 

  1. kubectl delete secret alertmanager-main -n monitoring 
  2. kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml --from-file=wechat.tmpl -n monitoring 

 上面的步骤创建完成后,很快我们就会收到一条wechat消息,同样邮箱中也会收到报警信息:


再次查看 AlertManager 的配置信息可以看到已经变成上面我们的配置信息了

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-03-26 20:37:14

Prometheus监控指标

2021-11-08 09:00:00

PrometheusKubernetes集群

2023-12-29 08:01:52

自定义指标模板

2021-05-28 08:58:41

Golang网卡metrics

2023-03-26 08:41:37

2021-10-28 08:39:22

Node Export自定义 监控

2013-01-10 09:36:19

NagiosNagios插件

2016-02-26 14:57:50

飞象网

2015-02-12 15:33:43

微信SDK

2011-04-06 15:05:58

nagios监控Linux

2015-02-12 15:38:26

微信SDK

2016-12-26 15:25:59

Android自定义View

2016-11-16 21:55:55

源码分析自定义view androi

2011-06-23 10:49:13

Qt 自定义信号

2011-12-16 14:23:51

Java

2009-06-08 20:13:36

Eclipse自定义控

2013-04-01 14:35:10

Android开发Android自定义x

2015-01-14 15:06:48

定义相机

2022-04-24 15:17:56

鸿蒙操作系统

2021-11-23 15:06:42

Kubernetes 运维开源
点赞
收藏

51CTO技术栈公众号