云原生k8s11 监控与告警实战(mysql,haproxy,nginx,Ingress-Controller,kafka,etcd), blackbox_exporter, Alertmanager各种告警规则参考及告警模板告警通知, 告警抑制与静默, 监控K8S核心组件:master节点api-server,controller-manager,kube-scheduler指标

监控案例:Prometheus监控MySQL

二进制部署mysql并基于mysql_exporter实现指标采集

#安装mysql:
root@prometheus-server2:~# apt install mariadb-server
root@prometheus-server2:~# vim /etc/mysql/mariadb.conf.d/50-server.cnf
     bind-address     = 0.0.0.0
     
root@prometheus-server2:~# systemctl restart mysqld.service

#授权监控账户权限:    (从本机访问,收集指标信息)
 root@prometheus-server2:~# mysql
 MariaDB [(none)]> CREATE USER 'mysql_exporter'@'localhost' IDENTIFIED BY 'imnot007*';
 MariaDB [(none)]> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_exporter'@'localhost';
 MariaDB [(none)]> flush privileges;

#验证权限:
 root@prometheus-server2:~# mysql -umysql_exporter -pimnot007* -hlocalhost


#准备mysqld_exporter环境:
#官方下载地址,mysqld_exporter-0.19.0.linux-amd64.tar.gz官方编译好的二进制,可以直接拿来用
https://github.com/prometheus/mysqld_exporter/releases

#确保可以执行  mysqld_exporter --help
root@prometheus-server2:/usr/local/src# tar xvf mysqld_exporter-0.19.0.linux-amd64.tar.gz
root@prometheus-server2:/usr/local/src# mv mysqld_exporter-0.19.0.linux-amd64/mysqld_exporter /usr/local/bin/

#配置mysqld_exporter 免密码登录mysql配置,让mysqld_exporter连接mysql:
root@prometheus-server2:/usr/local/src# vim /root/.my.cnf
[client]
user=mysql_exporter
password=imnot007*

#启动命令: (启动后会收集mysql指标,收集的指标事固定的;要改指标要修改源码,重新编译) 
#/usr/local/bin/mysqld_exporter --config.my-cnf=/root/.my.cnf
#访问9104端口可以看到收集的指标

#编写mysql_exporter service文件:
root@prometheus-server2:~# vim /etc/systemd/system/mysqld_exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/mysqld_exporter --config.my-cnf=/root/.my.cnf

[Install]
WantedBy=multi-user.target

root@prometheus-server2:~# systemctl daemon-reload && systemctl restart mysqld_exporter && systemctl enable mysqld_exporter


#prometheus采集数据:
root@prometheus-server1:/apps/prometheus# vim prometheus.yml 
- job_name: mysql-monitor-172.31.2.182
  static_configs: 
  - targets: ['172.31.2.182:9104']
    
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service


#导入grafana 模板验证
grafana导入模板:11323
grafana导入模板:13106

K8S部署监控MySQL并实现指标采集:

#这里准备一个干净的k8s环境
#创建存储类sc
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql/0.storageclass# ls
1-rbac.yaml  2-storageclass.yaml  3-nfs-provisioner.yaml

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql/0.storageclass# vim 3-nfs-provisioner.yaml
...
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 10.0.0.107
            - name: NFS_PATH
              value: /data/volumes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.0.0.107
            path: /data/volumes
            
#看下nfs环境有没有
root@k8s-ha1:~# vim /etc/exports
/data/k8sdata *(rw,no_root_squash)
/data/volumes *(rw,no_root_squash)
root@k8s-ha1:~# ll /data/volumes/

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql/0.storageclass# kubectl apply -f 1-rbac.yaml -f 2-storageclass.yaml -f 3-nfs-provisioner.yaml


#创建mysql,其中要在mysql-statefulset.yaml追加mysql-exporter
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# vim 5.mysql-statefulset.yaml
...
      containers:    #追加mysql-exporter,它就是连到mysql收集容器中mysql指标
        ...#一个pod3个容器,mysql,xtrabackup,mysql-exporter
      - name: mysql-exporter #只收集当前mysql容器,如果多副本,每个exporter收集自己的
        image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/mysqld-exporter:v0.15.1
        args:
          - "--mysqld.username=mysql_exporter" #使用哪个账号连到库上
          - "--mysqld.address=localhost:3306" #库的地址
          - "--web.listen-address=:9104"    #监听端口
          - "--config.my-cnf=/data/.my.cnf"    #认证配置文件
        volumeMounts:
        - name: mysql-exporter-configmap
          mountPath: /data/
      volumes:
      - name: conf
        emptyDir: {}
      - name: config-map
        configMap:
          name: mysql
      - name: mysql-exporter-configmap
        configMap:
          name: mysql-exporter-configmap
          items:
             - key: mysql-exporter-map
               path: .my.cnf
               
#上面指定的.my.cnf内容
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# vim 4.mysql-exporter-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-exporter-configmap
  namespace: magedu
  labels:
    app: mysql-exporter-configmap
data:
  mysql-exporter-map: |
    [client]
    user=mysql_exporter
    password=imnot007*

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# kubectl create ns magedu
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# kubectl apply -f 1.mysql-configmap.yaml -f 2.mysql-services.yaml -f 3.mysql-secret.yaml -f 4.mysql-exporter-configmap.yaml
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# kubectl apply -f 5.mysql-statefulset.yaml


#进入mysql授权监控账户权限: #注意,要在主库里操作
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/3.mysql# kubectl exec -it mysql-0 bash -n magedu -c mysql -- bash
root@mysql-0:/# mysql -uroot -p12345678
MariaDB [(none)]> CREATE USER 'mysql_exporter'@'localhost' IDENTIFIED BY 'imnot007*';
MariaDB [(none)]> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_exporter'@'localhost';
mysql> create database myserver;

#验证权限:
root@mysql-0:/# mysql -umysql_exporter -pimnot007* -hlocalhost
mysql> show databases;

#测试查看主、副mysql对应pod的监控指标
#curl 10.200.195.4:9104/metrics


#把cadvisor,node-exporter装好
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case1-daemonset-deploy-cadvisor.yaml -f case2-daemonset-deploy-node-exporter.yaml

#转Prometheus,要做下账号赋权
#创建监控账号
root@ubuntu101:~/1.prometheus-case-files# kubectl create serviceaccount monitor -n monitoring
#对 monitoring 账号授权
root@ubuntu101:~/1.prometheus-case-files# kubectl create clusterrolebinding monitor-clusterrolebinding -n monitoring --clusterrole=cluster-admin --serviceaccount=monitoring:monitor

root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-1-prometheus-cfg.yaml -f case3-2-prometheus-deployment.yaml -f case3-3-prometheus-svc.yaml

#登录Prometheus地址
http://10.0.0.101:39090/targets
#在target health中service-endpoints可以看到mysql(mysql的statefulset没配,svc中配置了自动发现,所以通过endpoints可以看到)


#部署grafana
root@ubuntu101:~/1.prometheus-case-files# vim case5-grafana.yaml
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case5-grafana.yaml 

root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case6-kube-state-metrics-deploy.yaml

#访问grafana    admin/admin
http://10.0.0.101:33000/login

#导入grafana 模板验证
grafana导入模板:11323
grafana导入模板:13106

监控案例:Prometheus监控HAProxy;

通过haproxy_exporter监控haproxy (haproxy_exporter通过haproxy状态页抓指标)

https://github.com/prometheus/haproxy_exporter

部署haproxy:

root@k8s-ha1:~# apt-cache  madison haproxy
root@k8s-ha1:~# apt install haproxy

#开启状态页 (如果是采集本机,可使用sock监控,sock文件地址在配置中)
root@k8s-ha1:~# vim /etc/haproxy/haproxy.cfg 
listen stats
  bind :8899
  stats enable
  #stats hide-version 
  stats uri  /haproxy-status    #状态页路径
  stats realm HAPorxy\ Stats\ Page    #状态页面
  stats auth haadmin:123456    #登录认证,自己设置(登录就是管理员,不支持详细权限控制)
  stats auth admin:123456
  
root@k8s-ha1:~# systemctl restart haproxy.service

#测试登录状态页      admin:123456(账号密码配的两个都可以)
172.31.7.109:8899/haproxy-status

监控Haproxy:

#部署haproxy_exporter:
#官网下载二进制文件
root@k8s-ha1:/usr/local/src# tar xvf haproxy_exporter-0.15.0.linux-amd64.tar.gz 
root@k8s-ha1:/usr/local/src# mv haproxy_exporter-0.15.0.linux-amd64/haproxy_exporter  /usr/local/bin/

#测试
root@k8s-ha1:/usr/local/src# haproxy_exporter --help
#监听地址9101,暴露地址 /metrics


#获取指标
1.启动方式一:#sock文件路径在haproxy.cfg配置中,用于本机获取指标
root@k8s-ha1:/usr/local/src# haproxy_exporter --haproxy.scrape-uri=unix:/run/haproxy/admin.sock

#访问收集指标测试下:
172.31.7.109:9191/metrics

2.启动方式二:#通过url,uri前面是账号密码,状态页地址;后表示抓取csv格式,&:终端后台运行
root@k8s-ha1:/usr/local/src# haproxy_exporter --haproxy.scrape-uri="http://haadmin:123456@127.0.0.1:8899/haproxy-status;csv" &

二进制Prometheus收集数据(不是k8s)

prometheus添加job:

root@prometheus-server1:/apps/prometheus# vim prometheus.yml
- job_name: 'haproxy-monitor-metrics'
  static_configs:
  - targets: ['172.31.7.109:9101']

root@prometheus-server1:/apps/prometheus# systemctl  restart prometheus.service


grafana导入模版12030
grafana导入模版367

监控案例:Prometheus监控Nginx;

1.在云主机编译安装nginx,然后通过prometheus实现监控

2.自定义nginx容器镜像、并基于kubernetes运行nginx,然后通过prometheus实现监控

nginx显示的状态页不是Prometheus支持的格式,所以中间要个exporter序列化成Prometheus格式,但nginx在0.17版本开始,内部的nginx-module-vts模块直接支持Prometheus的指标了(exporter方式还能用)

nginx采集

nginx-module-vts这个模块要在编译nginx的时候打进去

监控单机, docker 环境Nginx:

配置流程:
  编译安装nginx、添加nginx-module-vts模块
  编辑nginx配置并验证指标数据
  安装nginx exporter并验证数据
  配置prometheus收集nginx指标数据
  grafana导入模板验证数据
  

通过prometheus监控nginx:
需要在编译安装nginx的时候添加nginx-module-vts模块,github地址:https://github.com/vozlt/nginx-module-vts
root@prometheus-node2:~# cd /usr/local/src/

#下载内核源码,克隆或下载,后解压,后续以模块形式加载到nginx中
root@prometheus-node2:/usr/local/src# git clone https://github.com/vozlt/nginx-module-vts.git
root@prometheus-node2:/usr/local/src# unzip nginx-module-vts-0.2.5.zip

#下载nginx源码,重新编译下
root@prometheus-node2:/usr/local/src# wget https://nginx.org/download/nginx-1.30.0.tar.gz
root@prometheus-node2:/usr/local/src# apt  install iproute2  ntpdate  tcpdump telnet traceroute nfs-kernel-server nfs-common  lrzsz 
tree  openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev   gcc openssh-server      iotop unzip zip make

root@prometheus-node2:/usr/local/src# tar xvf nginx-1.30.0.tar.gz && cd nginx-1.30.0/

#编译nginx
root@prometheus-server2:/usr/local/src/nginx-1.24.0# ./configure --prefix=/apps/nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module  \
--with-http_gzip_static_module \
--with-pcre \
--with-file-aio \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--add-module=/usr/local/src/nginx-module-vts-0.2.5    #要加入,否则不支持

root@prometheus-node2:/usr/local/src/nginx-1.22.1# make && make install


编辑nginx配置文件:
root@prometheus-node2:/usr/local/src/nginx-1.24.0# vim /apps/nginx/conf/nginx.conf
http {
  ...
  #gzip on;
  vhost_traffic_status_zone; #启用状态页(改后nginx -t验证配置有没有问题)
  ...
  
  server {
    ...
    location /status {    #追加状态页
      vhost_traffic_status_display;
      vhost_traffic_status_display_format html;
    }
  }
  
#检测下语法
root@prometheus-node2:/# /apps/nginx/sbin/nginx -t
#启动(之前启动就 nginx -s reload)
root@prometheus-node2:/# /apps/nginx/sbin/nginx

#访问nginx和statues页面
172.31.2.182/status
#json格式输出
172.31.2.182/status/json
#支持prometheus格式输出(所以直接让prometheus收集这个路径也行)
172.31.2.182/status/format/prometheus

部署nginx-vts-exporter:

root@prometheus-node2:/usr/local/src# wget https://github.com/hnlq715/nginx-vts-exporter/releases/download/v0.10.3/nginx-vts-exporter-0.10.3.linux-amd64.tar.gz

root@prometheus-node2:/usr/local/src# tar xvf nginx-vts-exporter-0.10.3.linux-amd64.tar.gz

root@prometheus-node2:/usr/local/src# cp nginx-vts-exporter-0.10.3.linux-amd64/nginx-vts-exporter /usr/local/bin/

#指定nginx状态页地址,一定要json格式才行,就会收集指标
root@prometheus-node2:/usr/local/src# nginx-vts-exporter -nginx.scrape_uri http://127.0.0.1/status/format/json

#这时访问9913就可以看到指标
172.31.2.182:9913/metrics


#写个service文件,一直收集
root@prometheus-server2:/usr/local/src# cat /etc/systemd/system/nginx-vts-exporter.service
[Unit]
Description=nginx-vts-exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/nginx-vts-exporter -nginx.scrape_uri http://127.0.0.1/status/format/json

[Install]
WantedBy=multi-user.target

#验证nginx-vts-exporter数据:
root@prometheus-server2:/usr/local/src# systemctl start nginx-vts-exporter.service && systemctl enable nginx-vts-exporter.service

prometheus配置数据采集:

root@prometheus-server1:/apps/prometheus# vim prometheus.yml 
- job_name: 'nginx-metrics
  static_configs: 
  - targets: ['172.31.2.182:9913']
  
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service


#grafana导入模板  2949

监控Kubernetes 环境Nginx:

#先打镜像
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/1.nginx-image# vim Dockerfile
#FROM ubuntu:22.04
FROM registry.cn-hangzhou.aliyuncs.com/myhubregistry/ubuntu:24.04.3-base

LABEL maintainer="Jack <2973707860@qq..com>" \
      version="1.0" \
      description="This is a myserver project image"
#换源
ADD ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources
ARG NGINX_VERSION=1.30.0    #生成环境变量
ADD nginx-${NGINX_VERSION}.tar.gz /usr/local/src/  #加入源码包

#后面不用nginx-vtx-exporter也行
ADD nginx-vtx-exporter_0.10.8_linux_amd64/nginx-vtx-exporter /usr/local/bin/ 
ADD nginx-module-vts-0.2.5 /usr/local/src/nginx-module-vts-0.2.5
#RUN apt update && apt install -y iproute2  gcc openssh-server lrzsz tree  openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip make 
RUN  apt update  && apt  install -y openssl libssl-dev iproute2 tzdata locales fonts-noto-cjk wget  unzip  telnet net-tools gcc iotop  zip make iputils-ping libpcre3 libpcre3-dev  procps  fonts-noto-cjk  curl vim  libpcre2-dev zlib1g-dev  && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#用普通用户启动nginx,这个普通用户可加可不加
RUN groupadd  -r -g 2088 user1 && useradd -r -m  -s /sbin/nologin  -u 2088 -g 2088 user1
#编译
WORKDIR /usr/local/src/
RUN cd nginx-${NGINX_VERSION}/ &&  ./configure --prefix=/apps/nginx \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_realip_module \
  --with-http_stub_status_module  \
  --with-http_gzip_static_module \
  --with-pcre \
  --with-file-aio \
  --with-stream \
  --with-stream_ssl_module \
  --with-stream_realip_module \
  --add-module=/usr/local/src/nginx-module-vts-0.2.5 && make && make install
#做软连接,把日志做标准输出和错误输出,直接logs就能看见
RUN ln -sf /dev/stdout /apps/nginx/logs/access.log  && ln -sf /dev/stderr /apps/nginx/logs/error.log
RUN echo "alias ll='ls -l'" >> ~/.bashrc && localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 && dpkg-reconfigure -f noninteractive tzdata
ENV LANG=zh_CN.utf8

WORKDIR /root
ADD docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh /entrypoint.sh # 
ADD nginx.conf /apps/nginx/conf/nginx.conf    #加入配置文件
EXPOSE 80 443

ENTRYPOINT ["docker-entrypoint.sh"]


#启动,先把nginx拉起来,再把exporter跑起来
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/1.nginx-image# vim docker-entrypoint.sh
#!/bin/bash
/apps/nginx/sbin/nginx

#/usr/local/bin/nginx-vts-exporter -nginx.scrape_uri http://127.0.0.1/status/format/json
/usr/local/bin/nginx-vtx-exporter -nginx.scrape_uri http://127.0.0.1/status/format/json


root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/1.nginx-image# cat build-command.sh
#!/bin/bash
#docker build -t harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.22.1 .
nerdctl build -t harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.30.0 .
#docker push harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.22.1
nerdctl push harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.30.0

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/1.nginx-image# bash build-command.sh


#测试下能不能跑起来
root@ubuntu101:~/#nerdctl run -p 80:80 -it --rm harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.30.0

#部署
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/2.nginx-yaml# vim 1.nginx-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-nginx-deployment-label
  name: magedu-nginx-deployment
  namespace: magedu
spec:
  replicas: 2
  selector:
    matchLabels:
      app: magedu-nginx-selector
  template:
    metadata:
      labels:
        app: magedu-nginx-selector
        project: python
    spec:
      containers:
      - name: magedu-nginx-container
        image: harbor.myarchitect.online/magedu/nginx-vts-exporter:v1.30.0 
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/2.nginx-yaml# kubectl apply -f 1.nginx-deployment.yaml

收集指标

#上面deployment中pod没加Prometheus注解,所以发现不了,这里在service中加入注解
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/2.nginx-yaml# vim 2.nginx-svc.yaml
kind: Service
apiVersion: v1
metadata:
  labels:
    app: magedu-nginx-service-label
  name: magedu-nginx-service
  namespace: magedu
  annotations:
    prometheus.io/scrape: 'true'
    prometheus.io/port: "9913"
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30014
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30453
  - name: metrics
    port: 9913
    protocol: TCP
    targetPort: 9913
    nodePort: 39913
  selector:
    app: magedu-nginx-selector

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/4.nginx-vts-exporter/2.nginx-yaml# kubectl apply -f 2.nginx-svc.yaml


#grafana中导入模板  2949

监控案例:Prometheus监控Ingress-Nginx-Controller

#先部署ingress(有deployment和daemonset两种,若业务环境量不大,deployment部署即可)
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/5.ingress-case/1.1-ingress-nginx-1.8.2_deploy-yaml-k8s-v1.27.4# ls
1.ingress-nginx-controller-v1.8.2_daemonset.yaml  1.ingress-nginx-controller-v1.8.2_deployment.yaml
#如果部署deployment,最好节点反亲和

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/5.ingress-case/1.1-ingress-nginx-1.8.2_deploy-yaml-k8s-v1.27.4# vim 1.ingress-nginx-controller-v1.8.2_deployment.yaml
...
apiVersion: v1
kind: Service
metadata:
  labels:
    ...
  name: ingress-nginx-controller
  namespace: ingress-nginx
  annotations:    #追加,让Prometheus发现ingress controller
    prometheus.io/scrape: 'true'
    prometheus.io/port: "10254"

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/5.ingress-case/1.1-ingress-nginx-1.8.2_deploy-yaml-k8s-v1.27.4# kubectl apply -f 1.ingress-nginx-controller-v1.8.2_deployment.yaml

#把ingress contrller的端口40080配置到haproxy中(没有https,这里用http)
root@k8s-ha1:~# vim /etc/haproxy/haproxy.cfg
listen myserver-nginx
  bind 10.0.0.189:80
  mode tcp
  server k8s-node1 10.0.0.104:40080 check inter 3s fall 3 rise 5
  
root@k8s-ha1:~# systemctl restart haproxy.service

#测试ingress的指标地址,会直接暴露指标。上面指标端口配的是10254
curl ingress对应pod的ip:10254/metrics

#查看k8s的Prometheus,能直接发现ingress
http://10.0.0.101:39090/targets

#grafana导入模板  9614
http://10.0.0.101:33000

#目前还没有数据,ingress后面部署服务既有数据了
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/5.ingress-case# kubectl apply -f tomcat-app1.yaml -f tomcat-app2.yaml

#创建ingress规则(通过ingress访问pod来看ingress监控图标)
#移动端
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/5.ingress-case# vim 2.1.ingress_single-mobile.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mobile.jiege.com    #规则名称
  namespace: magedu
  annotations:
    kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
    #spec.ingressClassName: "nginx" ##指定Ingress Controller的类型
    nginx.ingress.kubernetes.io/use-regex: "true" ##指定后面rules定义的path可以使用正则表达式
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" ##连接超时时间,默认为5s
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600" ##后端服务器回转数据超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600" ##后端服务器响应超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-body-size: "50m" ##客户端上传文件,最大大小,默认为20m
    #nginx.ingress.kubernetes.io/rewrite-target: / ##URL重写
    nginx.ingress.kubernetes.io/app-root: /index.html
    
spec:
  ingressClassName: nginx
  rules:
  - host: mobile.jiege.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: magedu-tomcat-app2-service
            port:
              number: 80

ingress图标展示

 如果有个Prometheus在外面,可以把k8s里面的Prometheus当成联邦节点。外面的Prometheus去采集k8s里面的Prometheus,

再重新展示也行

监控kafka

这里有个项目,容器里面有kafka和exporter,通过kafka exporter收集的kafka指标

#docker-compose文件
version: '3'
services:
  zookeeper-server:
    container_name: zookeeper-container
    image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/zookeeper:v3.7.0 
    restart: always
    ports:
      - "2181:2181"
    volumes:
      - /etc/localtime:/etc/localtime
      - zookeeper_vol:/data
      - zookeeper_vol:/datalog
      - zookeeper_vol:/logs

  kafka-server:
    container_name: kafka-container
    image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kafka:2.13-2.8.1 
    ports:
      - "9092:9092"
    environment:
      #KAFKA_ADVERTISED_HOST_NAME: "172.31.4.3"
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://172.31.4.3:9092 #宿主机ip
      KAFKA_ADVERTISED_HOST_NAME: 0.0.0.0
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper-server:2181"
      KAFKA_LOG_DIRS: "/kafka/logs"
    volumes:
      - /etc/localtime:/etc/localtime
      - kafka_vol:/kafka
    restart: always
    links:
      - zookeeper-server
    depends_on:
      - zookeeper-server

  kafka_manager:
    image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kafka-manager 
    container_name: kafka-manager-container
    ports:
      - "9000:9000"
    environment:
      ZK_HOSTS: "zookeeper-server:2181"
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime
    links:
      - zookeeper-server
    depends_on:
      - zookeeper-server
      - kafka-server

  kafka-exporter:
    image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kafka-exporter:v1.7.0 
    container_name: kafka-exporter-container
    volumes:
      - /etc/localtime:/etc/localtime
    ports:
      - "9308:9308"
    restart: always
    links:#为exporter服务创建指向kafka-server服务的网络别名,容器内可通过kafka直接访问
      - kafka-server:kafka
    depends_on:
      - zookeeper-server
      - kafka-server

volumes:
  zookeeper_vol:
  kafka_vol:
  

#通过docker-compose部署kafka并通过kafka-exporter实现kafka指标采集:
root@k8s-deploy:~# cd /opt/
root@k8s-deploy:/opt# git clone https://gitee.com/jiege-gitee/kafka.git
root@k8s-deploy:/opt/kafka# docker-compose pull
#如果第一次部署出错了,要注意把zookeeper的卷(zookeeper_vol)和kafka的卷(kafka_vol)删掉,否则影响后面第二次部署
root@k8s-deploy:/opt/kafka# docker-compose up -d    #修改kafka监听地址
    #docker-compose文件修改,地址改成部署的本机地址,不改起不来
    environment:
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://172.31.4.3:9092 #宿主机ip


#会创建两个本地卷(zookeeper_vol和kafka_vol,第二次部署要删掉)
root@k8s-deploy:/opt/kafka# docker volume ls
#如果重新部署删除卷
#docker volume rm kafka_kafka_vol
#docker volume rm kafka_zookeeper_vol


#起来后,访问kafka管理端kafka_manager,端口号9000
#第一次登录,先添加kafka

添加kafka

#采集kafka通过kafka-exporter,端口好9308

#grafana导入模板   21708

kafka 主要指标: (可用于告警)

kafka主要指标

监控etcd

etcd 集群监控:Prometheus 自定义监控 etcd 集群的指标配置与实践(含关键指标解析)

#etcd上有两个证书文件,一个私钥,一个公钥
#指标是etcd自带的,不用使用etcd exporter
#要把证书给Prometheus,才能让Prometheus去采集

#验证通过证书可以访问
root@k8s-etcd1:~# curl -k --cert  /etc/kubernetes/ssl/etcd.pem  --key /etc/kubernetes/ssl/etcd-key.pem  https://172.31.7.106:2379/metrics

#在Prometheus服务器上,证书分发到prometheus(若Prometheus在k8s里面,可把证书创建成secret)
#这里是k8s以外的Prometheus
root@prometheus-server1:~# mkdir  /data/etcd/certs -p
#把etcd证书拷贝过去
root@k8s-etcd1:~# scp /etc/kubernetes/ssl/etcd.pem  /etc/kubernetes/ssl/etcd-key.pem  172.31.2.101:/data/etcd/certs 
#拷贝ca公钥,ca公钥在master上
root@k8s-master2:~# scp /etc/kubernetes/ssl/ca.pem 172.31.2.101:/data/etcd/certs/

#如果是k8s Prometheus环境里,要把这三个证书创建成secret


#prometheus配置:
    root@prometheus-server1:~# vim /apps/prometheus/prometheus.yml
      - job_name: 'etcd-cluster'
        metrics_path: /metrics
        scheme: https    #协议
        tls_config:        #证书配置
          ca_file: /data/etcd/certs/ca.pem
          cert_file: /data/etcd/certs/etcd.pem
          key_file: /data/etcd/certs/etcd-key.pem
        static_configs:    #地址
          - targets: ['172.31.7.106:2379','172.31.7.107:2379','172.31.7.108:2379']
          

#grafana导入模板   15308, 22236

监控组件 blackbox_exporter

blackbox_exporter是Prometheus 官方提供的一个exporter,可以监控 HTTP、 HTTPS、DNS、 TCP 、ICMP等目标实例,从而实现对被监控节点进行监控和数据采集。
    HTTP/HTPPS:URL/API可用性检测
    TCP:端口监听检测
    ICMP:主机存活检测
    DNS:域名可用
    
#promethues定义要监控的目标(比如ip通不通), 把监控(要调哪个模块)发给blackbox_exporter。blackbox_exporter根据Prometheus传递的目标和要使用的模块,进行抓取

blackbox_exporter使用架构

 

#部署blackbox_exporter
#去promethus.io官网下载blackbox_exporter
blackbox_exporter-0.28.0.linux-amd64.tar.gz

root@Prometheus-server2:/apps# tar xvf blackbox_exporter-0.28.0.linux-amd64.tar.gz
root@Prometheus-server2:/apps# ln -sv /apps/blackbox_exporter-0.28.0.linux-amd64 /apps/blackbox_exporter

#写service文件
root@Prometheus-server2:/apps# vim /etc/systemd/system/blackbox-exporter.service
[Unit]
Description=PrometheusBlackboxExporter
After=network.target

[Service]
Type=simple
User=root
Group=root
ExecStart=/apps/blackbox_exporter/blackbox_exporter\
    --config.file=/apps/blackbox_exporter/blackbox.yml\ #配置文件不用改,内有模块名称
    --web.listen-address=:9115
Restart=on-failure

[Install]
WantedBy=multi-user.target

#启动后
root@Prometheus-server2:/apps# systemctl start blackbox-exporter.service && systemctl enable blackbox-exporter.service

#blackbox-exporter启动后,可以通过9115端口查看

实现URL监控:

#监控http网站(如果Prometheus是k8s的,要修改configmap)
root@prometheus-server1:/apps/prometheus# vim /apps/prometheus/prometheus.yml
# 网站状态指标采集
- job_name: 'http_status'
  metrics_path: /probe    #指标路径(Prometheus获取指标路径),metric是它自己的指标
  params:
    module: [http_2xx]    #模块名称
  static_configs:
    - targets: ['http://www.xiaomi.com', 'http://www.magedu.com']
      labels:    #自己定义,会把标签加到指标里(可用于后期告警规则)
        instance: http_status
        group: web
  relabel_configs:    #标签重写
    - source_labels: [__address__] #将__address__(当前监控目标URL地址的标签)修改为__param_target,用于传递给blackbox_exporter
      target_label: __param_target #标签key为__param_target、value为www.xiaomi.com。key为__param_target、value为www.magedu.com
    - source_labels: [__address__] #非必须,新添加一个标签,key为url,value来自于__address__的值,用于绘图显示不同的http目标(url)
      target_label: url #将监控目标的值与url创建一个label
    - target_label: __address__  #新添加一个目标__address__,指向blackbox_exporter服务器地址,用于将监控请求发送给指定的blackbox_exporter服务器
      replacement: 172.31.2.102:9115 #指定blackbox_exporter服务器地址

root@prometheus-server1:/apps/prometheus# ./promtool check config ./prometheus.yml
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service
#重启后,它就会把目标发给blackbox exporter

#在blackbox exporter:9115端口页面可以看到抓取结果,每个域名都有log,包含抓取指标值
#里面包含证书过期时间 probe_ssl_earliest_cert_expiry   (秒)

prometheus验证指标抓取状态

prometheus验证指标抓取状态

 blackbox exporter界面验证数据

blackbox exporter界面验证数据

 实现ICMP监控:

root@prometheus-server1:/apps/prometheus# vim /apps/prometheus/prometheus.yml
# icmp 指标采集
- job_name: 'ping_status'
  metrics_path: /probe
  params:
    module: [icmp]    #模块名
  static_configs:
    - targets: ['172.31.0.2',"223.6.6.6"]    #监控目标(若为公有云要放开)
    labels:
      instance: 'ping_status'
      group: 'icmp'
  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target
    - source_labels: [__address__] #用于grafana显示采集目标
      target_label: ip
    - target_label: __address__
      replacement: 172.31.2.102:9115

root@prometheus-server1:/apps/prometheus# ./promtool check config ./prometheus.yml
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service
#重启后,它就会把目标发给blackbox exporter

实现端口监控

#监控端口通不通
root@prometheus-server1:/apps/prometheus# vim /apps/prometheus/prometheus.yml
# 端口指标采集
- job_name: 'port_status'
  metrics_path: /probe
  params:
    module: [tcp_connect]
  static_configs:
    - targets: ['172.31.2.101:9100', '172.31.2.102:9090','172.31.7.101:22']
      labels:
        instance: 'port_status'
        group: 'port'
  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target
    - source_labels: [__address__]  #用于grafana显示采集目标
      target_label: ip
    - target_label: __address__
      replacement: 172.31.2.102:9115
      
root@prometheus-server1:/apps/prometheus# ./promtool check config ./prometheus.yml
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service
#重启后,它就会把目标发给blackbox exporter


#grafana导入模版  9965

 

五:Alertmanager:

有个国产告警组件 PrometheusAlert, 比Alertmanager做的好。支持各种告警源和通知对象

prometheus触发一条告警的过程:

prometheus--->指标触发rule中的阈值--->超出持续时间--->alertmanager--->分组|抑制|静默--->媒体类型--->邮件|钉钉|微信等。

分组(group):将类似性质的警报发送给指定的收件人,比如网络通知发给网络工程师、数据库通知发送给
数据库工程师。
静默/沉默(silences):是一种简单的特定时间静音的机制,例如:服务器要升级维护可以先设置这个时间段告警静默。
抑制(inhibition):当警报发出后,停止重复发送由此警报引发的其他警报即合并一个故障引起的多个报警事件,可以消除冗余告警

alertmanager告警流程

 安装alertermanager:

root@prometheus-server3:/apps# pwd
/apps
root@prometheus-server3:/apps# wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz

root@prometheus-server3:/apps#tar xvf alertmanager-0.26.0.linux-amd64.tar.gz

root@prometheus-server3:/apps#ln -sv /apps/alertmanager-0.26.0.linux-amd64 /apps/alertmanager
'/apps/alertmanager'->'/apps/alertmanager-0.26.0.linux-amd64'

root@prometheus-server3:/apps#vim/etc/systemd/system/alertmanager.service
[Unit]
Description=Prometheusalertmanager
After=network.target

[Service]
ExecStart=/apps/alertmanager/alertmanager --config.file="/apps/alertmanager/alertmanager.yml"

[Install]
WantedBy=multi-user.target


root@prometheus-server3:/apps#systemctl daemon-reload &&systemctl restart alertmanager&&systemctl enable alertmanager

#会监听9093端口,可以登录alertmanager网页,展示当前状态,有没有告警,静默信息
#默认配置文件发不出告警,要自己调整匹配

#如果用docker启动,就用配置文件映射进去。如果k8s启动的话,就写configmap

5.1:邮件通知:

成本低,几乎没有成本,适合有专人值班

https://prometheus.io/docs/alerting/configuration/ #官方配置文档

#操作过程:
1.配置Prometheus的rule
2.配置Prometheus告警时发给谁,发给alertmanager,指定地址
3.配置alertmanager媒介,以什么样的方式发送给谁

5.1.1:alertermanager 配置文件解析:

# vim /apps/alertmanager/alertmanager.yml
global: 
  smtp_from: #发件人邮箱地址
  smtp_smarthost: #邮箱 smtp 地址。
  smtp_auth_username: #发件人的登陆用户名,默认和发件人地址一致。
  smtp_auth_password: #发件人的登陆密码,有时候是授权码。
  smtp_require_tls: #是否需要 tls 协议。默认是 true。
  
  wechart_api_url: #企业微信 API 地址。
  wechart_api_secret: #企业微信 API secret 
  wechat_api_corp_id: #企业微信 corp id 信息。
  
  resolve_timeout: 60s #当一个告警在 Alertmanager 持续多长时间未接收到新告警后就标记告警状态为resolved(已解决/已恢复)、在收件配置中结合 send_resolved: true 实现恢复通知

配置详解:

global: 
  resolve_timeout: 2m
  smtp_smarthost: 'smtp.qq.com:465' #现在一般都是ssl,465端口
  smtp_from: '2973707860@qq.com' 
  smtp_auth_username: '2973707860@qq.com'     #一般也是邮箱地址
  smtp_auth_password: 'ptiizujqboiydejf' #密码或授权码
  smtp_hello: '@qq.com' 
  smtp_require_tls: false    #一般是false
  
route:    #route 用来设置报警的分发策略
  group_by: [alertname] #采用哪个标签来作为分组依据,通过alertname告警名称(一般是这个)
  group_wait: 10s #一组告警第一次发送之前等待的延迟时间,即产生告警后延迟10秒钟将组内新产生的消息一起合并发送(一般设置为0)。
  group_interval: 10s #一组已发送过初始通知的告警接收到新告警后,下次发送通知前等待的延迟时间(一般设置为 5 分钟或更多)。
  repeat_interval: 2m #一条成功发送的告警,在最终发送通知之前等待的时间(通常设置为 3 小时或更长时间)。
#间隔示例:
  #group_wait: 10s #第一次产生告警,等待 10s,组内有告警就一起发出,没有其它告警就单独发出。
  #group_interval: 2m #第二次产生告警,先等待 2 分钟,2 分钟后还没有恢复就进入 repeat_interval。
  #repeat_interval: 5m #在最终发送消息前再等待 5 分钟,5 分钟后还没有恢复就发送第二次告警。

  receiver: default-receiver #其它的告警发送给 default-receiver (这里是非critical等级)
  routes: #将 critical(严重的)的报警发送给 myalertname
  - receiver: myalertname
  group_wait: 10s 
  match_re: 
    severity: critical #告警等级要在Prometheus的rule中定义
receivers: #定义多接收者
- name: 'default-receiver' 
  email_configs: 
  - to: 'rooroot@aliyun.com' 
    send_resolved: true #通知已经恢复的告警
- name: myalertname     #钉钉
  webhook_configs: 
  - url: 'http://172.30.7.101:8060/dingtalk/alertname/send' 
    send_resolved: true #通知已经恢复的告警

5.1.3:配置 prometheus 报警规则:

#规则文件放哪个路径无所谓,只要Prometheus启动能加载进去就行
root@prometheus-server1:/apps/prometheus# mkdir rules
root@prometheus-server1:/apps/prometheus# vim rules/server_rules.yaml
groups: 
  - name: alertmanager_pod.rules
    rules: 
    - alert: Pod_all_cpu_usage 警告
      expr: (sum by(name)(rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100) > 20
      for: 2m
      labels: #用于alertmanager去匹配这些告警源
        severity: warning
        service: pods 
        project: myserver 
      annotations: #description类似告警信息,$labels.name为容器名称(内置变量)
        description: 容器 {{ $labels.name }} CPU 资源利用率大于 20% , (current value is {{ $value }}) 
        summary: Pod CPU 利用率超过 20%

    - alert: Pod_all_cpu_usage 严重
      expr: (sum by(name)(rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100) > 30
      for: 2m
      labels: 
        severity: critical 
        service: pods 
        project: myserver 
      annotations: 
        description: 容器 {{ $labels.name }} CPU 资源利用率大于 10% , (current value is {{ $value }}) 
        summary: Pod CPU 利用率超过 30%

    - alert: Pod_all_memory_usage #expr: sort_desc(avg by(name)(irate(container_memory_usage_bytes{name!=""}[5m]))*100) > 10 #内存大于10%
      expr: sort_desc(avg by(name)(irate(node_memory_MemFree_bytes {name!=""}[5m]))) > 2 #内存大于2G
      for: 2m
      labels: 
        severity: critical
        project: myserver 
      annotations: 
        description: 容器 {{ $labels.name }} Memory 资源利用率大于 2G , (current value is {{ $value }}) 
        summary: Dev Memory 负载告警

    - alert: Pod_all_network_receive_usage
    expr: sum by (name)(irate(container_network_receive_bytes_total{container_label_io_kubernetes_pod_name!=""}[1m])) > 50*1024*1024
    for: 1m
    labels: 
      severity: critical
      project: myserver annotations: description: 容器 {{ $labels.name }} network_receive 资源利用率大于 50M , (current value is {{ $value }}) 
    
    - alert: node 内存可用大小
      expr: node_memory_MemFree_bytes < 42949672960 #故意写错的,写成4个g
      for: 1m
      labels: 
        #severity: critical #标签如果被基于严重等级的告警规则匹配成功后,则不在发送 project 规则的告警,即告警只会被一个规则匹配一次
        project: node
      annotations: 
        description: 容器可用内存小于 4G

  - name: ssl_expiry
    rules: 
    - alert: Ssl Cert Will Expire in 30 days 
      expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
      for: 1m
      labels: 
        severity: warning 
      annotations: 
        summary: "SSL certificate will expire soon on (instance {{ $labels.instance }})"           description: "https 证书还剩 30 days\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"

5.1.4:prometheus 加载报警规则:

root@prometheus-server1:/apps/prometheus# vim prometheus.yml
# Alertmanager configuration
alerting:    #告警发给谁
  alertmanagers:
  -static_configs:
    -targets:
      -172.31.2.103:9093 #alertmanager地址(生产环境可能是alertmanger的负载均衡器或service)

rule_files: 
  - "/apps/prometheus/rules/server_rules.yaml" #指定规则文件
  # - "second_rules.yml"
  
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service

#在Prometheus网页上可以看到Alerts


#注意这里Prometheus要收集k8s的pod指标,要收集cadvisor指标(前提保证cadvisor装上了)
root@prometheus-server1:/apps/prometheus# vim prometheus.yml
...
  - job_name: "cadivisor"
    static_configs
    - targets: ["172.31.7.111:8080","172.31.7.112:8080","172.31.7.113:8080"] #3个node

prometheus的alerts

5.1.2:配置并启动 alertermanager:

root@prometheus-server3:/apps# vim /apps/alertmanager/alertmanager.yml
global: 
  resolve_timeout: 2m    #2分钟没有收到新的告警就恢复(根据配置是否发通知)
  smtp_smarthost: 'smtp.qq.com:465' 
  smtp_from: '2973707860@qq.com' 
  smtp_auth_username: '2973707860@qq
  smtp_auth_password: 'udwthyyxtstcdhcj' 
  smtp_hello: '@qq.com' 
  smtp_require_tls: false

route: #route 用来设置报警的分发策略
  group_by: ['alertname'] #采用哪个标签来作为分组依据
  group_wait: 10s 
  group_interval: 10s
  repeat_interval: 2m
  receiver: 'web.hook' #设置接收人
receivers: 
- name: 'web.hook' 
  #webhook_configs: 
  #- url: 'http://127.0.0.1:5001/' 
  email_configs: 
    - to: '2973707860@qq.com' 
      send_resolved: true #是否发送已恢复的通知(一般发下)

inhibit_rules: #抑制的规则(一般这块不用动)
  - source_match: #源匹配级别,当匹配成功发出通知,但是其它'alertname', 'dev', 'instance'产生的 warning级别的告警通知将被抑制
      severity: 'critical' #报警的事件级别
    target_match: 
      severity: 'warning' #调用 source_match 的 severity 即如果已经有'critical' 级别的报警,那么将匹配目标为新产生的告警级别为'warning' 的将被抑制
    equal: ['alertname', 'dev', 'instance'] #匹配那些对象的告警

root@prometheus-server3:/apps# systemctl restart alertmanager.service

#有告警时,alertmanager页面(9093端口)会显示

5.2:钉钉通知:

先在钉钉,群里添加机器人, 通过webhook接入自定义服务

添加钉钉机器人

安全设置必须选一个:ip地址; 加签就是请求里要带个token; 关键字就是请求内容里要有关键字(可写alertname,name等只要消息里有就行)

钉钉认证-关键字-python 脚本:

root@dingding-server:~# vim /data/scripts/dingding-keywords.py
#!/usr/bin/python3
import sys
import requests
import json
#钉钉告警:
def info(msg): 
    url = 'https://oapi.dingtalk.com/robot/send?access_token=65cbfef3732b87f78a200973bbbed0d06f73ed38ae0ff04667fa1fec580faa41' 
    headers = {'Content-Type': 'application/json;charset=utf-8'}
    formdata = { "msgtype": "text", "text": {"content":str(msg)}}
    #print(formdata) 
    requests.post(url=url, data=json.dumps(formdata),headers=headers)
info(sys.argv[1])


#测试:
root@dingding-server:~# python3 /data/scripts/dingding-keywords.py "namespace=default\npod=pod1\ncpu=87%\n 持续时间=4.5m\nalertname=pod"

alertmanager可以使用prometheus-webhook-dingtalk发告警, 专门对接钉钉的

5.2.1.4:部署 webhook-dingtalk:

root@dingding-server:/apps# tar xvf prometheus-webhook-dingtalk-1.4.0.linux-amd64.tar.gz
root@dingding-server:/apps# ln -sv /apps/prometheus-webhook-dingtalk-1.4.0.linux-amd64 /apps/prometheus-webhook-dingtalk

#测试启动    ding.profile后面跟机器人的关键字alertname,后面加告警url
# ./prometheus-webhook-dingtalk --web.listen-address="0.0.0.0:8060" --ding.profile="alertname=https://oapi.dingtalk.com/robot/send?access_token=65cbfef3732b87f78a200973bbbe d0d06f73ed38ae0ff04667fa1fec580faa41


#修改alertmanager配置,让它把告警发给webhook-dingtalk
root@prometheus-server3:/apps/alertmanager# cat alertmanager.yml
...
route:
  group_by: [alertname]
  group_wait: 10s 
  group_interval: 10s
  repeat_interval: 10m
  # receiver: default-receiver
  receiver: dingding

receivers:    #加上新的收件人
...
- name: dingding 
  webhook_configs: 
  - url: 'http://172.31.2.120:8060/dingtalk/alertname/send' #后面地址时固定的
    send_resolved: true
    

root@prometheus-node1:/apps/alertmanager# systemctl restart alertmanager.service


#测试告警如果发出后,可以配置service文件启动:
root@dingding-server:/apps# cat /etc/systemd/system/prometheus-webhook-dingtalk.service
[Unit]
Description=Prometheus Server Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target

[Service]
Restart=on-failure 
WorkingDirectory=/apps/prometheus-webhook-dingtalk/
ExecStart=/apps/prometheus-webhook-dingtalk/prometheus-webhook-dingtalk --web.listen-address="0.0.0.0:8060" --ding.profile="alertname=https://oapi.dingtalk.com/robot/send?access_token=ba76276cd923a4e5dcd653ffabe4b71c4a23e8c4eb8e91446840d527c8d9cd4e"

[Install]
WantedBy=multi-user.target

5.2:钉钉消息模板:

消息模板定义在 dingtalk:

5.2.1:创建模板:

#下面的2006-01-02 15:04:05指的是时间格式,而不是指定这一天
root@dingding-server:/apps/prometheus-webhook-dingtalk# vim template1.yaml
{{ define "dingding.to.message1" }}

{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}} 

========= **监控告警** =========

**告警程序:** Alertmanager 
**告警类型:** {{ $alert.Labels.alertname }} 
**告警级别:** {{ $alert.Labels.severity }} 1**告警状态:** {{ .Status }} 
**故障主机:** {{ $alert.Labels.instance }} {{ $alert.Labels.device }} 
**告警主题:** {{ .Annotations.summary }} 
**告警详情:** {{ $alert.Annotations.message }}{{ $alert.Annotations.description}} 
**主机标签:** {{ range .Labels.SortedPairs }} </br> [{{ .Name }}: {{ .Value | markdown | html }} ]
{{- end }} </br>

**故障时间:** {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} 
========= = end = =========
{{- end }}
{{- end }}

{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}

========= 告警恢复 =========
**告警程序:** Alertmanager 
**告警主题:** {{ $alert.Annotations.summary }} 
**告警主机:** {{ .Labels.instance }} 
**告警类型:** {{ .Labels.alertname }} 
**告警级别:** {{ $alert.Labels.severity }} 1**告警状态:** {{ .Status }} 
**告警详情:** {{ $alert.Annotations.message }}{{ $alert.Annotations.description}} 
**故障时间:** {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
**恢复时间:** {{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} 

========= = **end** = =========
{{- end }}
{{- end }}
{{- end }}

5.2.2:配置 dingtalk 加载钉钉消息模板:

#若在k8s中,提供configmap
root@dingding-server:/apps/prometheus-webhook-dingtalk# cp config.example.yml config.yml

root@dingding-server:/apps/prometheus-webhook-dingtalk# vim config.yml
## Request timeout
# timeout: 5s

## Customizable templates path
templates: 
  - /apps/prometheus-webhook-dingtalk/template1.yaml 
  #- /apps/prometheus-webhook-dingtalk/template2.yaml 
  #- /apps/prometheus-webhook-dingtalk/template3.yaml

targets: 
  alertname: 
    url: https://oapi.dingtalk.com/robot/send?access_token=ac24b5bb7206c63fc95545eb44976b599ab423ca34c53f01890fed1c3c50553e 
    # secret for signature #钉钉加签内容,用就打开
    #secret: SEC76ae7c57db5e95d8a858f478dc2355aed4c36ae6836cbf1292cffad50c6a3f4b
    message: 
      # Use legacy template
      text: '{{ template "dingding.to.message1" . }}' #通过模板的 define 定义目标模板名称区分不同的模板,https://github.com/timonwong/prometheus-webhook-dingtalk/issues/16

5.2.3:启用 web 界面并指定配置文件启动 dingtalk:

#直接加载配置文件
root@dingding-server:/apps/prometheus-webhook-dingtalk-1.4.0.linux-amd64# ./prometheus-webhook-dingtalk --web.listen-address="0.0.0.0:8060" --web.enable-ui --config.file="config.yml"

#收到消息就会发给钉钉,消息会被序列化

#可以登录webhook-dingtalk网页,端口8060,可以测试消息序列化成模板样式
172.31.2.120:8060/ui/playground

5.3:企业微信通知:

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

打开企业微信官网注册账号,使用自己的手机号进行注册。

自 2022 年 6 月 20 号之后创建的机器人必须进行可信 IP 认证。

https://baijiahao.baidu.com/s?id=1745200188617297898&wfr=spider&for=pc

登录企业微信官网,创建应用(机器人)

企业微信创建应用

创建完后可以获取 AgentID 和 Secret, 可在企业微信上点击发消息测试

AgentID 和 Secret 会在发送微信报警信息的时候调用

AgentID和Secret

 查看企业id

企业id

5.3.13:prometheus 配置:

prometheus 和之前的配置一致,无需修改

5.3.14:alertermanager配置:

root@prometheus-server3:/apps/alertmanager# vim alertmanager.yml
...
route:
  group_by: [alertname]
  group_wait: 10s 
  group_interval: 10s
  repeat_interval: 10m
  # receiver: default-receiver
  receiver: wechat    #设置接收人为wechat

receivers:    #加个收件人信息,企业微信
  ...
  - name: 'wechat' 
    wechat_configs:  
    - corp_id: ww4c893118fbf4d07c    #企业id
      #to_user: '@all' #发给所有人
      to_party: 2    #部门id
      agent_id: 1000004    #agent id要换
      api_secret: STd8cpSsa2RAxH16WpnL6ZiOvVXulbh-XBh2_1kAnAU
      send_resolved: true    #是不是要发送恢复信息
      
root@prometheus-server3:/apps/alertmanager# systemctl restart  alertmanager.service

查看部门id

验证消息发送

5.5:自定义企业微信消息模板:

默认的消息内容需要调整、而且消息是连接在一起的。

5.5.1:定义模板:

#下面的变量都可以在官网找到
root@prometheus-server3:/apps/alertmanager# vim /apps/alertmanager/message_template.templ
{{ define "wechat.default.message" }}
{{ range $i, $alert :=.Alerts }} 
===alertmanager 监控报警=== 
告警状态:{{ .Status }}
告警级别:{{ $alert.Labels.severity }}
告警类型:{{ $alert.Labels.alertname }}
告警应用:{{ $alert.Annotations.summary }}
故障主机: {{ $alert.Labels.instance }}
告警主题: {{ $alert.Annotations.summary }}
触发阀值:{{ $alert.Annotations.value }}
告警详情: {{ $alert.Annotations.description }}
触发时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }} 
===========end============
{{ end }}
{{ end }


#然后在alertmanager中引用模板
root@prometheus-server3:/apps/alertmanager# vim alertmanager.yml
...
templates: #在空白的地方加上这个
  - '/apps/alertmanager-0.24.0.linux-amd64/message_template.templ' #alertermanager 引用模板

5.4:消息分类发送:

根据消息中的属性信息设置规则,将消息分类发送,目的如下:

1.将 node 的告警发给给 7x24 值班的企业微信群
  labels: 
    #severity: critical #标签如果被基于严重等级的告警规则匹配成功后,则不在发送 project 规则的告警,即告警只会被一个规则匹配一次
    project: node 

2.将 myserver 项目处于 warning 级别的告警发钉钉群
  severity: warning
  project: myserver 

3.将 myserver 项目处于 critical 级别的告警发送到 leader 的企业微信群,与指标的通过部门 ID 区分
  labels: 
    severity: critical
    project: myserver 

4.其它没有匹配的告警默认通知类型为邮件

5.4.1:prometheus rules 配置:

#首先要在promethues里给需要发送给更高收件人的告警加上label,要把他们筛出来
root@prometheus-server1:/apps/prometheus# vim rules/server_rule.yaml
groups:
  - name: alertmanager_pod.rules
  rules:
  - alert:Pod all cpu usage警告for: 2mlabels:
    expr: (sum by(name)(rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100)> 20
    severity: warning
    service:pods
    project:myserver
  annotations:
    description: 容器{{ $labels.name }} cPU 资源利用率大于 20%,(current value is {{ $value }})
    summary: Pod CPU利用率超过20%
  
  - alert: Pod_all_cpu_usage严重
  expr: (sum by(name)(rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100)> 30
  for:2m
  labels:
    severity: critical
    service: pods
    project: myserve
  annotations:
    description: 容器{{$labels.name }}CPu 资源利用率大于 10%,(current value is {{ $value }))
    summary: Pod CPU利用率超过30%
  ...
  

#在alertmanager里对这些告警进行匹配
root@prometheus-server3:/apps/alertmanager# vim alertmanager.yml
...
route: #route 用来设置报警的分发策略
  group_by: ['alertname'] #采用哪个标签来作为分组依据
  group_wait: 10s 
  group_interval: 10s
  repeat_interval: 2m
  receiver: 'email' #默认告警方式为邮件(正常应该发给wechat-365)
  #添加消息路由
  routes: 
  - receiver: 'wechat-365' #宿主机告警通过企业微信发送给监控组
    group_wait: 10s 
    match_re: 
      project: node #匹配 node 告警
  - receiver: 'dingding' #warning 级别的发送到钉钉群或邮件
    group_wait: 10s 
    match_re:     #写多个是and的关系,要同时满足
      severity: warning #匹配 warning 等级告警
      project: myserver
  - receiver: 'wechat-leader' #warning 级别的发送到 leader 的企业微信群
    group_wait: 1s 
    match_re: 
      severity: critical #匹配 critical 等级告警
      project: myserve
      
receivers:
- name: 'email' 
  email_configs: 
  - to: 'rooroot@aliyun.com' 
    send_resolved: true
- name: dingding 
  webhook_configs: 
  - url: 'http://172.31.2.120:8060/dingtalk/alertname/send' 
    send_resolved: true
- name: 'wechat-365' 
  wechat_configs: 
  - corp_id: ww4c893118fbf4d07c 
    #to_user: '@all' 
    to_party: 2
    agent_id: 1000004
    api_secret: STd8cpSsa2RAxH16WpnL6ZiOvVXulbh-XBh2_1kAnAU    #值班告警机器人
    send_resolved: true
- name: 'wechat-leader' 
  wechat_configs: 
  - corp_id: ww4c893118fbf4d07c 
    #to_user: '@all' 
    to_party: 14
    agent_id: 1000007
    api_secret: _nQiWd4cGHVDaFRoew5khHupHX3hHkcx43HPMIEsgGA #leader 告警机器人
    send_resolved: true
    
root@prometheus-server3:/apps/alertmanager# systemctl restart alertmanager.service

验证效果

飞书收到告警

各种告警规则参考

https://samber.github.io/awesome-prometheus-alerts/rules/

5.6:告警抑制与静默:

静默

若在特定时间段不想发告警,可以在alertmanager控制台上创建个Silence(静默规则),不让它发告警了;也可以直接把告警也关了

创建silence

图中,创建silence中    #以前的版本没有Matchers这个选项,选好静默时间直接提交就行
#注意时间格式,要早8小时
Matchers:匹配通过告警label匹配    # 要写,如:project="myserver",写完点下+号
Creator: 这个silence的创建者    # 要写

silence管理

查看当前所有silence,可以点Expire强制过期

抑制

基于告警规则,超过80%就不在发60%的告警,即由60%的表达式触发的告警被 抑制了。

同一个规则,如果有高的告警条件和低的告警条件。就会把低的规则抑制,不会发

root@prometheus-server1:/apps/prometheus# cat rules/server_rules.yaml
groups:
  - name: alertmanager_pod.rules
    rules:
    - alert: 磁盘容量
      expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes{fstype=~"ext4|xfs"}*100) > 80 #磁盘容量利用率大于 80%
      for: 2s
      labels:
        severity: critical
      annotations:
        summary: "{{$labels.mountpoint}} 磁盘分区使用率过高!"
        description: "{{$labels.mountpoint }} 磁盘分区使用大于 80%(目前使用:{{$value}}%)"
    - alert: 磁盘容量
      expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes{fstype=~"ext4|xfs"}*100) > 60 #磁盘容量利用率大于 60%
      for: 2s
      labels:
        severity: warning
      annotations:
        summary: "{{$labels.mountpoint}} 磁盘分区使用率过高!"
        description: "{{$labels.mountpoint }} 磁盘分区使用大于 80%(目前使用:{{$value}}%)"

5.7:alertermanager 高可用:

alertermanager高可用很少用,单机够用了。告警其实是http调用也没有消耗多少资源

5.7.1:单机:

alertermanager单机

5.7.2:基于负载均衡: #实现高可用

alertermanager高可用_负载均衡

5.7.3:基于 Gossip 机制:

官方的高可用机制

https://yunlzheng.gitbook.io/prometheus-book/part-ii-prometheus-jin-jie/readmd/alertmanager-high-availability

Alertmanager 引入了 Gossip 机制。Gossip 机制为多个 Alertmanager 之间提供了信息传递的机制。确保即使
在多个 Alertmanager 分别接收到相同告警信息的情况下,并且只有一个告警通知被发送给 Receiver。
集群环境搭建:
为了能够让 Alertmanager 节点之间进行通讯,需要在 Alertmanager 启动时设置相应的参数。其中主要的参
数包括:
--cluster.listen-address string: 当前实例集群服务监听地址
--cluster.peer value: 初始化时关联的其它实例的集群服务地址

基于 Gossip 机制

5.8:国产告警组件 PrometheusAlert:

比起alertermanager,在公司更推荐用PrometheusAlert,功能更强大,支持的告警信息更完善。支持更多云厂商的告警,图形功能更完善

PrometheusAlert 是开源的运维告警中心消息转发系统,支持主流的监控系统 Prometheus、Zabbix,日志系
统 Graylog2,Graylog3、数据可视化系统 Grafana、SonarQube,阿里云-云监控,以及所有支持 WebHook 接
口的系统发出的预警消息,支持将收到的这些消息发送到钉钉,微信,email,飞书,腾讯短信,腾讯电话,
阿里云短信,阿里云电话,华为短信,百度云短信,容联云电话,七陌短信,七陌语音,TG,百度
Hi(如流)等。

https://github.com/feiyu563/PrometheusAlert

7.K8S 核心组件监控:master 节点 api-server、controller-manager、kube-scheduler 指标采集与配置

使用k8s里面的Prometheus

#加上apiserver,做了服务发现(这是二进制装的(kubeasz),如果是kubeadm装的,有些发现配置不一样)
root@ubuntu101:~/1.prometheus-case-files# vim case3-1-prometheus-cfg.yaml
    - 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 #删除54-57

    - job_name: 'kube-controller-manager' #控制器,控制pod副本,资源限制
      scrape_interval: 10s
      scrape_timeout: 10s
      metrics_path: /metrics
      scheme: https
      kubernetes_sd_configs:
      - api_server: null
        role: endpoints
        namespaces:
          names: []
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        insecure_skip_verify: true
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        separator: ;
        regex: default;kubernetes;https
        replacement: $1
        action: keep
      - source_labels: [__address__]
        regex: '(.*):6443' #发现节点,下面把节点替换成10257(10257是kube-controller-manager的指标端口)
        replacement: '${1}:10257'    #通过10257拿到kube-controller-manager的指标
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)


    - job_name: 'kube-scheduler'    #做资源调度
      scrape_interval: 10s
      scrape_timeout: 10s
      metrics_path: /metrics
      scheme: https
      kubernetes_sd_configs:
      - api_server: null
        role: endpoints
        namespaces:
          names: []
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        insecure_skip_verify: true
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        separator: ;
        regex: default;kubernetes;https
        replacement: $1
        action: keep
      - source_labels: [__address__]
        regex: '(.*):6443'    #发现后端口替换为10259
        replacement: '${1}:10259'    #指标端口为10259
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)


#加上后Prometheus开始采集k8s这些组件的指标(promethues重启下),promethues网页上看下开始收集了没

#grafana导入模板
#grafana导入模板 15761      #apiserver

#可以从装好的kube-Prometheus中装好的Prometheus环境中导出模板,那边模板是最全的。这里从网上直接搜的
#grafana导入模板 12122      #kube-controller-manager

#grafana导入模板 24353      #kube-scheduler(如果指标不对,要在Prometheus页面查下对应指标什么样,改Prometheus或者改grafana展示语句)
修改下面grafana查询语句 component 为 job
sum by(name) (increase(workqueue_work_duration_seconds_bucket{job="kube-scheduler", cluster=~"$cluster"}[5m])> 8)

如果Prometheus要配置第三方存储,就配置remote_write,这样数据远程写入到其他地方,不写入本地了

可以让Prometheus把数据远程写入到 VictoriaMetrics 中

如果往里写的话,grafana就不向Prometheus查数据了,直接向 VictoriaMetrics 查数据

如果加上远程读,grafana还向Prometheus读数据,但promethues本地就不存了。读数据还是要向VictoriaMetrics去读

posted @ 2026-08-24 00:32  战斗小人  阅读(10)  评论(0)    收藏  举报