第二十章-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 更新文件
上述内容是一个 Kubernetes 的 ConfigMap 配置文件,用于配置 Alertmanager 的参数和告警分 发策略。让我们逐个解释每个部分的含义和作用。
- kind: ConfigMap
• 这个字段指定了配置文件的类型为 ConfigMap,它用于在 Kubernetes 中存储非机密 的配置数据。
- apiVersion: v1
• 这个字段指定了使用的 Kubernetes API 的版本。
- metadata:
• 这个部分包含了 ConfigMap 对象的元数据,如名称(name)和命名空间 (namespace)。
- name: alertmanager
• 这个字段指定了 ConfigMap 的名称为"alertmanager"。它是用于识别和引用该配置 的唯一标识符。
- namespace: monitor-sa
• 这个字段指定了 ConfigMap 所属的命名空间为"monitor-sa"。命名空间用于在 Kubernetes 中对资源进行逻辑隔离和组织。
- data:
• 这个部分包含了 ConfigMap 的数据字段,其中配置了 alertmanager 的参数和告警 分发策略。
-
alertmanager.yml: |- • 这个字段指定了一个名为"alertmanager.yml"的配置文件。它是 Alertmanager 的 配置文件,使用 YAML 格式进行定义。
-
global:
• 这个部分包含了全局配置参数,用于定义 Alertmanager 的全局行为和属性。在这个 例子中,配置了一些 SMTP(简单邮件传输协议)相关的参数,如 SMTP 主机、发件 人邮箱、SMTP 认证用户名和密码,以及是否要求 TLS 加密。
- route:
• 这个部分用于配置告警分发策略。它定义了如何将告警分组并发送到接收者。在这个例 子中,配置了按照告警名称(alertname)进行分组,设置了分组等待时间、组间隔时 间和重复告警间隔时间,并指定了默认的接收者。
-
receivers:
• 这个部分定义了接收者(receiver)的配置。在这个例子中,定义了一个名为"defaultreceiver"的接收者,配置了发送邮件的相关参数,如收件人邮箱和是否在告警解决后发送邮 件。
通过以上配置,Alertmanager 将根据定义的告警分发策略和接收者配置,将相应的告警通知发送 到指定的邮箱。
对于实际的 SMTP 参数配置,需要根据你所使用的 SMTP 服务器和账户进行相应的填写。以下是按 照具体步骤进行配置的指导:
- smtp_smarthost: 'smtp.163.com:25'
• 这里配置了 SMTP 的主机和端口。在这个示例中,使用了网易 163 邮箱的 SMTP 服 务器,其主机为 smtp.163.com,端口为 25。您可以根据你使用的 SMTP 服务器提 供商和具体配置进行相应修改。
- smtp_from: 'yangqinlinx@163.com'
• 这里配置了发件人的邮箱地址。您需要将 yangqinlinux@163.com 替换为您自己的有 效发件人邮箱地址。
- smtp_auth_username: 'yangqinlinux@163.com '
• 这里配置了 SMTP 认证的用户名。您需要将 yangqinlinux@163.com替换为您 SMTP 服务器认 证所需的有效用户名。
- 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 的各个节点,手动解压:
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 文件
查看 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 文件
查看 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,可看到如下
点击 Alerts,可看到如下
把 kubernetes-etcd 展开,可看到如下:
FIRING 表示 prometheus 已经将告警发给 alertmanager,在 Alertmanager 中可以看到有一个alert。
登录到 alertmanager web 界面,浏览器输入 192.168.2.201:30066,显示如下
这样我在我的 qq 邮箱, 1639373787@qq.com 就可以收到报警了,如下
修改 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 之后 热加载:
NAME READY STATUS RESTARTS AGE IP NODE
prometheus-server-67777bdd4-4t7nm 2/2 Running 0 14m 10.244.209.144
20.2 配置 Alertmanager 发送报警到微信
1、注册企业微信
登陆网址:
https://work.weixin.qq.com/
找到应用管理,创建应用应用名字 wechat
创建成功之后显示如下:
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 白名单中
这样企业微信就可以收到告警了
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 文件做备份
重新生成一个新的 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)账号:
-
将 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:
从输出中找到 token 字段的值,该值经过 base64 加密。需要对该 token 进行解密才能使用:
获得解密后的 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 数据









