【Prometheus】基于Altertmanager发送告警到多个接收方、监控各种服务、pushgateway

基于Altertmanager发送报警到多个接收方

  • 一、配置alertmanager-发送告警到qq邮箱
    • 1.1、告警流程
    • 1.2、告警设置
      • 【1】邮箱配置
      • 【2】告警规则配置
      • 【3】 部署prometheus
      • 【4】部署service
  • 二、配置alertmanager-发送告警到钉钉
  • 三、配置alertmanager-发送告警到企业微信
    • 3.1、注册企业微信
    • 3.2、修改alertmanager-cm.yaml
  • 四、Prometheus PromQL语法
    • 4.1、数据类型
      • 【1】瞬时向量选择
      • 【2】区间向量选择
      • 【3】偏移向量选择器
      • 【4】聚合操作符
      • 【5】函数
  • 五、Prometheus监控扩展
    • 5.1、promethues采集tomcat监控数据
    • 5.2、promethues采集redis监控数据
    • 5.3、Prometheus监控mysql
      • 【1】安装mysql、mariadb
      • 【2】登陆mysql为mysql_exporter创建账号并授权
      • 【3】创建mysql配置文件、运行时可免密码连接数据库
      • 【4】启动mysql_exporter客户端
      • 【5】修改prometheus-alertmanager-cfg.yaml文件
      • 【6】grafana导入mysql监控图表
    • 5.4、Prometheus监控Nginx
    • 5.5、prometheus监控mongodb
  • 六、Pushgateway
    • 6.1、简介
    • 6.2、优缺点
    • 6.3、实践
      • 【1】部署pushgateway
      • 【2】推送简单数据
      • 【3】推送复杂数据
      • 【4】删除某个组下某个实例的所有数据
      • 【5】删除某个组下的所有数据:
      • 【6】把数据上报到pushgateway

一、配置alertmanager-发送告警到qq邮箱

1.1、告警流程

1. Prometheus Server监控目标主机上暴露的http接口(这里假设接口A),通过Promethes配置的’scrape_interval’定义的时间间隔,定期采集目标主机上监控数据。

2. 当接口A不可用的时候,Server端会持续的尝试从接口中取数据,直到"scrape_timeout"时间后停止尝试。这时候把接口的状态变为“DOWN”。

3. Prometheus同时根据配置的"evaluation_interval"的时间间隔,定期(默认1min)的对Alert Rule进行评估;
当到达评估周期的时候,发现接口A为DOWN,即UP=0为真,激活Alert,进入“PENDING”状态,并记录当前active的时间;

4. 当下一个alert rule的评估周期到来的时候,发现UP=0继续为真,然后判断警报Active的时间是否已经超出rule里的‘for’ 持续时间,如果未超出,则进入下一个评估周期;如果时间超出,则alert的状态变为“FIRING”;同时调用Alertmanager接口,发送相关报警数据。

5. AlertManager收到报警数据后,会将警报信息进行分组,然后根据alertmanager配置的“group_wait”时间先进行等待。等wait时间过后再发送报警信息。

6. 属于同一个Alert Group的警报,在等待的过程中可能进入新的alert,如果之前的报警已经成功发出,那么间隔“group_interval”的时间间隔后再重新发送报警信息。比如配置的是邮件报警,那么同属一个group的报警信息会汇总在一个邮件里进行发送。

7. 如果Alert Group里的警报一直没发生变化并且已经成功发送,等待‘repeat_interval’时间间隔之后再重复发送相同的报警邮件;如果之前的警报没有成功发送,则相当于触发第6条条件,则需要等待group_interval时间间隔后重复发送。

1.2、告警设置

报警:指prometheus将监测到的异常事件发送给alertmanager
通知:alertmanager将报警信息发送到邮件、微信、钉钉等

【1】邮箱配置

邮箱设置:
在这里插入图片描述
开启的时候就会出现授权码,授权码只出现一次,要保存好。

邮箱配置

[root@master 3]# cat alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:name: alertmanagernamespace: monitor-sa
data:alertmanager.yml: |-global:resolve_timeout: 1msmtp_smarthost: 'smtp.163.com:25' # 163邮箱的SMTP服务器地址+端口smtp_from: '15011572xxx@163.com'  # 这是指定从哪个邮箱发送报警 smtp_auth_username: '15011572xxx' # 发送邮箱的授权码smtp_auth_password: 'BGWHYUOSOOHWEUJM'  # 改成自己的smtp_require_tls: falseroute:  # 用于配置告警分发策略group_by: [alertname] # 采用哪个标签来作为分组依据group_wait: 10s		# 组告警等待时间。也就是告警产生后等待10s,如果有同组告警一起发出group_interval: 10s   # 上下两组发送告警的间隔时间repeat_interval: 10m  # 重复发送告警的时间,减少相同邮件的发送频率,默认是1hreceiver: default-receiver  # 定义谁来收告警receivers:- name: 'default-receiver'email_configs:- to: '1011776350@qq.com'send_resolved: true
[root@master 3]# k apply -f alertmanager-cm.yaml
configmap/alertmanager created
[root@master 3]# k get cm -n monitor-sa
NAME                DATA   AGE
alertmanager        1      25s

【2】告警规则配置

[root@master 3]# cat prometheus-alertmanager-cfg.yaml
kind: ConfigMap
apiVersion: v1
metadata:labels:app: prometheusname: prometheus-confignamespace: monitor-sa
data:prometheus.yml: |rule_files:- /etc/prometheus/rules.ymlalerting:alertmanagers:- static_configs:- targets: ["localhost:9093"]global:scrape_interval: 15sscrape_timeout: 10sevaluation_interval: 1mscrape_configs:- job_name: 'kubernetes-node'kubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)- job_name: 'kubernetes-node-cadvisor'kubernetes_sd_configs:- role:  nodescheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor- job_name: 'kubernetes-apiserver'kubernetes_sd_configs:- role: endpointsscheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]action: keepregex: default;kubernetes;https- job_name: 'kubernetes-service-endpoints'kubernetes_sd_configs:- role: endpointsrelabel_configs:- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]action: replacetarget_label: __scheme__regex: (https?)- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]action: replacetarget_label: __address__regex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]action: replacetarget_label: kubernetes_name- job_name: 'kubernetes-pods'kubernetes_sd_configs:- role: podrelabel_configs:- action: keepregex: truesource_labels:- __meta_kubernetes_pod_annotation_prometheus_io_scrape- action: replaceregex: (.+)source_labels:- __meta_kubernetes_pod_annotation_prometheus_io_pathtarget_label: __metrics_path__- action: replaceregex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2source_labels:- __address__- __meta_kubernetes_pod_annotation_prometheus_io_porttarget_label: __address__- action: labelmapregex: __meta_kubernetes_pod_label_(.+)- action: replacesource_labels:- __meta_kubernetes_namespacetarget_label: kubernetes_namespace- action: replacesource_labels:- __meta_kubernetes_pod_nametarget_label: kubernetes_pod_name- job_name: 'kubernetes-etcd'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crtcert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crtkey_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.keyscrape_interval: 5sstatic_configs:- targets: ['10.32.1.147:2379']rules.yml: |groups:- name: examplerules:- alert: apiserver的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert:  apiserver的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: etcd的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert:  etcd的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: kube-state-metrics的cpu使用率大于80%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过80%"value: "{{ $value }}%"threshold: "80%"- alert: kube-state-metrics的cpu使用率大于90%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 0for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过90%"value: "{{ $value }}%"threshold: "90%"- alert: coredns的cpu使用率大于80%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过80%"value: "{{ $value }}%"threshold: "80%"- alert: coredns的cpu使用率大于90%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过90%"value: "{{ $value }}%"threshold: "90%"- alert: kube-proxy打开句柄数>600expr: process_open_fds{job=~"kubernetes-kube-proxy"}  > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kube-proxy打开句柄数>1000expr: process_open_fds{job=~"kubernetes-kube-proxy"}  > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-schedule打开句柄数>600expr: process_open_fds{job=~"kubernetes-schedule"}  > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-schedule打开句柄数>1000expr: process_open_fds{job=~"kubernetes-schedule"}  > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-controller-manager打开句柄数>600expr: process_open_fds{job=~"kubernetes-controller-manager"}  > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-controller-manager打开句柄数>1000expr: process_open_fds{job=~"kubernetes-controller-manager"}  > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-apiserver打开句柄数>600expr: process_open_fds{job=~"kubernetes-apiserver"}  > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-apiserver打开句柄数>1000expr: process_open_fds{job=~"kubernetes-apiserver"}  > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-etcd打开句柄数>600expr: process_open_fds{job=~"kubernetes-etcd"}  > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-etcd打开句柄数>1000expr: process_open_fds{job=~"kubernetes-etcd"}  > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"}  > 600for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过600"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"}  > 1000for: 2slabels:severity: criticalannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过1000"value: "{{ $value }}"- alert: kube-proxyexpr: process_virtual_memory_bytes{job=~"kubernetes-kube-proxy"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: schedulerexpr: process_virtual_memory_bytes{job=~"kubernetes-schedule"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-controller-managerexpr: process_virtual_memory_bytes{job=~"kubernetes-controller-manager"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-apiserverexpr: process_virtual_memory_bytes{job=~"kubernetes-apiserver"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-etcdexpr: process_virtual_memory_bytes{job=~"kubernetes-etcd"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kube-dnsexpr: process_virtual_memory_bytes{k8s_app=~"kube-dns"}  > 2000000000for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: HttpRequestsAvgexpr: sum(rate(rest_client_requests_total{job=~"kubernetes-kube-proxy|kubernetes-kubelet|kubernetes-schedule|kubernetes-control-manager|kubernetes-apiservers"}[1m]))  > 1000for: 2slabels:team: adminannotations:description: "组件{{$labels.job}}({{$labels.instance}}): TPS超过1000"value: "{{ $value }}"threshold: "1000"- alert: Pod_restartsexpr: kube_pod_container_status_restarts_total{namespace=~"kube-system|default|monitor-sa"} > 0for: 2slabels:severity: warnningannotations:description: "在{{$labels.namespace}}名称空间下发现{{$labels.pod}}这个pod下的容器{{$labels.container}}被重启,这个监控指标是由{{$labels.instance}}采集的"value: "{{ $value }}"threshold: "0"- alert: Pod_waitingexpr: kube_pod_container_status_waiting_reason{namespace=~"kube-system|default"} == 1for: 2slabels:team: adminannotations:description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}启动异常等待中"value: "{{ $value }}"threshold: "1"- alert: Pod_terminatedexpr: kube_pod_container_status_terminated_reason{namespace=~"kube-system|default|monitor-sa"} == 1for: 2slabels:team: adminannotations:description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}被删除"value: "{{ $value }}"threshold: "1"- alert: Etcd_leaderexpr: etcd_server_has_leader{job="kubernetes-etcd"} == 0for: 2slabels:team: adminannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 当前没有leader"value: "{{ $value }}"threshold: "0"- alert: Etcd_leader_changesexpr: rate(etcd_server_leader_changes_seen_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:team: adminannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 当前leader已发生改变"value: "{{ $value }}"threshold: "0"- alert: Etcd_failedexpr: rate(etcd_server_proposals_failed_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:team: adminannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 服务失败"value: "{{ $value }}"threshold: "0"- alert: Etcd_db_total_sizeexpr: etcd_debugging_mvcc_db_total_size_in_bytes{job="kubernetes-etcd"} > 10000000000for: 2slabels:team: adminannotations:description: "组件{{$labels.job}}({{$labels.instance}}):db空间超过10G"value: "{{ $value }}"threshold: "10G"- alert: Endpoint_readyexpr: kube_endpoint_address_not_ready{namespace=~"kube-system|default"} == 1for: 2slabels:team: adminannotations:description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.endpoint}}不可用"value: "{{ $value }}"threshold: "1"- name: 物理节点状态-监控告警rules:- alert: 物理节点cpu使用率expr: 100-avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by(instance)*100 > 90for: 2slabels:severity: ccriticalannotations:summary: "{{ $labels.instance }}cpu使用率过高"description: "{{ $labels.instance }}的cpu使用率超过90%,当前使用率[{{ $value }}],需要排查处理"- alert: 物理节点内存使用率expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}内存使用率过高"description: "{{ $labels.instance }}的内存使用率超过90%,当前使用率[{{ $value }}],需要排查处理"- alert: InstanceDownexpr: up == 0for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}: 服务器宕机"description: "{{ $labels.instance }}: 服务器延时超过2分钟"- alert: 物理节点磁盘的IO性能expr: 100-(avg(irate(node_disk_io_time_seconds_total[1m])) by(instance)* 100) < 60for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流入磁盘IO使用率过高!"description: "{{$labels.mountpoint }} 流入磁盘IO大于60%(目前使用:{{$value}})"- alert: 入网流量带宽expr: ((sum(rate (node_network_receive_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流入网络带宽过高!"description: "{{$labels.mountpoint }}流入网络带宽持续5分钟高于100M. RX带宽使用率{{$value}}"- alert: 出网流量带宽expr: ((sum(rate (node_network_transmit_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流出网络带宽过高!"description: "{{$labels.mountpoint }}流出网络带宽持续5分钟高于100M. RX带宽使用率{{$value}}"- alert: TCP会话expr: node_netstat_Tcp_CurrEstab > 1000for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} TCP_ESTABLISHED过高!"description: "{{$labels.mountpoint }} TCP_ESTABLISHED大于1000%(目前使用:{{$value}}%)"- alert: 磁盘容量expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes {fstype=~"ext4|xfs"}*100) > 80for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 磁盘分区使用率过高!"description: "{{$labels.mountpoint }} 磁盘分区使用大于80%(目前使用:{{$value}}%)"
[root@master 3]# k apply -f  prometheus-alertmanager-cfg.yaml
[root@master 3]# k get cm -n monitor-sa
NAME                DATA   AGE
alertmanager        1      7h52m
kube-root-ca.crt    1      7d12h
prometheus-config   2      7d7h  # 已生成

【3】 部署prometheus

生成一个etcd-certs,这个在部署prometheus需要

[root@master 3]# 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
secret/etcd-certs created
[root@node01 package]# ctr -n=k8s.io images import  alertmanager.tar.gz
[root@master 3]# cat prometheus-alertmanager-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:name: prometheus-servernamespace: monitor-salabels:app: prometheus
spec:replicas: 1selector:matchLabels:app: prometheuscomponent: server#matchExpressions:#- {key: app, operator: In, values: [prometheus]}#- {key: component, operator: In, values: [server]}template:metadata:labels:app: prometheuscomponent: serverannotations:prometheus.io/scrape: 'false'spec:nodeName: node01  # 换成自己节点的名字serviceAccountName: monitorcontainers:- name: prometheusimage: prom/prometheus:v2.2.1imagePullPolicy: IfNotPresentcommand:- "/bin/prometheus"args:- "--config.file=/etc/prometheus/prometheus.yml"- "--storage.tsdb.path=/prometheus"- "--storage.tsdb.retention=24h"- "--web.enable-lifecycle"ports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: /etc/prometheusname: prometheus-config- mountPath: /prometheus/name: prometheus-storage-volume- name: k8s-certsmountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/- name: alertmanagerimage: prom/alertmanager:v0.14.0imagePullPolicy: IfNotPresentargs:- "--config.file=/etc/alertmanager/alertmanager.yml"- "--log.level=debug"ports:- containerPort: 9093protocol: TCPname: alertmanagervolumeMounts:- name: alertmanager-configmountPath: /etc/alertmanager- name: alertmanager-storagemountPath: /alertmanager- name: localtimemountPath: /etc/localtimevolumes:- name: prometheus-configconfigMap:name: prometheus-config- name: prometheus-storage-volumehostPath:path: /datatype: Directory- name: k8s-certssecret:secretName: etcd-certs- name: alertmanager-configconfigMap:name: alertmanager- name: alertmanager-storagehostPath:path: /data/alertmanagertype: DirectoryOrCreate- name: localtimehostPath:path: /usr/share/zoneinfo/Asia/Shanghai

部署prometheus

[root@master 3]# kubectl apply -f prometheus-alertmanager-deploy.yaml
deployment.apps/prometheus-server configured
[root@master 3]# kubectl get pods -n monitor-sa -owide| grep prometheus
prometheus-server-cf55fc89b-mfk9z   2/2     Running   0          8h      10.244.196.151   node01   <none>           <none># 如果修改了这个配置文件,需要热加载一下
curl -X POST 10.244.196.151:9090/-/reload

【4】部署service

部署alertmanager的service,方便在浏览器访问

[root@master 3]# cat alertmanager-svc.yaml
---
apiVersion: v1
kind: Service
metadata:labels:name: prometheuskubernetes.io/cluster-service: 'true'name: alertmanagernamespace: monitor-sa
spec:ports:- name: alertmanagernodePort: 30066port: 9093protocol: TCPtargetPort: 9093selector:app: prometheussessionAffinity: Nonetype: NodePort
[root@master 3]# k apply -f alertmanager-svc.yaml
service/alertmanager created
[root@master 3]# kubectl get svc -n monitor-sa
NAME           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
alertmanager   NodePort   10.99.35.142     <none>        9093:30066/TCP   18s
prometheus     NodePort   10.104.116.119   <none>        9090:31000/TCP   7d9h
# 注意:上面可以看到prometheus的service在物理机映射的端口是31000,
# alertmanager的service在物理机映射的端口是30066

浏览器访问:http://10.32.1.147:30066/#/alerts
在这里插入图片描述
访问prometheus的web界面
点击status->targets,可看到如下
在这里插入图片描述
点击Alerts,可看到如下
在这里插入图片描述
此时查看自己的邮箱,是会有告警邮件产生的。

二、配置alertmanager-发送告警到钉钉

三、配置alertmanager-发送告警到企业微信

3.1、注册企业微信

登陆网址:
https://work.weixin.qq.com/
找到应用管理,创建应用
应用名字wechat
创建成功之后显示如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.2、修改alertmanager-cm.yaml

kind: ConfigMap
apiVersion: v1
metadata:name: alertmanagernamespace: monitor-sa
data:alertmanager.yml: |-global:resolve_timeout: 1msmtp_smarthost: 'smtp.163.com:25'smtp_from: '18874165690@163.com'smtp_auth_username: '18874165690'smtp_auth_password: 'WZCYMKKQMZRYFICZ'smtp_require_tls: falseroute:group_by: [alertname]group_wait: 10sgroup_interval: 10srepeat_interval: 10sreceiver: prometheusreceivers:- name: 'prometheus'wechat_configs:- corp_id: wwb510050c4fd9ef9cto_user: '@all'agent_id: 1000003api_secret: p8qOyWIIHPMqzYn-_MsCa8MHYilUn7b5TUjb22xrokU

参数说明:

  • secret: 企业微信(“企业应用”–>“自定应用”[Prometheus]–> “Secret”)
  • corp_id:企业信息(“我的企业”—>“CorpID”[在底部])
  • agent_id: 企业微信(“企业应用”–>“自定应用”[Prometheus]–> “AgentId”)
  • wechat是自创建应用名称 #在这创建的应用名字是wechat,那么在配置route时,receiver也应该是Prometheus
  • to_user: ‘@all’ :发送报警到所有人
[root@master 3]# k delete -f alertmanager-cm.yaml
[root@master 3]# k apply -f alertmanager-cm.yaml
[root@master 3]# k delete -f prometheus-alertmanager-deploy.yaml
[root@master 3]# k apply -f prometheus-alertmanager-deploy.yaml
[root@master 3]# k get pods -n monitor-sa
NAME                                READY   STATUS    RESTARTS   AGE
node-exporter-tjlfj                 1/1     Running   0          8d
node-exporter-v8fc5                 1/1     Running   0          8d
node-exporter-zxsch                 1/1     Running   0          8d
prometheus-server-cf55fc89b-f2xnd   2/2     Running   0          17s

后续可查看企微是否收到告警

四、Prometheus PromQL语法

4.1、数据类型

PromQL 表达式计算出来的值有以下几种类型:

  • 瞬时向量 (Instant vector): 一组时序,每个时序只有一个采样值
  • 区间向量 (Range vector): 一组时序,每个时序包含一段时间内的多个采样值
  • 标量数据 (Scalar): 一个浮点数
  • 字符串 (String): 一个字符串,暂时未用

【1】瞬时向量选择

用来选择一组时序在某个采样点的采样值
最简单的情况就是制定一个度量指标,选择出所有属于该度量指标的时序的当前采样值。
比如下面的表达式:apiserver_request_total

在这里插入图片描述

可以通过在后面添加大括号保卫起来的足以标签键值对来对时序进行过滤。
比如下面的表达式筛选出了job为 kubernetes-apiservers,并且 resource为 pod的时序:
在这里插入图片描述

匹配标签值时可以是等于,也可以使用正则表达式。总共有下面几种匹配操作符:
=:完全相等
!=: 不相等
=~: 正则表达式匹配
!~: 正则表达式不匹配

下面的表达式筛选出了container是kube-scheduler或kube-proxy或kube-apiserver的时序数据
container_processes{container=~“kube-scheduler|kube-proxy|kube-apiserver”}
在这里插入图片描述

【2】区间向量选择

类似于瞬时向量选择器,不同的是它选择的是过去一段时间的采样值。
可以通过在瞬时向量选择器后面添加包含在[]里的时长来得到区间向量选择器。
比如下面的表达式选出了所有度量指标为 apiserver_request_total且resource是pod的时序在过去1 分钟的采样值。
在这里插入图片描述
这个不支持Graph,需要选择Console,才会看到采集的数据。

说明:时长的单位可以是下面几种之一:
s:seconds
m:minutes
h:hours
d:days
w:weeks
y:years

【3】偏移向量选择器

前面介绍的选择器默认都是以当前时间为基准时间,偏移修饰器用来调整基准时间,使其往前偏移一段时间。
偏移修饰器紧跟在选择器后面,使用 offset 来指定要偏移的量。比如下面的表达式选择度量名称为apiserver_request_total的所有时序在 5 分钟前的采样值。
apiserver_request_total{job=“kubernetes-apiserver”,resource=“pods”} offset 5m

下面的表达式选择apiserver_request_total 度量指标在 1 周前的这个时间点过去 5 分钟的采样值。
apiserver_request_total{job=“kubernetes-apiserver”,resource=“pods”} [5m] offset 1w
在这里插入图片描述

【4】聚合操作符

PromQL 的聚合操作符用来将向量里的元素聚合得更少。总共有下面这些聚合操作符:

sum:求和
min:最小值
max:最大值
avg:平均值
stddev:标准差
stdvar:方差
count:元素个数
count_values:等于某值的元素个数
bottomk:最小的 k 个元素
topk:最大的 k 个元素
quantile:分位数

  • 计算master节点所有容器总计内存
    sum(container_memory_usage_bytes{instance=~“master”})/1024/1024/1024
    在这里插入图片描述

  • 计算master节点最近1m所有容器cpu使用率
    sum (rate (container_cpu_usage_seconds_total{instance=~“xianchaomaster1”}[1m])) / sum (machine_cpu_cores{ instance =~“xianchaomaster1”}) * 100
    在这里插入图片描述

  • 计算最近1m所有容器cpu使用率
    sum (rate (container_cpu_usage_seconds_total{id!=“/”}[1m])) by (id)
    #把id会打印出来
    结果如下:
    在这里插入图片描述

【5】函数

Prometheus 内置了一些函数来辅助计算,下面介绍一些典型的。

abs():绝对值
sqrt():平方根
exp():指数计算
ln():自然对数
ceil():向上取整
floor():向下取整
round():四舍五入取整
delta():计算区间向量里每一个时序第一个和最后一个的差值
sort():排序

五、Prometheus监控扩展

5.1、promethues采集tomcat监控数据

https://note.youdao.com/ynoteshare/index.html?id=0ddfc17eaf7bac94ad4497d7f5356213&type=note

5.2、promethues采集redis监控数据

https://note.youdao.com/ynoteshare/index.html?id=b9f87092ce8859cd583967677ea332df&type=note

5.3、Prometheus监控mysql

【1】安装mysql、mariadb

yum install mysql -y 
yum install mariadb  -y
# 上传课件里面的压缩包mysqld_exporter-0.10.0.linux-amd64.tar.gz,然后解压
tar -xvf mysqld_exporter-0.10.0.linux-amd64.tar.gz
cp -ar mysqld_exporter /usr/local/bin/
chmod +x /usr/local/bin/mysqld_exporter

【2】登陆mysql为mysql_exporter创建账号并授权

-- 创建数据库用户
mysql> CREATE USER 'mysql_exporter'@'localhost' IDENTIFIED BY 'Abcdef123!.';
Query OK, 0 rows affected (0.03 sec)
-- 对mysql_exporter用户授权
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_exporter'@'localhost';
Query OK, 0 rows affected (0.00 sec)
-- exit 退出mysql

【3】创建mysql配置文件、运行时可免密码连接数据库

[root@node01 ~]# cat my.cnf
[client]
user=mysql_exporter
password=Abcdef123!.

【4】启动mysql_exporter客户端

[root@node01 ~]# nohup mysqld_exporter --config.my-cnf=./my.cnf &
# mysqld_exporter的监听端口是9104
[root@node01 ~]# lsof -i:9104
COMMAND    PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
mysqld_ex 2216 root    3u  IPv6 723617678      0t0  TCP *:peerwire (LISTEN)

【5】修改prometheus-alertmanager-cfg.yaml文件

# 添加一个job name
- job_name: 'mysql'static_configs:- targets: ['10.32.1.148:9104']
[root@master 3]# vim prometheus-alertmanager-cfg.yaml
[root@master 3]# kubectl apply -f prometheus-alertmanager-cfg.yaml
configmap/prometheus-config configured
[root@master 3]# kubectl delete -f prometheus-alertmanager-deploy.yaml
deployment.apps "prometheus-server" deleted
[root@master 3]# kubectl apply -f prometheus-alertmanager-deploy.yaml
deployment.apps/prometheus-server created

访问prometheus查看:http://10.32.1.147:31000/targets

在这里插入图片描述

【6】grafana导入mysql监控图表

mysql-overview_rev5.json
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.4、Prometheus监控Nginx

https://note.youdao.com/ynoteshare/index.html?id=bea7b4b8f9a78db1679e1ac2ab747da5&type=note

5.5、prometheus监控mongodb

https://note.youdao.com/ynoteshare/index.html?id=39b54acb1fbc0199f966115ce9523bb6&type=note

六、Pushgateway

6.1、简介

Pushgateway是prometheus的一个组件,prometheus server默认是通过exporter主动获取数据(默认采取pull拉取数据),pushgateway则是通过被动方式推送数据到prometheus server,用户可以写一些自定义的监控脚本把需要监控的数据发送给pushgateway, 然后pushgateway再把数据发送给Prometheus server

6.2、优缺点

  • 优点
    Prometheus 默认采用定时pull 模式拉取targets数据,但是如果不在一个子网或者防火墙,prometheus就拉取不到targets数据,所以可以采用各个target往pushgateway上push数据,然后prometheus去pushgateway上定时pull数据
    在监控业务数据的时候,需要将不同数据汇总, 汇总之后的数据可以由pushgateway统一收集,然后由 Prometheus 统一拉取。
  • 缺点
    Prometheus拉取状态只针对 pushgateway, 不能对每个节点都有效;
    Pushgateway出现问题,整个采集到的数据都会出现问题
    监控下线,prometheus还会拉取到旧的监控数据,需要手动清理 pushgateway不要的数据。

6.3、实践

【1】部署pushgateway

安装pushgateway,在工作节点node01(10.32.1.148)操作
将课件中的安装包pushgateway.tar.gz上传到节点

[root@node01 package]# ll|grep push
-rw-r--r--  1 root      root         21320704 Feb 28 09:32 pushgateway.tar.gz
[root@node01 package]# docker load -i pushgateway.tar.gz
4d688dd2e2c4: Loading layer [==================================================>]  17.23MB/17.23MB
5447bffb5beb: Loading layer [==================================================>]  2.048kB/2.048kB
Loaded image: prom/pushgateway:latest
You have mail in /var/spool/mail/root
[root@node01 package]# lsof -i:9091
[root@node01 package]# docker run -d --name pushgateway -p 9091:9091 prom/pushgateway
ff87ff2c6f088a322f63e086883ca475602f13f30f209ded861c5530144b7a93

浏览器访问 http://10.32.1.148:9091/,出现如下ui界面
在这里插入图片描述
修改prometheus-alertmanager-cfg.yaml配置文件:

 - job_name: 'pushgateway'scrape_interval: 5sstatic_configs:- targets: ['10.32.1.148:9091']honor_labels: true
[root@master 3]# vim prometheus-alertmanager-cfg.yaml
[root@master 3]# k apply -f prometheus-alertmanager-cfg.yaml
configmap/prometheus-config configured
[root@master 3]# k delete -f prometheus-alertmanager-deploy.yaml
deployment.apps "prometheus-server" deleted
[root@master 3]# k apply -f prometheus-alertmanager-deploy.yaml
deployment.apps/prometheus-server created

在prometheus的targets列表可以看到pushgateway
在这里插入图片描述
可以查看pushgateway相关指标
在这里插入图片描述

【2】推送简单数据

推送指定的数据格式到pushgateway

# 向 {job="test_job"} 添加单条数据:
[root@node01 package]# echo " metric 3.6" | curl --data-binary @- http://10.32.1.148:9091/metrics/job/test_job
You have mail in /var/spool/mail/root# 注:--data-binary 表示发送二进制数据,注意:它是使用POST方式发送的!

刷新http://10.32.1.148:9091/

在这里插入图片描述

在这里插入图片描述

【3】推送复杂数据

[root@node01 package]# cat <<EOF | curl --data-binary @- http://10.32.1.148: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
You have mail in /var/spool/mail/root

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【4】删除某个组下某个实例的所有数据

【5】删除某个组下的所有数据:

【6】把数据上报到pushgateway

在被监控服务所在的机器配置数据上报,想要把10.32.1.147这个机器的内存数据上报到pushgateway,下面步骤需要在10.32.1.147操作

[root@master 3]# cat push.sh
node_memory_usages=$(free -m | grep Mem | awk '{print $3/$2*100}')
job_name="memory"
instance_name="10.32.1.149"
cat <<EOF | curl --data-binary @- http://10.32.1.148:9091/metrics/job/$job_name/instance/$instance_name
#TYPE node_memory_usages  gauge
node_memory_usages $node_memory_usages
EOF
[root@master 3]# sh push.sh

打开pushgateway web ui界面,可看到如下:
在这里插入图片描述

打开prometheus ui界面,可看到如下node_memory_usages的metrics指标
在这里插入图片描述
设置计划任务,定时上报数据

chmod +x push.sh
crontab -e
*/1 * * * * /usr/bin/bash  /root/CKA/model3/3/push.sh

查看指标数据,是有变化的

在这里插入图片描述

在这里插入图片描述

注意:

从上面配置可以看到,我们上传到pushgateway中的数据有job也有instance,而prometheus配置pushgateway这个job_name中也有job和instance,这个job和instance是指pushgateway实例本身,添加 honor_labels: true 参数, 可以避免promethues的targets列表中的job_name是pushgateway的 job 、instance 和上报到pushgateway数据的job和instance冲突。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/268218.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3基础教程(1)——nodejs环境搭建

博主个人小程序已经上线&#xff1a;【中二少年工具箱】 小程序二维如下&#xff1a; 正文开始 专栏简介1. 环境菜单2.为什么下载node3. nodejs简介4. nodejs安装5. 编辑器选择 专栏简介 本系列文章由浅入深&#xff0c;从基础知识到实战开发&#xff0c;非常适合入门同学。…

MySQL 面试题

MySQL 基础 数据库的约束与范式&#xff1f; 七大约束&#xff1a; 检查约束&#xff1a;以数据类型以及数据的长度进行约束&#xff0c;在一个表中&#xff0c; 所插入的数据&#xff0c;必须和数据类型匹配&#xff0c;并且范围不能超过指定的长度。非空约束 not null&…

第十四天-网络爬虫基础

目录 1.什么是爬虫 2.网络协议 OSI七层参考模型 TCP/IP模型 1.应用层 2.传输层 3.网络层 3.HTTP协议 1.介绍 2.http版本&#xff1a; 3.请求格式 4.请求方法 5.HTTP响应 状态码&#xff1a; 6.http如何连接 4.Python requests模块 1.安装 2.使用get/post 3.响…

动态规划5,粉刷房子,买卖股票的最佳时期

粉刷房子 思路&#xff1a; 1.经验题目要求 dp[i][0] 表示&#xff1a;粉刷到 i 位置的时候&#xff0c;最后一个位置粉刷上红色&#xff0c;此时的最小花费。 dp[i][1] 表示&#xff1a;粉刷到 i 位置的时候&#xff0c;最后一个位置粉刷上蓝色&#xff0c;此时的最小花费。…

java学习(常用类)

一、包装类&#xff08;针对八种基本数据类型相应的引用类型--包装类. 1)包装类和基本数据类型的相互转换 装箱&#xff1a;基本类型->包装类型 拆箱&#xff1a;包装类型->基本类型 //以下是int类型和char类型演示。 public class temp1 {public static void main(St…

TOMCAT的安装与基本信息

一、TOMCAT简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首选。对于一个初学者来说&#xff0c;可以这样认为&#xff0c…

Rust调用同级目录中的rs文件和调用下级目录中的rs文件

一、Rust调用同级目录中的rs文件 Rust新建工程demo02&#xff0c;src文件夹下面新建test.rs文件&#xff0c;这样main.rs文件与它属于同级目录中。 关键点&#xff1a;导入test文件和test文件中的Ellipse模块 mod test;//导入test模块&#xff08;文件&#xff09; use test…

MySQL-MHA搭建、故障测试

一、架构说明 MHA&#xff08;Master High Availability&#xff09;是一个用于 MySQL 主从复制管理和自动故障转移的开源工具集。MHA 的主要目的是提供 MySQL 环境的高可用性和自动故障转移功能&#xff0c;确保在主库发生故障时能够快速切换到备库&#xff0c;降低业务中断时…

Android 性能优化--APK加固(1)混淆

文章目录 为什么要开启混淆如何开启代码混淆如何开启资源压缩代码混淆配置代码混淆后&#xff0c;Crash 问题定位结尾 本文首发地址&#xff1a;https://h89.cn/archives/211.html 最新更新地址&#xff1a;https://gitee.com/chenjim/chenjimblog 为什么要开启混淆 先上一个 …

架构设计:生产消费模型

1. 引言 在现代软件系统中&#xff0c;处理大量数据和消息是一项重要的任务。生产消费模型作为一种经典的并发模式&#xff0c;在解决数据生产和消费之间的关系上发挥着关键作用。该模型通过有效地管理生产者和消费者之间的通信和数据流动&#xff0c;实现了系统组件之间的解耦…

LASSO算法

LASSO (Least Absolute Shrinkage and Selection Operator) 是一种回归分析的方法&#xff0c;它能够同时进行变量选择和正则化&#xff0c;以增强预测准确性和模型的解释性。LASSO通过在损失函数中加入一个L1惩罚项来实现这一点。该惩罚项对系数的绝对值进行约束。 基本概念 …

python中的类与对象(3)

目录 一. 类的多继承 二. 类的封装 三. 类的多态 四. 类与对象综合练习&#xff1a;校园管理系统 一. 类的多继承 在&#xff08;2&#xff09;第四节中我们介绍了什么是类的继承&#xff0c;在子类的括号里面写入要继承的父类名。上一节我们只在括号内写了一个父类名&…

【详识JAVA语言】面向对象程序三大特性之三:多态

多态 多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 多态实现条件 在java中要实现多态&#xff0c;必须要满足如下几个条件&#xff0c;缺一不可&#xf…

基于阿里云OSS上传图片实战案例

一、案例描述 基于Springboot框架实现一个上传图片到阿里云服务端保存的小案例。 二、准备工作 基于Springboot免费搭载轻量级阿里云OSS数据存储库&#xff08;将本地文本、照片、视频、音频等上传云服务保存&#xff09;-CSDN博客 三、代码 新建这两个类&#xff1a;一个…

【数据结构初阶】九、五种比较排序的讲解和实现(直接插入 \ 希尔 \ 直接选择 \ 堆 \ 冒泡 -- C语言)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【数据结构初阶】八、非线性表里的二叉树&#xff08;二叉树的实现 -- C语言链式结构&#xff09;-CSDN博客 排序 排序的概念 所谓排序&#xff0c;就是使一串记录&#xff0c;按照…

网络编程(IP、端口、协议、UDP、TCP)【详解】

目录 1.什么是网络编程&#xff1f; 2.基本的通信架构 3.网络通信三要素 4.UDP通信-快速入门 5.UDP通信-多发多收 6.TCP通信-快速入门 7.TCP通信-多发多收 8.TCP通信-同时接收多个客户端 9.TCP通信-综合案例 1.什么是网络编程&#xff1f; 网络编程是可以让设…

Web开发学习-HTML

第一天 固定结构 如何注释&#xff1a;vs code中使用ctrl/可以达到注释这一行的效果&#xff0c;同时再次按下ctrl/&#xff0c;可以取消注释。 HTML标签的结构 例如&#xff1a;<strong>字体加粗</strong>这个就是双标签&#xff0c;<br>换行标签&#xff…

[RoarCTF 2019]Easy Calc

这题考查的是: 字符串解析特性目录读取文件内容读取 字符串解析特性详解&#xff1a;PHP字符串解析特性 &#xff08;$GET/$POST参数绕过&#xff09;&#xff08;含例题 buuctf easycalc&#xff09;_参数解析 绕过-CSDN博客 ascii码查询表&#xff1a;ASCII 表 | 菜鸟工具 …

flurl升级之后没有FlurlNewtonsoftJsonSerializer

新建NewtonsoftJsonSerializer.cs /// <summary> /// ISerializer implementation based on Newtonsoft.Json. /// Default serializer used in calls to GetJsonAsync, PostJsonAsync, etc. /// </summary> public class NewtonsoftJsonSerializer : IJsonSerial…

【贪心算法】Leetcode 455.分发饼干 376. 摆动序列 53. 最大子数组和

【贪心算法】Leetcode 455 分发饼干 376. 摆动序列【规律很多】53. 最大子数组和 455 分发饼干局部最优推全局最优&#xff1a;尽量用大饼干去满足大胃口的小朋友 376. 摆动序列【规律很多】思想&#xff1a;注意考虑一个坡度留首尾两个点、平坡、首尾 53. 最大子数组和【好思想…