Skip to content

第二十章-Alertmanager发送报警.md

本章所讲内容:

20.1 安装和配置 Alertmanager-发送报警到 qq 邮箱

20.2 安装和配置 Alertmanager-发送报警到微信

20.3 安装和配置 Alertmanager-发送报警到钉钉

20.4 Prometheus 监控外部 k8s 集群

20.1 配置 Alertmanager 发送报警到 qq 邮箱

20.1.1 controllmanager

​ 在 k8s 的 控制 节点创建 alertmanager-cm.yaml 文件,内容如下:

$ cat alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: alertmanager
  namespace: monitor-sa
data:
  alertmanager.yml: |-
    global:
      resolve_timeout: 1m
      smtp_smarthost: 'smtp.163.com:25'
      smtp_from: 'yangqinlinux@163.com'
      smtp_auth_username: 'yangqinlinux@163.com'
      smtp_auth_password: 'XUCJJZAQKLPZRWMT'
      smtp_require_tls: false
    route:    # 用于配置告警分发策略
      group_by: [alertname]    # 采用哪个标签来作为分组依据
      group_wait: 10s       # 组告警等待时间。也就是告警产生后等待 10s,如果有同组告警一起发出
      group_interval: 10s    # 两组告警的间隔时间
      repeat_interval: 10m      # 重复告警的间隔时间,减少相同邮件的发送频率
      receiver: default-receiver    # 设置默认接收人
    receivers:
    - name: 'default-receiver'
      email_configs:
      - to: '1208779136@qq.com'
        send_resolved: true

通过 kubectl apply 更新文件

$ kubectl apply -f alertmanager-cm.yaml

​ 上述内容是一个 Kubernetes 的 ConfigMap 配置文件,用于配置 Alertmanager 的参数和告警分 发策略。让我们逐个解释每个部分的含义和作用。

  1. kind: ConfigMap

• 这个字段指定了配置文件的类型为 ConfigMap,它用于在 Kubernetes 中存储非机密 的配置数据。

  1. apiVersion: v1

• 这个字段指定了使用的 Kubernetes API 的版本。

  1. metadata:

• 这个部分包含了 ConfigMap 对象的元数据,如名称(name)和命名空间 (namespace)。

  1. name: alertmanager

• 这个字段指定了 ConfigMap 的名称为"alertmanager"。它是用于识别和引用该配置 的唯一标识符。

  1. namespace: monitor-sa

• 这个字段指定了 ConfigMap 所属的命名空间为"monitor-sa"。命名空间用于在 Kubernetes 中对资源进行逻辑隔离和组织。

  1. data:

• 这个部分包含了 ConfigMap 的数据字段,其中配置了 alertmanager 的参数和告警 分发策略。

  1. alertmanager.yml: |- • 这个字段指定了一个名为"alertmanager.yml"的配置文件。它是 Alertmanager 的 配置文件,使用 YAML 格式进行定义。

  2. global:

• 这个部分包含了全局配置参数,用于定义 Alertmanager 的全局行为和属性。在这个 例子中,配置了一些 SMTP(简单邮件传输协议)相关的参数,如 SMTP 主机、发件 人邮箱、SMTP 认证用户名和密码,以及是否要求 TLS 加密。

  1. route:

• 这个部分用于配置告警分发策略。它定义了如何将告警分组并发送到接收者。在这个例 子中,配置了按照告警名称(alertname)进行分组,设置了分组等待时间、组间隔时 间和重复告警间隔时间,并指定了默认的接收者。

  1. receivers:

    • 这个部分定义了接收者(receiver)的配置。在这个例子中,定义了一个名为"defaultreceiver"的接收者,配置了发送邮件的相关参数,如收件人邮箱和是否在告警解决后发送邮 件。

​ 通过以上配置,Alertmanager 将根据定义的告警分发策略和接收者配置,将相应的告警通知发送 到指定的邮箱。

​ 对于实际的 SMTP 参数配置,需要根据你所使用的 SMTP 服务器和账户进行相应的填写。以下是按 照具体步骤进行配置的指导:

  1. smtp_smarthost: 'smtp.163.com:25'

• 这里配置了 SMTP 的主机和端口。在这个示例中,使用了网易 163 邮箱的 SMTP 服 务器,其主机为 smtp.163.com,端口为 25。您可以根据你使用的 SMTP 服务器提 供商和具体配置进行相应修改。

  1. smtp_from: 'yangqinlinx@163.com'

• 这里配置了发件人的邮箱地址。您需要将 yangqinlinux@163.com 替换为您自己的有 效发件人邮箱地址。

  1. smtp_auth_username: 'yangqinlinux@163.com '

• 这里配置了 SMTP 认证的用户名。您需要将 yangqinlinux@163.com替换为您 SMTP 服务器认 证所需的有效用户名。

  1. smtp_auth_password: 'XUCJJZAQKLPZRWMT'

• 这里配置了 SMTP 认证的密码。您需要将 XUCJJZAQKLPZRWMT 替换为 您 SMTP 服务器认证所需的有效密码。请注意,对于敏感信息如密码,建议使用 Kubernetes 的机密(Secrets)来存储和引用,以确保安全性。

20.1.2 configmap

​ 在 k8s 的 控制 节点生成一个 prometheus-alertmanager-cfg.yaml 文件,内容如下:

更新资源清单文件

$ kubectl delete -f prometheus-cfg.yaml 

$ cat prometheus-alertmanager-cfg.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus-config
  namespace: monitor-sa
data:
  prometheus.yml: |
    rule_files:
    - /etc/prometheus/rules.yml
    alerting:
      alertmanagers:
      - static_configs:
        - targets: ["localhost:9093"]
    global:
      scrape_interval: 15s
      scrape_timeout: 10s
      evaluation_interval: 1m
    scrape_configs:
    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: ':9100'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
    - job_name: 'kubernetes-node-cadvisor'
      kubernetes_sd_configs:
      - role:  node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __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//proxy/metrics/cadvisor
    - job_name: 'kubernetes-apiserver'
      kubernetes_sd_configs:
      - role: endpoints
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        action: keep
        regex: default;kubernetes;https
    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: :
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name 
    - job_name: kubernetes-pods
      kubernetes_sd_configs:
      - role: pod
      relabel_configs:
      - action: keep
        regex: true
        source_labels:
        - __meta_kubernetes_pod_annotation_prometheus_io_scrape
      - action: replace
        regex: (.+)
        source_labels:
        - __meta_kubernetes_pod_annotation_prometheus_io_path
        target_label: __metrics_path__
      - action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: :
        source_labels:
        - __address__
        - __meta_kubernetes_pod_annotation_prometheus_io_port
        target_label: __address__
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - action: replace
        source_labels:
        - __meta_kubernetes_namespace
        target_label: kubernetes_namespace
      - action: replace
        source_labels:
        - __meta_kubernetes_pod_name
        target_label: kubernetes_pod_name
    - job_name: 'kubernetes-etcd'
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crt
        cert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crt
        key_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.key
      scrape_interval: 5s
      static_configs:
      - targets: ['192.168.2.201:2380','192.168.2.102:2380','192.168.2.103:2380']
  rules.yml: |
    groups:
    - name: example
      rules:
      - alert: apiserver的cpu使用率大于80%
        expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 80
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.job}}组件的cpu使用率超过80%"
      - alert:  apiserver的cpu使用率大于90%
        expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 90
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.job}}组件的cpu使用率超过90%"
      - alert: etcd的cpu使用率大于80%
        expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 80
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.job}}组件的cpu使用率超过80%"
      - alert:  etcd的cpu使用率大于90%
        expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 90
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.job}}组件的cpu使用率超过90%"
      - alert: kube-state-metrics的cpu使用率大于80%
        expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 80
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.k8s_app}}组件的cpu使用率超过80%"
          value: "{{  }}%"
          threshold: "80%"      
      - alert: kube-state-metrics的cpu使用率大于90%
        expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 0
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.k8s_app}}组件的cpu使用率超过90%"
          value: "{{  }}%"
          threshold: "90%"      
      - alert: coredns的cpu使用率大于80%
        expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 80
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.k8s_app}}组件的cpu使用率超过80%"
          value: "{{  }}%"
          threshold: "80%"      
      - alert: coredns的cpu使用率大于90%
        expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 90
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.k8s_app}}组件的cpu使用率超过90%"
          value: "{{  }}%"
          threshold: "90%"      
      - alert: kubernetes-apiserver打开句柄数>600
        expr: process_open_fds{job=~"kubernetes-apiserver"}  > 600
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.job}}打开句柄数>600"
          value: "{{  }}"
      - alert: kubernetes-apiserver打开句柄数>1000
        expr: process_open_fds{job=~"kubernetes-apiserver"}  > 1000
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.job}}打开句柄数>1000"
          value: "{{  }}"
      - alert: kubernetes-etcd打开句柄数>600
        expr: process_open_fds{job=~"kubernetes-etcd"}  > 600
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "{{.instance}}的{{.job}}打开句柄数>600"
          value: "{{  }}"
      - alert: kubernetes-etcd打开句柄数>1000
        expr: process_open_fds{job=~"kubernetes-etcd"}  > 1000
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "{{.instance}}的{{.job}}打开句柄数>1000"
          value: "{{  }}"
      - alert: coredns
        expr: process_open_fds{k8s_app=~"kube-dns"}  > 600
        for: 2s
        labels:
          severity: warnning 
        annotations:
          description: "插件{{.k8s_app}}({{.instance}}): 打开句柄数超过600"
          value: "{{  }}"
      - alert: coredns
        expr: process_open_fds{k8s_app=~"kube-dns"}  > 1000
        for: 2s
        labels:
          severity: critical
        annotations:
          description: "插件{{.k8s_app}}({{.instance}}): 打开句柄数超过1000"
          value: "{{  }}"
      - alert: kubernetes-apiserver
        expr: process_virtual_memory_bytes{job=~"kubernetes-apiserver"}  > 2000000000
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "组件{{.job}}({{.instance}}): 使用虚拟内存超过2G"
          value: "{{  }}"
      - alert: kubernetes-etcd
        expr: process_virtual_memory_bytes{job=~"kubernetes-etcd"}  > 2000000000
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "组件{{.job}}({{.instance}}): 使用虚拟内存超过2G"
          value: "{{  }}"
      - alert: kube-dns
        expr: process_virtual_memory_bytes{k8s_app=~"kube-dns"}  > 2000000000
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "插件{{.k8s_app}}({{.instance}}): 使用虚拟内存超过2G"
          value: "{{  }}"
      - alert: HttpRequestsAvg
        expr: sum(rate(rest_client_requests_total{job=~"kubernetes-kube-proxy|kubernetes-kubelet|kubernetes-schedule|kubernetes-control-manager|kubernetes-apiservers"}[1m]))  > 1000
        for: 2s
        labels:
          team: admin
        annotations:
          description: "组件{{.job}}({{.instance}}): TPS超过1000"
          value: "{{  }}"
          threshold: "1000"   
      - alert: Pod_restarts
        expr: kube_pod_container_status_restarts_total{namespace=~"kube-system|default|monitor-sa"} > 0
        for: 2s
        labels:
          severity: warnning
        annotations:
          description: "在{{.namespace}}名称空间下发现{{.pod}}这个pod下的容器{{.container}}被重启,这个监控指标是由{{.instance}}采集的"
          value: "{{  }}"
          threshold: "0"
      - alert: Pod_waiting
        expr: kube_pod_container_status_waiting_reason{namespace=~"kube-system|default"} == 1
        for: 2s
        labels:
          team: admin
        annotations:
          description: "空间{{.namespace}}({{.instance}}): 发现{{.pod}}下的{{.container}}启动异常等待中"
          value: "{{  }}"
          threshold: "1"   
      - alert: Pod_terminated
        expr: kube_pod_container_status_terminated_reason{namespace=~"kube-system|default|monitor-sa"} == 1
        for: 2s
        labels:
          team: admin
        annotations:
          description: "空间{{.namespace}}({{.instance}}): 发现{{.pod}}下的{{.container}}被删除"
          value: "{{  }}"
          threshold: "1"
      - alert: Etcd_leader
        expr: etcd_server_has_leader{job="kubernetes-etcd"} == 0
        for: 2s
        labels:
          team: admin
        annotations:
          description: "组件{{.job}}({{.instance}}): 当前没有leader"
          value: "{{  }}"
          threshold: "0"
      - alert: Etcd_leader_changes
        expr: rate(etcd_server_leader_changes_seen_total{job="kubernetes-etcd"}[1m]) > 0
        for: 2s
        labels:
          team: admin
        annotations:
          description: "组件{{.job}}({{.instance}}): 当前leader已发生改变"
          value: "{{  }}"
          threshold: "0"
      - alert: Etcd_failed
        expr: rate(etcd_server_proposals_failed_total{job="kubernetes-etcd"}[1m]) > 0
        for: 2s
        labels:
          team: admin
        annotations:
          description: "组件{{.job}}({{.instance}}): 服务失败"
          value: "{{  }}"
          threshold: "0"
      - alert: Etcd_db_total_size
        expr: etcd_debugging_mvcc_db_total_size_in_bytes{job="kubernetes-etcd"} > 10000000000
        for: 2s
        labels:
          team: admin
        annotations:
          description: "组件{{.job}}({{.instance}}):db空间超过10G"
          value: "{{  }}"
          threshold: "10G"
      - alert: Endpoint_ready
        expr: kube_endpoint_address_not_ready{namespace=~"kube-system|default"} == 1
        for: 2s
        labels:
          team: admin
        annotations:
          description: "空间{{.namespace}}({{.instance}}): 发现{{.endpoint}}不可用"
          value: "{{  }}"
          threshold: "1"
    - name: 物理节点状态-监控告警
      rules:
      - alert: 物理节点cpu使用率
        expr: 100-avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by(instance)*100 > 90
        for: 2s
        labels:
          severity: ccritical
        annotations:
          summary: "{{ .instance }}cpu使用率过高"
          description: "{{ .instance }}的cpu使用率超过90%,当前使用率[{{  }}],需要排查处理" 
      - alert: 物理节点内存使用率
        expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{ .instance }}内存使用率过高"
          description: "{{ .instance }}的内存使用率超过90%,当前使用率[{{  }}],需要排查处理"
      - alert: InstanceDown
        expr: up == 0
        for: 2s
        labels:
          severity: critical
        annotations:   
          summary: "{{ .instance }}: 服务器宕机"
          description: "{{ .instance }}: 服务器延时超过2分钟"
      - alert: 物理节点磁盘的IO性能
        expr: 100-(avg(irate(node_disk_io_time_seconds_total[1m])) by(instance)* 100) < 60
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{.mountpoint}} 流入磁盘IO使用率过高!"
          description: "{{.mountpoint }} 流入磁盘IO大于60%(目前使用:{{}})"
      - alert: 入网流量带宽
        expr: ((sum(rate (node_network_receive_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{.mountpoint}} 流入网络带宽过高!"
          description: "{{.mountpoint }}流入网络带宽持续5分钟高于100M. RX带宽使用率{{}}"
      - alert: 出网流量带宽
        expr: ((sum(rate (node_network_transmit_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{.mountpoint}} 流出网络带宽过高!"
          description: "{{.mountpoint }}流出网络带宽持续5分钟高于100M. RX带宽使用率{{}}"
      - alert: TCP会话
        expr: node_netstat_Tcp_CurrEstab > 1000
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{.mountpoint}} TCP_ESTABLISHED过高!"
          description: "{{.mountpoint }} TCP_ESTABLISHED大于1000%(目前使用:{{}}%)"
      - alert: 磁盘容量
        expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes {fstype=~"ext4|xfs"}*100) > 80
        for: 2s
        labels:
          severity: critical
        annotations:
          summary: "{{.mountpoint}} 磁盘分区使用率过高!"
          description: "{{.mountpoint }} 磁盘分区使用大于80%(目前使用:{{}}%)"


$ kubectl apply -f prometheus-alertmanager-cfg.yaml

安装 prometheus 和 alertmanager

alertmanager.tar.gz 镜像包上传的 k8s 的各个节点,手动解压:

$ docker load -i alertmanager.tar.gz 

$ docker load -i prometheus_2.2.1.tar.gz 

20.1.3 deployment

​ 在 k8s 的 控制 节点生成一个 prometheus-alertmanager-deploy.yaml 文件,内容如下:

$ cat 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:
      nodeName: k8s-node01
      serviceAccountName: monitor
      containers:
      - name: prometheus
        image: 192.168.2.206/library/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: 192.168.2.206/library/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
          hostPath:
           path: /data
           type: Directory
        - name: k8s-certs
          secret:
           secretName: etcd-certs
        - name: alertmanager-config
          configMap:
            name: alertmanager
        - name: alertmanager-storage
          hostPath:
           path: /data/alertmanager
           type: DirectoryOrCreate
        - name: localtime
          hostPath:
           path: /usr/share/zoneinfo/Asia/Shanghai

yaml 文件解释说明:

​ 这段 YAML 文件描述了一个名为"prometheus-server"的 Deployment 资源,它用于在 Kubernetes 集群中部署 Prometheus 监控系统的服务器组件。

首先,文件中的 metadata 部分定义了资源的元数据,包括名称、所属的命名空间和一些标签用于标识 资源。

在 spec 部分中,定义了 Deployment 的规范。replicas 字段指定了需要创建的 Pod 副本数量,这里设 置为 1。selector 字段指定了用于选择 Pod 的标签。在这里,选择器要求 Pod 的标签中必须包含 app: prometheus 和 component: server。

template 部分定义了要创建的 Pod 的模板。在这个模板中,定义了 Pod 的元数据,包括一些标签用于 标识 Pod,以及一些注解用于提供额外的配置信息。例如,prometheus.io/scrape 注解被设置为 false,表示不对该 Pod 进行数据采集。

在 spec 部分的 containers 字段中,定义了两个容器:prometheus 和 alertmanager。

• prometheus 容器使用了 prom/prometheus:v2.2.1 镜像,通过指定的命令和参数来运行Prometheus 服务器。容器监听 9090 端口,并挂载了一些卷,包括用于存放配置文件的/etc/prometheus 目录和用于存储数据的/prometheus/目录。

• alertmanager 容器使用了 prom/alertmanager:v0.14.0 镜像,通过指定的参数来运行 Alertmanager。容器监听 9093 端口,并挂载了一些卷和主机路径,用于配置和存储数据。

最后,定义了一些卷,包括用于 Prometheus 配置的 ConfigMap 卷、用于 Prometheus 数据存储的 主机路径卷、用于保存 Kubernetes 证书的密钥卷、用于 Alertmanager 配置的 ConfigMap 卷、用于 Alertmanager 数据存储的主机路径卷,以及用于时区设置的主机路径卷。

​ 通过这个 Deployment 资源的定义,Kubernetes 将会创建一个 Pod,其中包含一个运行 Prometheus 服务器的容器和一个运行 Alertmanager 的容器。

注意:

配置文件指定了 nodeName: k8s-node01,这个位置要写你自己环境的 node 节点名字

20.1.4 secret

生成一个 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

通过 kubectl apply 更新 yaml 文件

$ kubectl delete -f prometheus-deploy.yaml

$ kubectl apply -f prometheus-alertmanager-deploy.yaml

查看 prometheus 是否部署成功

$ kubectl get pods -n monitor-sa | grep prometheus 
prometheus-server-7bc8d8f478-7r6vn   2/2     Running   0               4m18s

显示如上,可看到 pod 状态是 running,说明 prometheus 部署成功

在 k8s 的 控制 节点生成一个 alertmanager-svc.yaml 文件,内容如下:

$ cat 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

通过 kubectl apply 更新 yaml 文件

$ kubectl apply -f alertmanager-svc.yaml 

查看 service 在物理机上映射的端口

$ kubectl get svc -n monitor-sa
NAME           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
alertmanager   NodePort   10.100.180.210   <none>        9093:30066/TCP   8s
prometheus     NodePort   10.99.7.98       <none>        9090:30200/TCP   23h

​ 注意:上面可以看到 prometheus 的 service 暴漏的端口是 30200,alertmanager 的 service 暴露的端口是 30066

访问 prometheus 的 web 界面

点击 status->targets,可看到如下

clip_image011

点击 Alerts,可看到如下

image-20231101215120835

img

把 kubernetes-etcd 展开,可看到如下:

image-20231101215107889

​ FIRING 表示 prometheus 已经将告警发给 alertmanager,在 Alertmanager 中可以看到有一个alert。

​ 登录到 alertmanager web 界面,浏览器输入 192.168.2.201:30066,显示如下

clip_image017

这样我在我的 qq 邮箱, 1639373787@qq.com 就可以收到报警了,如下

image-20231101215510035

修改 prometheus 任何一个配置文件之后,可通过 kubectl apply 使配置生效,执行顺序如下:

$ kubectl delete -f alertmanager-cm.yaml

$ kubectl apply -f alertmanager-cm.yaml 

$ kubectl delete -f prometheus-alertmanager-cfg.yaml 

$ kubectl apply -f prometheus-alertmanager-cfg.yaml 

$ kubectl delete-f prometheus-alertmanager-deploy.yaml 

$ kubectl apply –f prometheus-alertmanager-deploy.yaml

改了 configmap 之后 热加载:

$ kubectl get pods -n monitor-sa -owide

NAME READY STATUS RESTARTS AGE IP NODE

prometheus-server-67777bdd4-4t7nm 2/2 Running 0 14m 10.244.209.144

$ curl -X POST http://10.244.209.144:9090/-/reload

img

20.2 配置 Alertmanager 发送报警到微信

1、注册企业微信

登陆网址:

https://work.weixin.qq.com/

找到应用管理,创建应用应用名字 wechat

创建成功之后显示如下:

img

AgentId:*003 Secret:**Oj6dD4Jg9qaMu1TTaDzVTCrXHcjlFs

AgentId 和 Secret 用自己企业微信的

2、修改 alertmanager-cm.yaml

$ cat alertmanager-cm.yaml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: alertmanager
  namespace: monitor-sa
data:
  alertmanager.yml: |-
    global:
      resolve_timeout: 1m
      smtp_smarthost: 'smtp.163.com:25'
      smtp_from: '1814553****@163.com'
      smtp_auth_username: '1814553****'
      smtp_auth_password: 'LAYXLXRZGFUBWOMZ'
      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: "wwa82df90a693*****"
        to_user: '@all'
        agent_id: 1000005
        api_secret: "xPte8Jw6g1PC_Hkla8Nkshr-3m44gBqPvDWZ*******"

参数说明:

secret: 企业微信("企业应用"-->"自定应用"[Prometheus]--> "Secret")

wechat 是本人自创建应用名称

corp_id: 企业信息("我的企业"--->"CorpID"[在底部])

agent_id: 企业微信("企业应用"-->"自定应用"[Prometheus]--> "AgentId")

wechat 是自创建应用名称 #在这创建的应用名字是 wechat,那么在配置 route 时,receiver 也应该是Prometheus

to_user: '@all' :发送报警到所有人

​ 正常发送报警到企业微信,需要添加 ip 白名单,步骤如下:

​ 问题:Prometheus 以及 alertmanager 可以正常列出告警,但企业微信无法收到 alertmanger发送的告警

1、查看容器 alertmanager 的日志

# kubectl get pods -n monitor-sa -o wide | grep prometheus

prometheus-server-55cd9cb6d7-jcbqk 2/2 Running 0 46m 10.244.166.180 node1

# kubectl logs prometheus-server-55cd9cb6d7-jcbqk -c alertmanager -n monitor-sa

2、日志中有 60020(不安全的访问 IP)的错误码以及 IP 和相应的帮助链接信息
level=debug ts=2022-07-29T11:06:26.870766805Z caller=impl.go:929 msg="response: {\"errcode\":60020,\"errmsg\":\"not allow to access from your ip, hint: [1659092786248532786593324], from ip: 60.24.250.19, more info at https://open.work.weixin.qq.com/devtool/query?e=60020\"}" incident="{}:{alertname=\"controller-manager 的 cpu 使用率大于90%\"}"
3、将日志中的 IP 信息加入企业微信自建应用的 IP 白名单中

img

img

​ 这样企业微信就可以收到告警了

20.3 配置 Alertmanager 发送报警到微信钉钉

1、创建钉钉机器人

打开电脑版钉钉,创建一个群,创建自定义机器人,按如下步骤创建

https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq

https://developers.dingtalk.com/document/app/custom-robot-access

我创建的机器人如下:

群设置-->智能群助手-->添加机器人-->自定义-->添加

机器人名称:test

接收群组:钉钉报警测试

安全设置:

自定义关键词:cluster1

上面配置好之后点击完成即可,这样就会创建一个 test 的报警机器人,创建机器人成功之后怎么查看 webhook,按如下:

点击智能群助手,可以看到刚才创建的 test 这个机器人,点击 test,就会进入到 test 机器人的设置

界面

出现如下内容: 机器人名称:test

接受群组:钉钉报警测试消息推送:开启

webhook: https://oapi.dingtalk.com/robot/send?access_token=**

注意:access_token=用自己的钉钉的 token

安全设置:

自定义关键词:cluster1

2、安装钉钉的 webhook 插件,在 k8s 的控制节点操作

$ tar zxvf prometheus-webhook-dingtalk-0.3.0.linux-amd64.tar.gz

$ cd prometheus-webhook-dingtalk-0.3.0.linux-amd64

启动钉钉报警插件

$ nohup ./prometheus-webhook-dingtalk --web.listen-address="0.0.0.0:8060" -- ding.profile="cluster1=https://oapi.dingtalk.com/robot/send?access_token=******" &

对原来的 alertmanager-cm.yaml 文件做备份

$ cp alertmanager-cm.yaml alertmanager-cm.yaml.bak

重新生成一个新的 alertmanager-cm.yaml 文件

$ cat >alertmanager-cm.yaml <<EOF 
kind: ConfigMap
apiVersion: v1
metadata:
  name: alertmanager
  namespace: monitor-sa
data:
  alertmanager.yml: |-
    global:
      resolve_timeout: 1m
      smtp_smarthost: 'smtp.163.com:25'
      smtp_from: '1814553****@163.com'
      smtp_auth_username: '1814553****'
      smtp_auth_password: 'LAYXLXRZGFUBWOMZ'
      smtp_require_tls: false
    route:
      group_by: [alertname]
      group_wait: 10s
      group_interval: 10s
      repeat_interval: 10m
      receiver: cluster1
    receivers:
    - name: 'cluster1'
      webhook_configs:
    - url: 'http://192.168.40.63:8060/dingtalk/cluster1/send'
    send_resolved: true
EOF

修改 prometheus 任何一个配置文件之后,可通过 kubectl apply 使配置生效,执行顺序如下:

$ kubectl delete -f alertmanager-cm.yaml 

$ kubectl apply -f alertmanager-cm.yaml

$ kubectl delete -f prometheus-alertmanager-cfg.yaml 

$ kubectl apply -f prometheus-alertmanager-cfg.yaml 

$ kubectl delete -f prometheus-alertmanager-deploy.yaml 

$ kubectl apply -f prometheus-alertmanager-deploy.yaml

20.4 prometheus 监控外部 k8s 集群

​ 在 Kubernetes(K8S)集群内部署 Prometheus 是一种方便的方式,可以使用官方提供的 YAML 文件进行部署。但是在将 Prometheus 部署在集群外运行,并采集多个 K8S 集群的情况下,需要进行一 些额外的配置。

以下是在集群外部署 Prometheus 并采集多个 K8S 集群的步骤:

1、构造 apiserver proxy URL

在 K8S 集群中,节点(nodes)、Pod 和服务(services)都有自己的私有 IP,无法直接从集群外部访 问。但是 K8S 提供了几种访问方式:

  • 通过公共 IP 访问服务(service)
  • 通过代理(proxy)访问节点(node)、Pod 和服务
  • 通过集群内部的节点或 Pod 间接访问

可以使用以下规则构造 apiserver proxy URL:

  • 访问节点:https://${apiserver_address}/api/v1/nodes/${node_name}/proxy/metrics

  • 访问服务: https://${apiserver_address}/api/v1/namespaces/${service_namespace}/services/http:${service_name}[:${port_name}]/proxy/metrics

  • 访问 Pod: https://${apiserver_address}/api/v1/namespaces/${pod_namespace}/pods/http:${p od_name}[:${port_name}]/proxy/metrics

其中${apiserver_address}是 apiserver 的地址,可以通过 kubectl cluster-info 命令查看。默认情况下,apiserver 的地址是集群内部的私有 IP。

2、apiserver 授权

为了访问 K8S 的 apiserver,需要进行授权。在集群内部部署的 Prometheus 可以使用默认配置进行访 问,但在集群外部访问需要使用 token 和客户端证书进行认证。因此,需要进行 RBAC(Role-Based Access Control)授权。

以下是授权的步骤:

  • 在 K8S 集群的控制节点上创建一个 ServiceAccount(SA)账号:
$ kubectl create serviceaccount monitor -n monitor-sa
  • 将 SA 账号与 ClusterRole 绑定:

  • kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor-sa -- clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor

​ 虽然创建了 ServiceAccount(SA)账号,但是访问 apiserver 时并不直接使用 SA 账号,而是使 用 token。因此,需要获取 ServiceAccount(SA)账号 monitor 对应的 token,并解密该 token。

通过以下命令获取 token:

$ kubectl get sa monitor -n monitor-sa -o yaml

从输出中找到 token 字段的值,该值经过 base64 加密。需要对该 token 进行解密才能使用:

$ echo "SGLDDLFKGJLGIEMTV…" | base64 -d

获得解密后的 token 后,可以作为 bearer_token 访问 apiserver。

​ 以集群外部的方式采集 K8S 信息:在集群外部署 Prometheus 并采集多个 K8S 集群的情况下,需 要以集群外部的方式进行配置和采集。以下是相关步骤:

  • 在 Prometheus 的 Job 配置中,以 cadvisor 采集为例,可以使用以下配置:
- job_name: cadvisor
  scrape_interval: 30s
  scrape_timeout: 10s
  scheme: https
  tls_config:
    insecure_skip_verify: true
  bearer_token_file: /k8s_token
 # 使用 apiserver 授权部分解密的 token 值,以文件 k8s_token 形式存储


# k8s 自动发现配置
kubernetes_sd_configs:
- role: node
  api_server: https://xx:6443
  bearer_token_file: /k8s_token
  tls_config:
    insecure_skip_verify: true
# 跳过验证,否则抓取会报

在上述配置中,需要注意以下几点:

• tls_config 和 bearer_token_file 必须在 Job 配置中和 kubernetes_sd_configs 都存在,否 则会导致认证失败。

• bearer_token_file 指定了解密后的 token 文件路径,可以使用前面获取到的解密后的 token 值,将其保存到文件 k8s_token 中。

• kubernetes_sd_configs 指定了 Kubernetes 的自动发现配置,role 设置为 node 表示采集 节点信息,api_server 指定 Kubernetes 的 apiserver 地址。

​ 以上配置将使 Prometheus 以集群外部的方式通过 apiserver proxy URL 访问 K8S 集群的节点,并采 集相关的 metrics 数据