云原生k8s10 pushgateway,prometheus Federation(联邦集群),Prometheus与Exporter安全认证,手动k8s部署Prometheus一套,Prometheus自动发现,relabel机制与语法,kube-state-metrics,监控JVM和redis

prometheus pushgateway:

pushgateway 简介:

  pushgateway通常用于临时的指标数据收集。
  pushgateway不支持数据拉取(pull模式),需要客户端主动将数据推送给pushgateway。
  #pushgateway默认会把数据存在内存里,一重启数据就没了
  pushgateway可以单独运行在一个节点,然后需要自定义监控脚本把需要监控的主动推送给pushgateway的API接口,然后pushgateway再等待prometheus server抓取数据,即
pushgateway本身没有任何抓取监控数据的功能,目前pushgateway只能被动的等待数据从客户端进行推送。
  --persistence.file=""  #数据保存的文件,默认只保存在内存中
  --persistence.interval=5m  #数据持久化的间隔时间(每隔多久往上面保存的文件做数据持久化)

pushgateway 数据采集流程

 部署pushgateway:

#2种方式,容器里搭建或者二进制搭建(主机上)

#二进制方式搭建(长期用)
#在Prometheus的官网下载二进制文件  https://prometheus.io/download/#pushgateway

#使用docker部署(临时用)
#用官方的镜像起个临时的
  # docker run -d --name pushgateway -p 9091:9091 prom/pushgateway:v1.8.0


这里用二进制方法部署
#下载  pushgateway-1.11.2.linux-amd64.tar.gz,传入服务器上
#pushgateway装在prometheus-server2上,我这里就装在同一台机器上了
root@prometheus-server1:~# mv pushgateway-1.11.2.linux-amd64.tar.gz /usr/local/src/
root@prometheus-server1:~# cd /usr/local/src/
#解压,里面二进制文件直接启动就能用了,执行pushgateway即可
root@prometheus-server1:/usr/local/src# tar xvf pushgateway-1.11.2.linux-amd64.tar.gz

root@prometheus-server1:/usr/local/src# cp pushgateway-1.11.2.linux-amd64/pushgateway /usr/local/bin/
root@prometheus-server1:/usr/local/src# vim /lib/systemd/system/pushgateway.service
[Unit]
Description=Prometheus pushgateway
After=network.target

[Service]
ExecStart=/usr/local/bin/pushgateway

[Install]
WantedBy=multi-user.target

root@prometheus-server1:/usr/local/src# systemctl daemon-reload
root@prometheus-server1:/usr/local/src# systemctl restart pushgateway.service

#确保9091端口是监听的
root@prometheus-server1:/usr/local/src# ss -tnl
LISTEN        0             4096                              *:9091                             *:*

root@prometheus-server1:/usr/local/src# systemctl enable pushgateway.service

#浏览器登录测试  
http://10.0.0.108:9091/
#它不能抓指标,要我们把指标推上去
http://10.0.0.108:9091/metrics  #现在只有它自己的运行指标,没有业务指标

客户端推送单条指标数据:

要Push数据到PushGateway中,可以通过其提供的API标准接口来添加,默认URL地址为:
http://<ip>:9091/metrics/job/<JOBNAME>{/<LABEL_NAME>/<LABEL_VALUE>}
#ip为pushgateway的ip,job固定格式,JOBNAME类似注解,定义什么方式采集的,LABEL_NAME指标名称,LABEL_VALUE指标值

其中<JOBNAME>是必填项,是job的名称,后边可以跟任意数量的标签对,一般我们会添加一个 instance/<INSTANCE_NAME>实例名称标签,来方便区分各个指标是在哪个节点产生的。

如下推送一个job名称为mytest_job,key为mytest_metric值为2022
   # echo "mytest_metric 2088" | curl --data-binary @- http://10.0.0.108:9091/metrics/job/mytest_job #@-表示从标准输入读取数据

#执行
root@prometheus-node1:~# echo "mytest_metric 2088" | curl --data-binary @- http://10.0.0.108:9091/metrics/job/mytest_job
浏览器刷新   http://10.0.0.108:9091/metrics   可以看到如下:
# TYPE mytest_metric untyped
mytest_metric{instance="",job="mytest_job"} 2088  #instance是自动生成的,没写为空

http://10.0.0.108:9091/   可会看到前面上传的指标,后面点击delete group可删除指标

#更新指标,直接覆盖就行
root@prometheus-node1:~# echo "mytest_metric 2088" | curl --data-binary @- http://10.0.0.108:9091/metrics/job/mytest_job

prometheus server配置数据采集:

root@prometheus-server1:/apps/prometheus# vim prometheus.yml
global:
  scrape_interval: 15s 
  evaluation_interval: 15s #类似解析时间,对应下面的rule_files(告警规则之类,15s加载一次)
...
  - job_name: 'pushgateway-monitor'
    scrape_interval: 5s    #不写默认15s(上面global全局配置)
    static_configs:
      - targets: ['10.0.0.108:9091']


#测试Prometheus被调接口来动态加载配置,生产环境比较有用,不用重启Prometheus(重启要重新加载数据,可能较慢)
#首先开启web.enable-lifecycle,这里已经开启了
root@prometheus-server1:/apps/prometheus# vim /etc/systemd/system/prometheus.service
...
ExecStart=/apps/prometheus/prometheus --config.file=/apps/prometheus/prometheus.yml --web.enable-lifecycle

#curl下api,在任意主机,只要能通
root@prometheus-node1:~# curl -X POST http://10.0.0.108:9090/-/reload

#查看Prometheus的target health页,就看到监控pushgateway-monitor了
http://10.0.0.108:9090/targets
#就能在Prometheus查到刚刚pushgateway加入的自定义指标mytest_metric了
http://10.0.0.108:9090/ 下在query搜mytest_metric,返回如下
mytest_metric{exported_job="mytest_job", instance="10.0.0.108:9091", job="pushgateway-monitor"}  2088
#Prometheus拿到了,就可以在grafana进行绘图了

prometheus server验证指标

 客户端推送多条数据-方式一:

#对应地址:http://<ip>:9091/metrics/job/<JOBNAME>{/<LABEL_NAME>/<LABEL_VALUE>}
root@prometheus-node1:~# cat <<EOF | curl --data-binary @- http://10.0.0.108:9091/metrics/job/test_job/instance/10.0.0.109
#TYPE node_memory_usage gauge
node_memory_usage 4311744512
# TYPE memory_total gauge
node_memory_total 103481868288
EOF

推送多条数据-方式一

 客户端推基于脚本送多条数据-方式二:

#基于自定义脚本实现数据的收集和推送:
root@prometheus-node1:~# cat memory_monitor.sh
#!/bin/bash

total_memory=$(free |awk '/Mem/{print $2}')
used_memory=$(free |awk '/Mem/{print $3}')

job_name="custom_memory_monitor"    #定义任务名称
instance_name=`ifconfig eth0 | grep -w inet | awk '{print $2}'` pushgateway_server="http://10.0.0.108:9091/metrics/job"
#如果标签instance不够,可以后面再写一队
cat <<EOF | curl --data-binary @- ${pushgateway_server}/${job_name}/instance/${instance_name}
#TYPE custom_memory_total gauge
custom_memory_total $total_memory
#TYPE custom_memory_used gauge
custom_memory_used $used_memory
EOF


#分别在不同主机执行脚本,验证指标数据收集和推送:
root@prometheus-node1:~# bash memory_monitor.sh
root@prometheus-node2:~# bash memory_monitor.sh

客户端推基于脚本送多条数据-方式二

prometheus Federation(联邦集群):

如果机器特别多,一个Prometheus采集压力大,可以采用联邦节点采集指标,核心Prometheus抓取联邦节点采集的指标

prometheus Federation

 上图中,核心Prometheus主要负责抓取指标,如果数据量大,grafana从它这查数据,会有性能问题。核心Prometheus可以写入victory数据库,grafana直接读victory数据库的数据而非通过核心Prometheus

部署Prometheus联邦

ip作用
172.31.2.101 核心Prometheus
172.31.2.102 联邦节点1-收集172.31.2.181
172.31.2.103 联邦节点2-收集172.31.2.182, 172.31.2.183
172.31.2.181 node节点1,要装上node_exporter
172.31.2.182 node节点2,要装上node_exporter
172.31.2.183 node节点3,要装上node_exporter
#在101,102和103上分别安装prometheus server
root@prometheus-server1:~# mv prometheus-server-3.5.1-onekey-install.tar.gz /usr/local/src/
root@prometheus-server1:~# cd /usr/local/src/
root@prometheus-server1:/usr/local/src# tar xvf prometheus-server-3.5.1-onekey-install.tar.gz

#查看脚本,通过service文件跑起来
root@prometheus-server1:/usr/local/src# cat prometheus-install.sh
#!/bin/bash
VERSION="3.5.1"
PKG="prometheus-${VERSION}.linux-amd64.tar.gz"
S_DIR="prometheus-${VERSION}.linux-amd64"
mkdir -p /apps
tar xvf ${PKG} -C /apps/
ln -sv /apps/${S_DIR} /apps/prometheus
\cp ./prometheus.service /etc/systemd/system/prometheus.service
systemctl   daemon-reload &&  systemctl  restart prometheus && systemctl  enable  prometheus
echo "prometheus Server install successful"

#安装
root@prometheus-server1:/usr/local/src# bash prometheus-install.sh

配置prometheus联邦节点收集node-exporter指标数据:

#联邦节点先去收集数据
#联邦节点1-172.31.1.102:
root@prometheus-server1:/apps/prometheus# # vim prometheus.yml
  - job_name: "prometheus-idc1"
    static_configs: 
      - targets: ["172.31.2.181:9100"]
      
root@prometheus-server2:/apps/prometheus# systemctl restart prometheus.service

#联邦节点2-172.31.1.03:
root@prometheus-server3:/apps/prometheus# vim prometheus.yml
  - job_name: "prometheus-idc2"
    static_configs: 
      - targets: ["172.31.2.182:9100","172.31.2.183:9100"]

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

配置核心Prometheus server,去抓取102,103的数据

#如果之前这个核心Prometheus有数据的话,先停止,把数据移走,再启动相当于新的环境
root@prometheus-server1:/apps/prometheus# systemctl stop prometheus.service
#把数据移走,相当于把数据删了
root@prometheus-server1:/apps/prometheus# mv data data.bak
#如果之前配置了抓取指标,也删掉下配置
root@prometheus-server1:/apps/prometheus# systemctl start prometheus.service


#配置prometheus server通过联邦节点收集的node-exporter指标数据:
root@prometheus-server1:/apps/prometheus# vim prometheus.yml
  - job_name: 'prometheus-federate-2.102' #每个联邦节点都要加
    scrape_interval: 10s    #抓取间隔时间
    honor_labels: true    #保留原指标,不把指标替换,一般为true
    metrics_path: '/federate'    #Prometheus联邦节点指标url,聚合了很多指标,不能直接看,要加正则指定看
    params:
      'match[]': #数据匹配条件
      - '{job="prometheus"}' #匹配job=prometheus的间序列数据,这是Prometheus收集的当前节点自身的运行指标数据
      - '{job="prometheus-idc1"}' #匹配job="prometheus-idc1,这是联邦节点收集的其它主机的指标数据
      - '{__name__=~"job:.*"}' #名称正则匹配,or a metric name starting with ,后续匹配任意长度的任意字符
      - '{__name__=~"node.*"}' # or a metric name starting with ,后续匹配任意长度的任意字符
      - '{__name__=~"node_memory.*"}' #指定匹配以 开头的指标名称
    static_configs: 
    - targets: 
      - '172.31.2.102:9090' #可以写多个
  - job_name: 'prometheus-federate-2.103'
    scrape_interval: 10s
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]': 
      - '{job="prometheus"}' #匹配job=prometheus的间序列数据,这是Prometheus收集的当前节点自身的运行指标数据
      - '{job="prometheus-idc2"}' #匹配job="prometheus-idc2,这是联邦节点收集的其它主机的指标数据
      - '{__name__=~"job:.*"}' # or a metric name starting with job: ,后续匹配任意长度的任意字符
      - '{__name__=~"node.*"}' # or a metric name starting with node ,后续匹配任意长度的任意字符
      - '{__name__=~"node_memory.*"}' #指定匹配以node_memory开头的指标名称
    static_configs: 
    - targets: 
      - '172.31.2.103:909
      
root@prometheus-server1:/apps/prometheu# systemctl restart prometheus.service
#如果等了15s,1分钟以上还是没有数据,可以通过二进制启动Prometheus来排错

#下图为验证prometheus 通过联邦节点收集的node-exporter指标数据,其中job是Prometheus联邦节点加的

promethues联邦指标检查

 grafana 验证数据(16098)

grafana看联邦数据

 

Prometheus Server与 Exporter的安全认证

这是扩展功能,一般用不上; api被拿到了, 无非是获得些监控数据, 有可能不太安全,要加上些认证

Prometheus Server web登录认证:

root@prometheus-server1:~# apt install apache2-utils
root@prometheus-server1:~# htpasswd -nbB -C 10 admin admin123 #指定使用bcrypt加密密码,账户名admin、密码为admin123,-n不更新密码文件,-b命令行获取密码,-B使用bcrypt加密(https://zh.wikipedia.org/wiki/Bcrypt)
admin:$2y$10$ccEsAGpJSl9jhgsL/UJbzOGEXi6agE5ceBHcZFhC.0ix05hAOCPFC
#注意:加到Prometheus中时admin:后要加个空格

#同一个Prometheus可以配置好几个账号,但没办法指定具体权限

#文件名无所谓
root@prometheus-server1:~# vim /apps/prometheus/web-auth.yaml
basic_auth_users:
  admin: $2y$10$ccEsAGpJSl9jhgsL/UJbzOGEXi6agE5ceBHcZFhC.0ix05hAOCPFC


#service里加个参数, web.config.file
root@prometheus-server1:~# vim /etc/systemd/system/prometheus.service
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target

[Service]
Restart=on-failure
WorkingDirectory=/apps/prometheus/
ExecStart=/apps/prometheus/prometheus --config.file=/apps/prometheus/prometheus.yml --web.enable-lifecycle --web.config.file=/apps/prometheus/web-auth.yaml

[Install]
WantedBy=multi-user.target

#加载
root@prometheus-server1:~# systemctl daemon-reload
root@prometheus-server1:~# systemctl restart prometheus.service

#后期通过curl命令, 第三方客户端如grafana访问Prometheus必须带认证(如granfana已有数据源,要修改数据源的认证)

prometheus web界面登录验证

Prometheus Server与 Node Exporter的安全认证

node-exporter一般不加,一般都是内网地址

Node Exporter 配置认证:

root@prometheus-server1:~# htpasswd -nbB -C 10 user1 user123 #生成密码
user1:$2y$10$IxyxKCJyyZymv2J70tmo6OtmuTxG8Y8Qd1pDIa5f50ZR9e3/dyB7W
#注意:加到配置中时user1:后要加个空格

node配置:
root@prometheus-node1:~# vim /apps/node_exporter/api-auth.yaml
basic_auth_users:
  user1: $2y$10$gt4N7oLvbNRLiRrF4RatT.DczUw6fkVF29MObgC2i3ejjudE0DmXW

#修改service文件,追加web.config.file参数
root@prometheus-node1:~# vim /etc/systemd/system/node-exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target

[Service]
ExecStart=/apps/node_exporter/node_exporter --web.config.file=/apps/node_exporter/api-auth.yaml

[Install]
WantedBy=multi-user.target


root@prometheus-node1:~# systemctl daemon-reload
root@prometheus-node1:~# systemctl restart node-exporter.service

#分发到其他各node节点:
root@prometheus-node1:~# scp /apps/node_exporter/api-auth.yaml 172.31.2.182:/apps/node_exporter/api-auth.yaml
root@prometheus-node1:~# scp /etc/systemd/system/node-exporter.service 172.31.2.182:/etc/systemd/system/node-exporter.service
root@prometheus-node2:~# systemctl daemon-reload
root@prometheus-node2:~# systemctl restart node-exporter.service

#这时,浏览器输入Node Exporter的metrics地址需要输入认证

Prometheus Server实现配置认证:

#追加basic_auth
root@prometheus-server1:~# vim /apps/prometheus/prometheus.yml
scrape_configs:
  - job_name: "prometheus"    #自己的指标
    basic_auth:    #下面写上账号名,密码
      username: admin
      password: admin123
    static_configs: 
      - targets: ["localhost:9090"] 
    
  - job_name: 'promethues-node'
    basic_auth:
      username: user1
      password: user123
    static_configs: 
      - targets: ['172.31.2.181:9100','172.31.2.182:9100']

root@prometheus-server1:~# systemctl restart prometheus.service

核心Prometheus到Prometheus联邦节点也需要做认证,否则核心Prometheus抓取不到指标

加的方式都是一样的

#追加basic_auth配置
root@prometheus-server1:/apps/prometheus# vim prometheus.yml
  - job_name: 'prometheus' #它自己的
    basic_auth:    #下面写上账号名,密码
      username: admin
      password: admin123
    static_configs:
      - targets: ["localhost:9090"]
        labels:
          app: "prometheus"
      
  - job_name: 'prometheus-federate-2.102' #每个联邦节点都要加
    basic_auth:    #下面写上账号名,密码
      username: admin
      password: admin123
    scrape_interval: 10s
    honor_labels: true
    metrics_path: '/federate'
    params:
      ...    #参考上面
  - job_name: 'prometheus-federate-2.103'
    basic_auth:    #下面写上账号名,密码
      username: admin
      password: admin123 
    scrape_interval: 10s
    honor_labels: true
    metrics_path: '/federate'
    params:
      ...    #参考上面
      
root@prometheus-server1:/apps/prometheu# systemctl restart prometheus.service

手动在k8s中部署Prometheus

为了了解Prometheus原理,这里不用kube-Prometheus,手动一个个部署Prometheus组件

一:node-exporter、cadvisor 和 prometheus server:

#主节点传入1.prometheus-case-files-y99-v4.zip并解压
root@ubuntu101:~# unzip 1.prometheus-case-files-y99-v4.zip
root@ubuntu101:~# cd 1.prometheus-case-files/
root@ubuntu101:~/1.prometheus-case-files# ls
app-monitor-case                      case2-daemonset-deploy-node-exporter.yaml  case3-4-nginx.yaml                    kube-state-metrics-2.18.0
bak                                   case3-1-prometheus-cfg.yaml                case4-prom-rbac.yaml                  kube-state-metrics-2.18.0.zip
cadvisor-v0.39.2.tar.gz               case3-1-prometheus-cfg.yaml.bak            case5-grafana.yaml
cadvisor-v0.39.2.tar.gz.zip           case3-2-prometheus-deployment.yaml         case6-kube-state-metrics-deploy.yaml
case1-daemonset-deploy-cadvisor.yaml  case3-3-prometheus-svc.yaml                case7-binary-prometheus-config.yaml

1.1:安装 cadvisor:

采集node节点上容器指标,可以做二次开发(go语言)

#可以docker部署,这里用daemonset部署
#通过daemonset安装cadvisor

root@ubuntu101:~/1.prometheus-case-files# vim case1-daemonset-deploy-cadvisor.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: cadvisor-daemonset
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: cAdvisor
  template:
    metadata:
      labels:
        app: cAdvisor
    spec:
      tolerations:    #污点容忍,忽略master的NoSchedule
        - effect: NoSchedule
          key: node-role.kubernetes.io/master
      hostNetwork: true    #自己加的,监听在宿主机网络,为了后面Prometheus跑在k8s外面做服务发现(里面不需要)
      restartPolicy: Always   # 重启策略
      containers:
      - name: cadvisor
        image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/cadvisor-amd64:v0.56.2 
        imagePullPolicy: IfNotPresent  # 镜像策略
        ports:
        - containerPort: 8080
        volumeMounts:
          - name: root
            mountPath: /rootfs
          - name: run
            mountPath: /var/run
          - name: sys
            mountPath: /sys
          - name: docker
            #mountPath: /var/lib/docker
            mountPath: /var/lib/containerd
      volumes:
      - name: root
        hostPath:
          path: /
      - name: run
        hostPath:
          path: /var/run
      - name: sys
        hostPath:
          path: /sys
      - name: docker
        hostPath:
          #path: /var/lib/docker 
          path: /var/lib/containerd

root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case1-daemonset-deploy-cadvisor.yaml
#这时各个节点上8080端口就可看到cadvisor指标了  http://10.0.0.104:8080/containers/
#和kube-Prometheus部署的效果一样,采集各个pod的指标了,采集什么数据就看当前节点运行什么容器了
#收集的指标地址,promethues采集这个地址:    http://10.0.0.104:8080/metrics

#kubelet有cadvisor,但是它的版本,访问路径都是特定的,单独的api。可以单独部署一个,如上所示,自己部署的更好管理些

1.2:node-exporter:

#和二进制安装效果效果相同,单机用docker run就行
root@ubuntu101:~/1.prometheus-case-files# vim case2-daemonset-deploy-node-exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter-daemonset
  namespace: monitoring 
  labels:
    k8s-app: node-exporter
spec:
  selector:
    matchLabels:
        k8s-app: node-exporter
  template:
    metadata:
      labels:
        k8s-app: node-exporter
    spec:
      tolerations:
        - effect: NoSchedule
          key: node-role.kubernetes.io/master
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/node-exporter:v1.11.1 
        imagePullPolicy: IfNotPresent
        name: prometheus-node-exporter
        ports:
        - containerPort: 9100
          hostPort: 9100
          protocol: TCP
          name: metrics
        volumeMounts:
        - mountPath: /host/proc
          name: proc
        - mountPath: /host/sys
          name: sys
        - mountPath: /host
          name: rootfs
        args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        - --path.rootfs=/host
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
        - name: rootfs
          hostPath:
            path: /
      hostNetwork: true    #如果不用host网络,外网不能访问,宿主机浏览器无法访问(不需要就去掉)
      hostPID: true


root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case2-daemonset-deploy-node-exporter.yaml

#测试:  http://10.0.0.104:9100/

1.3:prometheus server:

#可以使用docker run一个,也可以使用二进制部署,也可以在k8s里部署

#准备Prometheus的配置文件
root@ubuntu101:~/1.prometheus-case-files# vim case3-1-prometheus-cfg.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus-config
  namespace: monitoring 
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 10s
      evaluation_interval: 1m
    scrape_configs:
    - job_name: mysql-monitor-172.31.2.102 #静态示例,先忽略
      static_configs:
        - targets: ['172.31.2.102:9104']

    - job_name: 'kubernetes-node' #动态发现,自动发现新加的node,缩容也会发现,不会再抓取指标
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)

    - job_name: 'kubernetes-cadvisor' #发现有单独ns的cadvisor(因上面用容器直接启动)
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:8080'
        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/${1}/proxy/metrics/cadvisor #k8s里的,要通过这个特定指标路径访问
    - job_name: 'kubernetes-apiserver' #发现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' #动态发现所有svc的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: $1:$2
      - 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' #直接发现pod(不用service)
      kubernetes_sd_configs:
      - role: pod
        namespaces: #可选指定namepace,如果不指定就是发现所有的namespace中的pod
          names:
          - myserver
          - magedu
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name

    - job_name: 'kubernetes-nginx-pods'
      kubernetes_sd_configs:
      - role: pod
        namespaces: #可选指定namepace,如果不指定就是发现所有的namespace中的pod
          names:
          - myserver
          - magedu
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name


    - job_name: "kube-state-metrics"
      static_configs:
        - targets: ["kube-state-metrics.kube-system:8080"]


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

#接下来要保护Prometheus
#可以用pvc存储类,创建静态pvc。这里为了方便,直接用共享存储

#创建共享目录
root@k8s-ha1:~# mkdir -p /data/k8sdata/prometheusdata
#确保目录是共享出去的
root@k8s-ha1:~# vim /etc/exports
/data/k8sdata *(rw,no_root_squash)    #共享出去了,里面的子目录直接可以挂载使用

#改下权限(如果用的是文件存储类,也要改下;如果是块不用改) Prometheus镜像里进程默认使用普通用户启动,id为65534
root@k8s-ha1:~# chown 65534:65534 /data/k8sdata/prometheusdata/ -R

#保证Prometheus部署时有权限,创建监控账号monitor,并授予权限能在k8s集群中执行api的发现动作
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# vim case3-2-prometheus-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-server-deployment
  namespace: monitoring
  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:
      securityContext:
        runAsUser: 0
      #nodeName: 172.31.7.113
      serviceAccountName: monitor
      containers:
      - name: prometheus
        image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/prometheus:v3.5.2 
        imagePullPolicy: IfNotPresent
        command:    #启动参数,可以自己指定
          - prometheus
          - --config.file=/etc/prometheus/prometheus.yml #配置文件
          - --storage.tsdb.path=/prometheus    #数据目录,要做数据持久化
          - --storage.tsdb.retention.time=720h #数据最长保留时间
          - --web.enable-lifecycle    #api reload打开
        resources: #Prometheus非常消耗内存,因采集指标先放内存里,2小时往磁盘持久化一次(规模越大,消耗越多)
          limits:
            memory: "2048Mi"
            cpu: "1"
          requests:
            memory: "2048Mi"
            cpu: "1"
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: /etc/prometheus/prometheus.yml
          name: prometheus-config
          subPath: prometheus.yml
        - mountPath: /prometheus/
          name: prometheus-storage-volume
      volumes:
        - name: prometheus-config
          configMap:
            name: prometheus-config
            items:
              - key: prometheus.yml
                path: prometheus.yml
                mode: 0644
        - name: prometheus-storage-volume #可以直接使用pvc,把权限改好就行
          nfs:
            server: 10.0.0.107
            path: /data/k8sdata/prometheusdata

          #hostPath:
          # path: /data/prometheusdata
          # type: Directory


root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-2-prometheus-deployment.yaml
#这样数据就在共享存储上,把Prometheus删了重建也没关系,数据不会丢失,它重启之后会重新加载历史的指标数据

root@ubuntu101:~/1.prometheus-case-files# kubectl get pod -n monitoring
NAME                                            READY   STATUS    RESTARTS      AGE
cadvisor-daemonset-46lh6                        1/1     Running   0             2d23h
cadvisor-daemonset-mmhph                        1/1     Running   0             2d23h
cadvisor-daemonset-pxr9r                        1/1     Running   0             2d23h
cadvisor-daemonset-v4hst                        1/1     Running   0             2d23h
node-exporter-daemonset-992vr                   1/1     Running   0             2d11h
node-exporter-daemonset-j8hh7                   1/1     Running   0             2d11h
node-exporter-daemonset-jng4v                   1/1     Running   0             2d11h
node-exporter-daemonset-p54hk                   1/1     Running   0             2d11h
prometheus-server-deployment-7d499fb7df-7z2vg   1/1     Running   0             35s

#看下是不是真的起来了,一定要都是info,error的话就要看下了(若没有改权限会报数据写入失败)
root@ubuntu101:~/1.prometheus-case-files# kubectl -n monitoring logs -f prometheus-server-deployment-7d499fb7df-7z2vg

#创建service
root@ubuntu101:~/1.prometheus-case-files# vim case3-3-prometheus-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: prometheus-svc
  namespace: monitoring
  labels:
    app: prometheus
spec:
  type: NodePort
  ports:
    - port: 9090
      targetPort: 9090
      nodePort: 39090
      protocol: TCP
  selector:
    app: prometheus
    component: server
    
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-3-prometheus-svc.yaml

#访问  10.0.0.101:39090
#在Prometheus页面的target可以看到自动发现的服务,kubernetes-nodes-cadvisor是kubelet自带的cadvisor,kubernetes-cadvisor是通过daemonset装的cadvisor

部署grafana

#准备放grafana数据地址
root@k8s-ha1:~# mkdir -p /data/k8sdata/grafana

root@ubuntu101:~/1.prometheus-case-files# vim case5-grafana.yaml
#---
#apiVersion: v1
#kind: PersistentVolumeClaim
#metadata:
#  name: grafana-pvc
#spec:
#  accessModes:
#    - ReadWriteOnce
#  resources:
#    requests:
#      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: grafana
  name: grafana-deployment
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      securityContext:
        runAsUser: 0
      #nodeName: 172.31.7.113
      containers:
        - name: grafana
          image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/grafana:9.3.6 
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
              name: http-grafana
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /robots.txt
              port: 3000
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 30
            successThreshold: 1
            timeoutSeconds: 2
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 3000
            timeoutSeconds: 1
          resources:
            requests:
              cpu: 250m
              memory: 750Mi
          volumeMounts:
            - mountPath: /var/lib/grafana
              name: grafana-nfs-volume
      volumes:
      - name: grafana-nfs-volume
        nfs:
          server: 10.0.0.107    #把数据放到存储上,这里可用pvc
          path: /data/k8sdata/grafana
---
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: monitoring
spec:
  type: NodePort
  ports:
    - port: 3000
      protocol: TCP
      targetPort: http-grafana
      nodePort: 33000
  selector:
    app: grafana
  #sessionAffinity: None
  #type: LoadBalancer

root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case5-grafana.yaml
#若起不来,看下日志可能是数据存放路径权限不足,可在另一台机器上docker run启动镜像,ps -ef看下grafana用户id为472
#执行       root@k8s-ha1:~# chown 472:0 /data/k8sdata/grafana -R
#改完后重新部署下,最好删了重建grafana

#访问   10.0.0.101:33000              admin/admin
#左侧设置下,data sources添加Prometheus数据源,写Prometheus的service(不建议写nodeport)
#url写 http://prometheus-svc.monitoring:9090     #同一个namespace可以不加,最好这里加上
#保存

root@ubuntu101:~/1.prometheus-case-files# kubectl get svc -n monitoring
NAME             TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
grafana          NodePort   10.100.45.140    <none>        3000:33000/TCP   16m
prometheus-svc   NodePort   10.100.112.205   <none>        9090:39090/TCP   69m

#grafana上import coredns的dashboard,14981,名字写 CoreDNS-14981,选择上面添加的Prometheus数据源,点import
#如下图,Requests(total) 为请求速率,可以压测获得到达瓶颈的值,然后设置告警值
#Responses(latency)是响应延迟时间,决定了性能

coredns图标

二:prometheus 的服务发现机制:

    prometheus 获取数据源 target 的方式有多种,如静态配置和动态服务发现
配置,prometheus 默认是采用 pull 方式拉取监控数据的,也就是周期性去目标
主机上抓取 metrics 数据,每一个被抓取的目标需要暴露一个 HTTP 接口,
prometheus 通过这个暴露的接口就可以获取到相应的指标数据,这种方式需要
由 Prometheus 提前配置好要采集的目标有哪些,需要在 Prometheus.yml 配置
scrape_configs 中的各种静态 job 来实现,无法动态感知新服务,如果后面增加或
删除了目标 node、pod 等,就得手动修 promrtheus 配置,并重启 promethues,
很不方便,所以出现了动态服务发现(Service Discovery,简称 sd),动态服务发现能
够使 Prometheus Server 自动发现要采集的目标的新端点,对被删除 pod 也会自
动发现并不在采集其指标,通过服务发现,Prometheus 能查询到需要监控的
Target 列表,然后轮询这些 Target 获取监控数据。
    prometheus 目前支持的服务发现有很多种,常用的主要分为以下几种:#下面配置中包含sd的都是动态发现
    https://prometheus.io/docs/prometheus/latest/configuration/configuration/#configuration-file
    
kubernetes_sd_configs: #基于Kubernetes API实现的服务发现,让prometheus动态发现kubernetes中被监控的目标
static_configs: #静态服务发现,基于 prometheus 配置文件指定的监控目标
dns_sd_configs: #DNS 服务发现监控目标        #很少用
#consoul为第三方服务,服务注册到consul中,Prometheus会定时去consul获取要监控的指标列表,一般是微服务或地址.如果不变Prometheus就什么都不做,如果增加或少了目标,Prometheus会做对应调整(这种服务发现不需要依赖于k8s api)
consul_sd_configs: #Consul 服务发现,基于 consul 服务动态发现监控目标 
file_sd_configs: #基于指定的文件实现服务发现,基于指定的文件发现监控目标    #很少用


promethues 的静态静态服务发现 static_configs:每当有一个新的目标实例需要监控,都需要手动修改
配置文件配置目标 target.

promethues 的 consul 服务发现 consul_sd_configs:Prometheus 一直监视 consul 服务,当发现在
consul 中注册的服务有变化,prometheus 就会自动监控到所有注册到 consul 中的目标资源.

promethues 的 k8s 服务发现 kubernetes_sd_configs:Prometheus 与 Kubernetes 的 API 进行交互,
动态的发现 Kubernetes 中部署的目标资源.

2.1:relabeling 简介及 kubernetes_sd_configs:

https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config

#Prometheus抓取到k8s的指标后,前面会自动加上__meta_kubernetes如__meta_kubernetes_pod_ready,有时为了精简展示,会进行标签重写
promethues 的 relabeling(标签重写)功能很强大,它能够在抓取到目标实例之前把目标实例的元数据标签
动态重新修改,动态添加或者覆盖标签,prometheus 从 Kubernetes API 动态发现目标(target)之后,在被发现
的 target 实 例中 , 都会 附加 一 些 的对 应 的 Metadata 标 签信 息 , 比如 service 服 务发 现 的 标签 :
https://github.com/prometheus/prometheus/blob/main/discovery/kubernetes/service.go
元数据标签有:
__address__:以<host>:<port> 格式显示目标 targets 的地址
__scheme__:采集的目标服务地址的 Scheme 形式,HTTP 或者 HTTPS 
__metrics_path__:采集的目标服务的访问路径

#如下图,是没有重写之前,Prometheus抓取后序列化后的指标

relabeling 简介

2.1.1:基础功能-重新标记目的:

为了更好的识别监控指标,便于后期调用数据匹配、grafana 展示、告警等需求, prometheus 支持对发现的目标进行 label 修改,在两个阶段可以重新标记:

#常用relabel_configs,很少用metric_relabel_configs
relabel_configs : 在对 target 进行数据采集之前(比如在采集数据之前重新定义标签信息,如目的 IP、目
的端口等信息),可以使用 relabel_configs 添加、修改或删除一些标签、也可以只采集特定目标或过滤目
标,通常都是使用此方式。

metric_relabel_configs:在对 target 进行数据采集之后,即如果是已经抓取到指标数据时,可以使用
metric_relabel_configs 做最后的重新标记和过滤。

重新标记

#示例:
静态配置:
  - job_name: "prometheus-node"
    static_configs: 
      - targets: ["172.31.2.181:9100","172.31.2.182:9100"]
      
基于 API Server 的动态发现:
    - job_name: 'kubernetes-apiserver' #名称自己写,这里用于发现apiserver的endpoint
      kubernetes_sd_configs:    #发现的方式,基于kubernetes_sd_configs实现服务发现(k8s的服务发现)
      - role: endpoints    #发现类型为 endpoints
      scheme: https    #使用的发现协议
      tls_config:    #证书配置
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt#容器里的证书路径,公钥(每个pod都有)
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token #容器里的 token 路径
      relabel_configs:    #重写,重新re修改标签 label 配置 configs
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] #源标签,即对哪些标签进行操作
        action: keep    #action 定义了 relabel 的具体动作,action 支持多种
        regex: default;kubernetes;https #指定匹配条件、只发现 default 命名空间的 kubernetes 服务后面的endpoint 并且是 https 协议

#会拿到下面的endpoint,进行指标抓取。如果是多个,会进行轮询指标抓取
root@ubuntu101:~/1.prometheus-case-files# kubectl get ep
NAME         ENDPOINTS         AGE
kubernetes   10.0.0.101:6443   140d

#grafana就可以展示和apiserver相关的状态指标了,这里导入15761模板id,名字加-15761,数据源选Prometheus

2.1.2:label 详解:

source_labels:源标签,没有经过 relabel 处理之前的标签名字
target_label:通过 action 处理之后生成新的标签名字(不删除原有旧标签)    #保留情况没有这个标签,看action怎么做
regex:自定义的值或正则表达式匹配,功能是用于匹配源标签的值
replacement:通过分组替换后标签(target_label)对应的/()/() $1:$2 #类似对括号内正则,通过$1,$2进行引用(标签分组引用)

2.1.3:action 详解:

https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config

#replace和keep用的比较多
replace:替换标签值,根据regex正则匹配到源标签的值,使用replacement来引用表达式匹配的分组
keep:满足regex正则条件的实例进行采集,把source_labels中没有匹配到regex正则内容的Target实例丢
掉,即只采集匹配成功的实例。
drop:满足regex正则条件的实例不采集,把source_labels中匹配到regex正则内容的Target实例丢掉,
即只采集没有匹配到的实例。

#hashmod用的很少
hashmod:使用hashmod计算source_labels的Hash值并进行对比,基于自定义的模数取模,以实现对目标
进行分类、重新赋值等功能:
scrape_configs:
  -job_name:ip_job
    relabel_configs:
    -source_labels:[__address__]    #对ip地址取模
      modulus: 4    #按4取模,返回0,1,2,3
      target_label: __ip_hash    #对ip地址做的hash
      action: hashmod    #这个动作是hashmod
    -source_labels:[__ip_hash]
      regex: ^1$    #只取结果是1的,进行保留
      action: keep
      
#做标签映射
labelmap:匹配regex所有标签名称,然后复制匹配标签的值进行分组,可以通过replacement分组引用(${1},${2},…)替代

labelkeep:匹配regex所有标签名称,其它不匹配的标签都将从标签集中删除
labeldrop:匹配regex所有标签名称,其它匹配的标签都将从标签集中删除

2.1.4:测试label功能:

#测试删掉下面3行,因为没有了过滤,很多无关的pod都被匹配进行监控了
root@ubuntu101:~/1.prometheus-case-files#vim case3-1-prometheus-cfg.yaml
...
    - job_name: 'kubernetes-apiserver' #发现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:
      #不指定namespace,服务名称和协议,会发现一大堆namespace,service
      #- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
      #  action: keep
      #  regex: default;kubernetes;https     #删除54-57
      
root@ubuntu101:~/1.prometheus-case-files# kubectl apply-f case3-1-prometheus-cfg.yaml

#还要把Prometheus重建下,Prometheus在创建的时候会拉去configmap,只重启不会更新configmap
root@ubuntu101:~/1.prometheus-case-files# kubectl delete -f case3-2-prometheus-deployment.yaml
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-2-prometheus-deployment.yaml

2.1.5:查看prometheus server容器证书:

root@ubuntu101:~/1.prometheus-case-files# kubectl exec -it -n monitoring prometheus-server-deployment-fdc4c4df6-ljcv2 -- ls /var/run/secrets/kubernetes.io/serviceaccount/

#对比容器的ca.crt与宿主机/etc/kubernetes/ssl/ca.pem文件的md5值是一样的。
root@ubuntu101:~/1.prometheus-case-files# kubectl exec -it -n monitoring prometheus-server-deployment-fdc4c4df6-ljcv2-- md5sum /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

root@ubuntu101:~/1.prometheus-case-files# md5sum /etc/kubernetes/ssl/ca.pem

2.1.6:支持的发现目标类型:

node #node节点
service #发现service
pod #通过pod注解发现pod
endpoints #基于svc注解发现endpoints(pod),有的场景pod不一定都有svc
Endpointslice #对endpoint进行切片
ingress #发现ingress

2.1.8:api-server 指标数据:

Apiserver 组件是 k8s集群的入口,资源对象的管理请求都是从apiserver进来的,所以对apiserver指标做监控可以用来判断集群的健康状况。

2.1.8.1:apiserver_request_total:

以下promQL语句为查询apiserver最近一分钟不同方法的请求数量统计:
apiserver_request_total 为请求各个服务的访问详细统计:
#哪些url的请求次数最多
sum(rate(apiserver_request_total[10m])) by (instance,code,verb)

2.1.8.2:关于annotation_prometheus_io_scrape:

在k8s中,基于prometheus的发现规则,需要在被发现的目的target定义注解匹配annotation_prometheus_io_scrape=true,且必须匹配成功该注解才会保留监控target,然后再进行数据抓取并进行标签替换,如 annotation_prometheus_io_scheme标签为http或https:

#对应被监控项上的注解如下:
promethues.io/scrape: true    #允许Prometheus发现,否则Prometheus会把他们忽略掉不做发现
promethues.io/path: <metric path>    #告诉Prometheus,去哪个url抓取指标,默认metrics不用指定
promethues.io/port: <port>


#Prometheus中自动发现的配置
- job_name: 'kubernetes-service-endpoints'#job名称
      kubernetes_sd_configs: #sd_configs发现
      -role: endpoints#角色,基于svc的endpoints发现
      relabel_configs: #标签重写配置
      
#annotation_prometheus_io_scrape的值为true,保留标签然后再向下执行
      - source_labels:
[__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
        
#将__meta_kubernetes_service_annotation_prometheus_io_scheme修改为__scheme__
      -source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex:(https?)#正则匹配协议http或https(?匹配全面的字符0次或一次),即其它协议不替换
        
#将__meta_kubernetes_service_annotation_prometheus_io_path替换为__metrics_path__
      -source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+) #路径为为1到任意长度(.为匹配除\n之外的任意单个字符,+为匹配一次或多次)
        
#地址发现及标签重写
      -source_labels: [__address__,__meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement:$1:$2 #格式为地址:端口
        
#匹配regex所匹配的标签,然后进行应用:
      -action: labelmap
        regex: __meta_kubernetes_service_label_(.+) #通过正则匹配名称匹配之前的数据:

正则匹配

#将__meta_kubernetes_namespace替换为kubernetes_namespace
      -source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace

#将__meta_kubernetes_service_name替换为kubernetes_name
      -source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name

2.1.9:kube-dns的服务发现:

2.1.9.1:查看kube-dns状态:

root@ubuntu101:~# kubectl get svc -n kube-system kube-dns -o yaml |grep prometheus
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"prometheus.io/port":"9153","prometheus.io/scrape":"true"},"labels":{"addonmanager.kubernetes.io/mode":"Reconcile","k8s-app":"kube-dns","kubernetes.io/cluster-service":"true","kubernetes.io/name":"CoreDNS"},"name":"kube-dns","namespace":"kube-system"},"spec":{"clusterIP":"10.100.0.2","ports":[{"name":"dns","port":53,"protocol":"UDP"},{"name":"dns-tcp","port":53,"protocol":"TCP"},{"name":"metrics","port":9153,"protocol":"TCP"}],"selector":{"k8s-app":"kube-dns"}}}
    prometheus.io/port: "9153"     #注解标签,用于prometheus匹配发现端口
    prometheus.io/scrape: "true"     #注解标签,用于prometheus匹配抓取数据

通过svc发现pod及指标:

root@ubuntu101:~/1.prometheus-case-files# vim case3-1-prometheus-cfg.yaml
...
    - job_name: 'kubernetes-service-endpoints' #动态发现所有svc的endpoints
      kubernetes_sd_configs:
      - role: endpoints    #要发现endpoints,通过svc发现
      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    #生成一个新label,给Prometheus抓数据用,名为__scheme__,值就是匹配的值,https或http
        target_label: __scheme__
        regex: (https?)    #值是https或者http都行
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] #没写默认/metrics
        action: replace    ##生成一个新label,给Prometheus抓数据用,名为__metrics_path__
        target_label: __metrics_path__
        regex: (.+)    #任意长度任意字符,至少有一个
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]#地址,端口
        action: replace    #下面一个目标label表示源label合一块
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)    #匹配地址,匹配端口
        replacement: $1:$2    #做标签引用
      - action: labelmap    #把发现的label全部加上下面内容,Prometheus加的
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]    #匹配namespace
        action: replace    #生成新的label,叫kubernetes_namespace,值是上面匹配的值
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]    #servicename
        action: replace    #生成新的label
        target_label: kubernetes_name


#如果修改coredns副本数(或创其他符合条件svc),Prometheus很快会发现,在Prometheus页面上方栏选target health可看到
http://10.0.0.101:39090/targets

#下面是部署nginx服务来测试上面Prometheus通过svc服务发现pod
root@ubuntu101:~/1.prometheus-case-files# vim case3-4-nginx.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-nginx-deployment-label
  name: magedu-nginx-deployment
  namespace: magedu
spec:
  replicas: 3
  selector:
    matchLabels:
      app: magedu-nginx-selector
  template:
    metadata:
      labels:
        app: magedu-nginx-selector
      annotations:
        prometheus.io/port: "9913"
        prometheus.io/scrape: "true"
    spec:
      containers:
      - name: magedu-nginx-container
        #image: gaciaga/nginx-vts:1.11.12-alpine-vts-0.1.14 
        image: registry.cn-hangzhou.aliyuncs.com/myhubregistry/nginx:gaciaga_nginx-vts-1.11.12-alpine-vts-0.1.14 
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
          - name: "password"
            value: "123456"
          - name: "age"
            value: "20"
      - name: magedu-nginx-exporter-container
        #image: sophos/nginx-vts-exporter 
        image: registry.cn-hangzhou.aliyuncs.com/myhubregistry/nginx:sophos_nginx-vts-exporter_v0.10.7 
        imagePullPolicy: IfNotPresent
        args:
          - '-nginx.scrape-uri=http://127.0.0.1/status/format/json'
        ports:
          - containerPort: 9913
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: magedu-nginx-service-label
  name: magedu-nginx-service
  namespace: magedu
  annotations:
    prometheus.io/port: "9913"    #端口9913
    prometheus.io/scrape: "true"    #允许做发现
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30092
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30093
  selector:
    app: magedu-nginx-selector



#只发现那些namespace对应Prometheus配置
root@ubuntu101:~/1.prometheus-case-files# vim case7-binary-prometheus-config.yaml
#指定namespace 的pod
  - job_name: 'kubernetes-发现指定namespace的所有pod'
    kubernetes_sd_configs:
    - role: pod
      api_server: https://172.31.7.101:6443
      tls_config:
        insecure_skip_verify: true
      bearer_token_file: /apps/prometheus/k8s.token
      namespaces:    #指定发现哪些namespace,这种最节省性能 
        names:
        - myserver
        - magedu
    relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_pod_label_(.+)
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: kubernetes_namespace
    - source_labels: [__meta_kubernetes_pod_name]
      action: replace
      target_label: kubernetes_pod_name
      
#另一种方式不在这指定,在发现时通过正则匹配,属于先发现后过滤,把发现后的结果丢弃,不如上面直接指定名称空间去发现好

gpu有dcgm-exportor, 做服务发现的, 这个是英伟达直接提供的。node-eporter采集不到gpu的指标

2.1.10:node 节点发现及指标

2.1.10.1:配置详解:

kind: ConfigMap
apiVersion: v1 
metadata:
  labels: 
    app: prometheus 
  name: prometheus-config 
  namespace: monitor-sa
data: 
  prometheus.yml: |
  global: 
    scrape_interval: 15s
    scrape_timeout: 10s 
    evaluation_interval: 1m
  scrape_configs: 
  - job_name: 'kubernetes-node' #job name
    kubernetes_sd_configs: #发现配置
    - role: node #发现角色
    relabel_configs: #标签重写配置
    
    - source_labels: [__address__] #源标签
      regex: '(.*):10250' #通过正则匹配后缀为:10250 的实例,10250 是 kubelet 端口
      replacement: '${1}:9100' #重写为IP:9100,即将端口替换为prometheus node-exporter的端口,$1是上面匹配第一个
      target_label: __address__ #将[__address__]替换为__address__,生成新的label,让Prometheus拿这个地址
      action: replace #将[__address__] 的值依然赋值给__address__
#发现 lable 并引用
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+) #加上前缀
#匹配的目的数据:

node 节点发现及指标

2.1.10.2:kubelet 监听

# lsof -i:10250
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
kubelet 866 root 10u IPv6 47583 0t0 TCP k8s-node1:10250->k8s-master1:47644 (ESTABLISHED)
kubelet 866 root 29u IPv6 27079 0t0 TCP *:10250 (LISTEN)

# kubectl get node 172.31.7.113 -o yaml | grep 10250
    Port: 1025

2.1.10.3:node 节点指标

# curl http://172.30.7.111:9100/metrics

#HELP:解释当前指标的含义,上面表示在每种模式下 node 节点的 cpu 花费的时间,以 s 为单位
#TYPE:说明当前指标的数据类型,如:
# HELP node_load1 1m load average. 
# TYPE node_load1 gauge 
node_load1 0.49
# HELP node_load15 15m load average. 
# TYPE node_load15 gauge 
node_load15 0.72
# HELP node_load5 5m load average. 
# TYPE node_load5 gauge 
node_load5 0.54

2.1.10.4:常见监控指标:

node_cpu_:CPU 相关指标
node_load1:load average #系统负载指标
node_load5 
node_load15

node_memory_:内存相关指标

node_network_:网络相关指标

node_disk_:磁盘 IO 相关指标
node_filesystem_:文件系统相关指标

node_boot_time_seconds:系统启动时间监控

go_*:node exporte 运行过程中 go 相关指标
process_*:node exporter 运行时进程内部进程指标

#grafana上node模板可以选   11047

2.1.11:Cadvisor 发现:

2.1.11.1:prometheus job 配置:

#下面是发现kubelet内置的cadvisor,这种用的不多,用的比较多的是单独装一个cadvisor
  - job_name: 'kubernetes-node-cadvisor' #job 名称
    kubernetes_sd_configs: #基于 k8s 的服务发现
    - 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 #默认 token 路径
    relabel_configs: #标签重写配置
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)

#replacement 指定替换后的标签(target_label)对应的值为 kubernetes.default.svc:443
    - target_label: __address__
      replacement: kubernetes.default.svc:443 #通过k8s的api server做指标获取

#将[__meta_kubernetes_node_name]重写为 __metrics_path__
    - source_labels: [__meta_kubernetes_node_name] regex: (.+) #至少1位长度以上
      target_label: __metrics_path__
      replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor #指定cadvisord 的API路径(kubelet内置的cadvisor)

查看 cadvisor 数据:
# curl --cacert /etc/kubernetes/ssl/ca.pem -H "Authorization: Bearer $TOKEN" https://172.31.7.101:6443/api/v1/nodes/172.31.7.113/proxy/metrics/cadvisor


#tls_config 配置的证书地址是每个 Pod 连接 apiserver 所使用的地址,无论证书是否用得上,在 Pod 启动时kubelet 
都会给每一个 pod 自动注入 ca 的公钥,即所有的 pod 启动的时候都会有一个 ca 公钥被注入进去用于在访问 apiserver 的时候被调用。
#下面是单独装一个cadvisor(在主机直接部署的cadvisor,可以采集到k8s里pod的指标),这种方式用的更多些
root@ubuntu101:~/1.prometheus-case-files# vim case3-1-prometheus-cfg.yaml
...
    - job_name: 'kubernetes-cadvisor' #发现有单独ns的cadvisor(因上面用容器直接启动)
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:8080'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
#一旦发现cadvisor之后,就可以导入cadvisor相关指标了
#grafana上搜cadvisor对应模板,有些模板会有服务发现的示例(可能需要特定label,最好按照它的写)   
14282   #这个模板比较老,名字label获取不对   查看指标地址 ip:8080/metrics ,改查询语句label

指定namespace发现目标

-job_name:'kubernetes-nginx-pods'
  kubernetes_sd_configs:
  -role:pod
    namespaces:#可选指定namepace,如果不指定就是发现所有的namespace中的pod
      names:
      -myserver
      -maged

2.1.13:prometheus 部署在 k8s 集群以外并实现服务发现:

k8s是单独部署的,Prometheus是在k8s外部部署的,这种情况下要实现服务发现,Prometheus自动发现并抓取pod的指标

要注意网络问题,要考虑采集pod地址通不通(有时能发现,但不在一个网络内像overlay网络,抓取不到指标,要把pod和Prometheus的网络打通)

#promethues访问nginx的pod访问不通演示
#获取nginx的pod地址
root@ubuntu101:~/1.prometheus-case-files# kubectl get pod -n magedu -o wide
NAME                                     IP                NODE
magedu-nginx-deployment-85c9cd4469-2rx78    10.200.45.23    172.31.7.111
magedu-nginx-deployment-85c9cd4469-zlgds    10.200.195.4    172.31.7.113
nagedu-nginx-deployment-85c9cd4469-zwdqn    10.200.165.18    172.31.7.112

#从外部Prometheus访问nginx的pod地址不通,因为这个地址是k8s里通过calico虚拟出来的,k8s外访问不通
root@prometheus-serverl:-# ping 10.200.195.4

#这种情况下就没办法抓取pod的指标,但如果连通node就可以抓取node的指标

在namespacemonitoring 创建服务发现账号prometheus并授权。

2.1.13.1:创建用户并授权:

这个账号是给服务发现使用的,去使用token,token要配在外部使用的Prometheus上,否则Prometheus没权限做服务发现

(k8s里面部署Prometheus是使用默认的,所以就没有配)

root@ubuntu101:~/1.prometheus-case-files# vim case4-prom-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: monitoring
---
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token    #创建token
metadata:
  name: monitoring-token
  namespace: monitoring
  annotations:
    kubernetes.io/service-account.name: "prometheus"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole    #授权
metadata:
  name: prometheus
rules:
- apiGroups:
  - ""
  resources:    #能够发现资源对象
  - nodes
  - services
  - endpoints
  - pods
  - nodes/proxy
  verbs:    #授权动作
  - get
  - list
  - watch
- apiGroups:
  - "extensions"
  resources:
    - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - nodes/metrics
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
#apiVersion: rbac.authorization.k8s.io/v1beta1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding    #权限绑定
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitoring


root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case4-prom-rbac.yaml

root@ubuntu101:~/1.prometheus-case-files# kubectl get secrets -n monitoring
NAME             TYPE
monitoring-token kubernetes.io/service-account-token

#拿到token,放到k8s环境以外的Prometheus上
root@ubuntu101:~# kubectl describe secret monitoring-token -n monitoring
Name:         monitoring-token
Namespace:    monitoring
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: prometheus
              kubernetes.io/service-account.uid: b7215575-024d-4e97-8493-f4c33a880545
Type:  kubernetes.io/service-account-token    #账号token
Data
====
ca.crt:     1310 bytes
namespace:  10 bytes
token:      eyJh...1Odw    #获取这个token值

  
#写入token,放到k8s环境以外的Prometheus上
root@prometheus-server1:~# vim /apps/prometheus/k8s.token        #名称,后缀名随便起
eyJh...1Odw

2.1.13.3:prometheus 添加 job:

这里是二进制的Prometheus

#这里有的通,有的不通。像apiserver能通,像pod就不通。追加下面内容
root@prometheus-server1:~# vim /apps/prometheus/prometheus.yml
#node节点发现
- job_name: 'kubernetes-nodes-monitor'
  scheme: http
  tls_config:
    insecure_skip_verify: true    #忽略证书
  bearer_token_file: /apps/prometheus/k8s.token    #token
  kubernetes_sd_configs:
    - role: node    #发现node
      api_server: https://172.31.7.101:6443    #指定api server
      tls_config:
        insecure_skip_verify: true    #忽略证书
      bearer_token_file: /apps/prometheus/k8s.token
  relabel_configs:    #和k8s里的配置一样
    - source_labels: [__address__]
      regex: '(.*):10250'
      replacement: '${1}:9100'
      target_label: __address__
      action: replace
    #下面这些可以不写,加了些label做测试
    - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region]
      regex: '(.*)'
      replacement: '${1}'
      action: replace
      target_label: LOC
    - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region]
      regex: '(.*)'
      replacement: 'NODE'
      action: replace
      target_label: Type
    - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region]
      regex: '(.*)'
      replacement: 'K8S-test'
      action: replace
      target_label: Env
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)

#指定namespace的pod
- job_name: 'kubernetes-发现指定namespace的所有pod'
  kubernetes_sd_configs:
    - role: pod
      api_server: https://172.31.7.101:6443
      tls_config:
        insecure_skip_verify: true
      bearer_token_file: /apps/prometheus/k8s.token
      namespaces:
        names:
          - myserver
          - magedu
  relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_pod_label_(.+)
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: kubernetes_namespace
    - source_labels: [__meta_kubernetes_pod_name]
      action: replace
      target_label: kubernetes_pod_name

#指定Pod发现条件(这里肯定不通,机器连不上pod)
- job_name: 'kubernetes-指定发现条件的pod'
  kubernetes_sd_configs:
    - role: pod
      api_server: https://172.31.7.101:6443    #推荐些api server的负载均衡器地址
      tls_config:
        insecure_skip_verify: true    #忽略证书
      bearer_token_file: /apps/prometheus/k8s.token    #指定token,这个token一定要有权限
  relabel_configs:    #标签重写,和k8s里写的没什么区别
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
      action: replace
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
      target_label: __address__
    - action: labelmap
      regex: __meta_kubernetes_pod_label_(.+)
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: kubernetes_namespace
    - source_labels: [__meta_kubernetes_pod_name]
      action: replace
      target_label: kubernetes_pod_name
    - source_labels: [__meta_kubernetes_pod_label_pod_template_hash]
      regex: '(.*)'
      replacement: 'K8S-test'
      action: replace
      target_label: Env
      
      
root@prometheus-server1:~# systemctl restart prometheus.service

prometheus 部署在 k8s 集群以外并实现服务发现

 

下面是Prometheus基于第三方的服务发现实现方式

用的最多的是consul的方式, file/dns 的服务发现了解即可

consul方式: 如果服务能注册到consul中,Prometheus通过consul读取已经注册的服务并对他们进行指标的抓取

2.3:consul_sd_configs:

https://www.consul.io/

Consul是分布式k/v数据存储集群,目前常用于服务的服务注册和发现。

2.3.1:部署consul集群:

consul下载地址: (二进制)

https://releases.hashicorp.com/consul/

Docker部署:

#docker部署的地址不固定,client允许0.0.0.0访问就行
#docker run -d -p 8500:8500 --name=consul hashicorp/consul:1.22.7 agent -server -bootstrap -ui -client=0.0.0.0

或二进制环境:

#准备三台主机
172.31.2.181
172.31.2.182
172.31.2.183

Node1:
#把官网下载的二进制文件解压
root@prometheus-node1:~# unzip consul_1.22.7_linux_amd64.zip
root@prometheus-node1:~# cp consul /usr/local/bin/
root@prometheus-node1:~# scp consul 172.31.2.182:/usr/local/bin/
root@prometheus-node1:~# scp consul 172.31.2.183:/usr/local/bin/

#验证可执行
#consul -h

#分别创建数据目录:
# mkdir /data/consul/ -p

#参数:
consulagent-server #使用server模式运行consul服务
-bootstrap #首次部署使用初始化模
-bind #设置群集通信的监听地址 (一般和-client是一样的,多网卡可能不通,也可写0.0.0.0)
-client #设置客户端访问的监听地址
-data-dir #指定数据保存路径
-ui #启用内置静态webUI服务器
-node #此节点的名称,群集中必须唯一
-datacenter=dc1 #集群名称,默认是dc1
-join #加入到已有consul环境

#启动服务:
#第一次启动要加bootstrap
node1:
root@prometheus-node1:~# nohup consul agent -server -bootstrap -bind=172.31.2.181 -client=172.31.2.181 -data-dir=/data/consul -ui -node=172.31.2.181&

#join加入已有consul集群,不用指定server因为server已经起来,ui也不用加
node2:
root@prometheus-node2:~# nohup consul agent -bind=172.31.2.182 -client=172.31.2.182 -data-dir=/data/consul -node=172.31.2.182 -join=172.31.2.181&

node3:
root@prometheus-node3:~# nohup consul agent -bind=172.31.2.183 -client=172.31.2.183 -data-dir=/data/consul -node=172.31.2.183 -join=172.31.2.181&

#启动后查看监听端口8500看看是不是有了
root@prometheus-node1:~# ss -tnl

#访问测试:   浏览器输入
172.31.2.181:8500
#services是已经注册的服务,nodes是consol的节点

#可以看下启动日志
root@prometheus-node1:~# cat nohup.out

consol页面

2.3.3:测试写入数据: (注册服务)

通过consul的API写入数据

#写其中一个地址就可以,它会进行同步的

#向consol注册3个node
#注册一个新的节点,check为consol会对服务进行状态监测,服务不可用会被踢掉,不在可用服务列进行展示,最后是consol的地址(写其中一个就可以)。命令在哪个服务器注册都行
~# curl -X PUT -d '{"id":"node-exporter181","name":"node-exporter181","address":"172.31.2.181","port":9100,"tags":["node-exporter"],"checks": [{"http": "http://172.31.2.181:9100/","interval":"5s"}]}' http://172.31.2.181:8500/v1/agent/service/register

~# curl -X PUT -d '{"id":"node-exporter182","name":"node-exporter182","address":"172.31.2.182","port":9100,"tags":["node-exporter"],"checks": [{"http": "http://172.31.2.182:9100/","interval":"5s"}]}' http://172.31.2.181:8500/v1/agent/service/register

~# curl -X PUT -d '{"id":"node-exporter183","name":"node-exporter183","address":"172.31.2.183","port":9100,"tags":["node-exporter"],"checks": [{"http": "http://172.31.2.183:9100/","interval":"5s"}]}' http://172.31.2.181:8500/v1/agent/service/register

在consol页面左侧的services会看到,先是红叉,后续监测通过会变绿色

#删除注册命令(不执行)
# curl --request PUT http://172.31.2.181:8500/v1/agent/service/deregister/node-exporter181

2.3.5:配置prometheus到consul发现服务:

#这里用k8s上的Prometheus,也可以用独立部署的Prometheus测试
root@ubuntu101:~/1.prometheus-case-files# vim case3-1-prometheus-cfg.yaml
...
    - job_name:consul
      honor_labels:true #保留原标签(采集的数据中的标签和prometheus本地标签发送冲突,使用采集数据标签)
      metrics_path: /metrics #指标路径,指发现完后,向新节点抓数据的路径
      scheme:http
      consul_sd_configs:    #指定consol服务的地址
        - server:172.31.2.181:8500
          services:[]    #要不要指定发现哪些service,不指定发现所有(一般不指定)
        - server:172.31.2.182:8500
          services:[]
        - server:172.31.2.183:8500
          services:[]
      relabel_configs:    #标签重写
      - source_labels:['__meta_consul_tags']
        target_label:'product'    #增加标签
      - source_labels:['__meta_consul_dc']
        target_label:'idc'
      - source_labels:['__meta_consul_service']
        regex:"consul"    #如果是consul的话就删掉(consul是自身的service)
        action:drop
        
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-1-prometheus-cfg.yaml

#把Prometheus删了重启下
root@ubuntu101:~/1.prometheus-case-files# kubectl delete -f case3-2-prometheus-deployment.yaml
root@ubuntu101:~/1.prometheus-case-files# kubectl apply -f case3-2-prometheus-deployment.yaml

#在grafana页面可以看到发现了consul的3个节点(就是从consul中拿的)

2.3.6:consul 服务注册与删除:

注册:
# curl -X PUT -d '{"id": "node-exporter103","name": "node-exporter103","address": "172.31.2.103","port":9100,"tags": ["node-exporter103"],"checks": [{"http": "http://172.31.2.103:9100/","interval": "5s"}]}' http://172.31.2.181:8500/v1/agent/service/register 

删除:
# curl --request PUT http://172.31.2.181:8500/v1/agent/service/deregister/node-exporter183

2.4:file_sd_configs: (仅作展示,一般用不上)

把Prometheus要发现的服务放到本地的文本文件中,让Prometheus每隔一段时间扫描文件里的内容

要修改的地址加入或删除在这个文件中,增删全在这个文件中进行维护,不用重启Prometheus服务了,会自动根据文件中的服务进行发现。但是得维护这样的文件。如果服务器比较多,这种方式不适合,文件手动改很容易出错,还不如使用consul。

2.4.1:编辑 sd_configs 文件:

root@prometheus-server1:/apps/prometheus# mkdir file_sd
root@prometheus-server1:/apps/prometheus# cd file_sd
root@prometheus-server1:/apps/prometheus/file_sd# vim sd_my_server.json
[
  { 
    "labels": {"job": "file_sd_my_server"}
    "targets": ["172.31.2.181:9100","172.31.2.182:9100","172.31.2.183:9100"]
  }
]

2.4.2:prometheus 调用 sd_configs:

root@prometheus-server1:/apps/prometheus# vim prometheus.yml 
- job_name: 'file_sd_my_server' 
    file_sd_configs
    - files:
      - /apps/prometheus/file_sd/sd_my_server.json
      refresh_interval: 10s #每隔多少时间做一次发现
      
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service

#看grafana控制台有没有生效

#修改上面的sd_my_server.json文件,Prometheus会自动发现并更新

file_sd_configs

2.5:DNS 服务发现 : (用的不多, 了解)

用/etc/hosts文件或者dns服务器解析都行

 

三:kube-state-metrics 组件介绍:

服务很小, 功能很多, k8s里监控pod重启, pod状态异常告警。支持很多种资源对象属性指标统计, 统计资源对象的状态

    Kube-state-metrics:通过监听 API Server 生成有关资源对象的状态指标,比如Deployment、Node、Pod,
需要注意的是kube-state-metrics的使用场景不是用于监控对方是否存活,而是用于周期性获取目标对象
的metrics 指标数据并在 web 界面进行显示或被 prometheus 抓取(如 pod 的状态是 running 还是
Terminating、pod 的创建时间等),目前的 kube-state-metrics 收集的指标数据可参见官方的文档,
https://github.com/kubernetes/kube-state-metrics/tree/master/docs, 并不会存储这些指标数据,所
以我们可以使用Prometheus 来抓取这些数据然后存储,主要关注的是业务相关的一些元数据,比如
Deployment、Pod、副本状态等,调度了多少个 replicas?现在可用的有几个?多少个 Pod 是
running/stopped/terminated 状态?Pod 重启了多少次? 目前有多少job在运行中。

官方的定义:
kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects.

Github: https://github.com/kubernetes/kube-state-metrics

镜像: https://hub.docker.com/r/bitnami/kube-state-metrics https://quay.io/repository/coreos/kube-state-metrics?tag=latest&tab=tags

#指标 https://xie.infoq.cn/article/9e1fff6306649e65480a96bb1

3.1:部署kube-state-metrics:

#github下载 kube-state-metrics-2.18.0.zip,拷贝到下面的路径中
root@ubuntu101:~/1.prometheus-case-files# unzip kube-state-metrics-2.18.0.zip
root@ubuntu101:~/1.prometheus-case-files# cd kube-state-metrics-2.18.0/examples/standard/
#注意镜像,换成国内镜像
root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# vim deployment.yaml
...
    spec:
      automountServiceAccountToken: true
      containers:
        #- image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.18.0
        - image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kube-state-metrics:v2.18.0

#安装,如果显示Kustomization没装,再执行一次即可
root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# kubectl apply -f .

root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# kubectl get pod -n kube-system 
NAME                                       READY   STATUS    RESTARTS       AGE
...
kube-state-metrics-77456d48bc-q22d2        1/1     Running   0              25s

#新建service,如Prometheus在k8s外面,去抓这里面的指标,就把这个指标暴露下(k8s里面Prometheus走service)
root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# vim node-port-svc.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    prometheus.io/scrape: 'true'
  name: kube-state-metrics-nodeport
  namespace: kube-system
  labels:
    app: kube-state-metrics
spec:
  type: NodePort
  ports:
  - name: kube-state-metrics
    port: 8080
    targetPort: 8080
    nodePort: 31666
    protocol: TCP
  selector:
    #app: kube-state-metrics
    app.kubernetes.io/name: kube-state-metrics
    
root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# kubectl apply -f node-port-svc.yaml

root@ubuntu101:~/1.prometheus-case-files/kube-state-metrics-2.18.0/examples/standard# kubectl get svc -n kube-system
NAME                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  
kube-dns                      ClusterIP   10.100.0.2      <none>        53/UDP,53/TCP,9153/TCP   
kube-state-metrics            ClusterIP   None            <none>        8080/TCP,8081/TCP        
kube-state-metrics-nodeport   NodePort    10.100.91.211   <none>        8080:31666/TCP     

#访问31666 获取kube-state-metrics数据
http://10.0.0.101:31666/metrics

3.3:prometheus 采集数据

#k8s里面的Prometheus或者外面的Prometheus都行
root@prometheus-server1:/apps/prometheus# vim prometheus.yml 
  - job_name: "kube-state-metrics" 
    honor_timestamps: true
    static_configs: 
    - targets: ["172.31.7.111:31666"] 
    metric_relabel_configs: 
    - target_label: cluster
      replacement: myserver-k8s    #加个标签,可加可不加
      
root@prometheus-server1:/apps/prometheus# systemctl restart prometheus.service

#Prometheus网页看下是否能收集到这些指标

验证 prometheus 状态

3.5:grafana 导入模板

grafana导入模板 13332 (有些老,指标无法识别)

grafana导入模板 21742

grafana导入模板 14518 (这个比较全, 比较好)

 

四:监控扩展:

基于第三方 exporter 实现对目的服务的监控

4.1:监控 Java 服务(tomcat)@

https://github.com/nlighten/tomcat_exporter

监控 tomcat 的活跃连接数、堆栈内存等信息:

# TYPE tomcat_connections_active_total gauge
tomcat_connections_active_total{name="http-nio-8080",} 2.0

# TYPE jvm_memory_bytes_used gauge
jvm_memory_bytes_used{area="heap",} 2.4451216E7

如果是spring的话,也有相应的jar包,让研发把指标收集下导出来就行,这时候会用到各种exporter

4.1.1:自定义镜像:

#重新打镜像(把jar包放进去,如果是spring一般是由研发放的)
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/tomcat-image# ll
total 473760
drwxr-xr-x 3 root root      4096 May  7 14:15 ./
drwxr-xr-x 5 root root        71 May  7 14:15 ../
-rw-r--r-- 1 root root       692 May  7 14:15 Dockerfile
-rw-r--r-- 1 root root       253 May  7 14:15 build-command.sh
-rw-r--r-- 1 root root      3405 May  7 14:15 metrics.war
drwxr-xr-x 2 root root        23 May  7 14:15 myapp/
-rw-r--r-- 1 root root       175 May  7 14:15 myapp.tar.gz
-rw-r--r-- 1 root root       125 May  7 14:15 run_tomcat.sh
-rw-r--r-- 1 root root      7592 May  7 14:15 server.xml
-rw-r--r-- 1 root root     59477 May  7 14:15 simpleclient-0.8.0.jar
-rw-r--r-- 1 root root      5840 May  7 14:15 simpleclient_common-0.8.0.jar
-rw-r--r-- 1 root root     21767 May  7 14:15 simpleclient_hotspot-0.8.0.jar
-rw-r--r-- 1 root root      7104 May  7 14:15 simpleclient_servlet-0.8.0.jar
-rw-r--r-- 1 root root 484967424 May  7 14:15 tomcat-8.5.73-jdk11-corretto.tar.gz
-rw-r--r-- 1 root root     19582 May  7 14:15 tomcat_exporter_client-0.0.12.jar
-rw-r--r-- 1 root root      3405 May  7 14:15 tomcat_exporter_servlet-0.0.12.war

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/tomcat-image# vim Dockerfile
#FROM tomcat:8.5.73-jdk11-corretto 
#FROM tomcat:8.5.73
FROM registry.cn-hangzhou.aliyuncs.com/zhangshijie/tomcat:8.5.73

LABEL maintainer="jack 2973707860@qq.com"
ADD server.xml /usr/local/tomcat/conf/server.xml

RUN mkdir /data/tomcat/webapps -p
ADD myapp /data/tomcat/webapps/myapp    #放java服务
ADD metrics.war /data/tomcat/webapps    #提供metrics页面的,把指标暴露出来
ADD simpleclient-0.8.0.jar  /usr/local/tomcat/lib/    #下面这些都是提供指标的jar包
ADD simpleclient_common-0.8.0.jar /usr/local/tomcat/lib/
ADD simpleclient_hotspot-0.8.0.jar /usr/local/tomcat/lib/
ADD simpleclient_servlet-0.8.0.jar /usr/local/tomcat/lib/
ADD tomcat_exporter_client-0.0.12.jar /usr/local/tomcat/lib/

#ADD run_tomcat.sh /apps/tomcat/bin/
EXPOSE 8080 8443 8009
#CMD ["/apps/tomcat/bin/catalina.sh","run"]
#CMD ["/apps/tomcat/bin/run_tomcat.sh"]

4.1.2: 构建并测试镜像

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/tomcat-image# vim build-command.sh
#!/bin/bash
nerdctl build -t harbor.myarchitect.online/myserver/tomcat-app1:v1 .
nerdctl push harbor.myarchitect.online/myserver/tomcat-app1:v1
#docker build -t harbor.linuxarchitect.io/magedu/tomcat-app1:v1 .
#docker push  harbor.linuxarchitect.io/magedu/tomcat-app1:v1

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

#测试下
root@harbor:~# docker run -it --rm -p 8080:8080 harbor.myarchitect.online/myserver/tomcat-app1:v1

#访问下,看看有没有这个指标
10.0.0.106:8080/metrics
#web服务地址
10.0.0.106:8080/myapp

4.1.3:创建 pod 并验证:

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# ls
tomcat-deploy.yaml  tomcat-svc.yaml

#基于pod自动发现
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# vim tomcat-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  namespace: myserver
spec:
  selector:
    matchLabels:
     app: tomcat
  replicas: 1 # tells deployment to run 2 pods matching the template
  template: # create pods using pod definition in this template
    metadata:
      labels:
        app: tomcat
      annotations:    #加上注解,k8s可以直接发现
        prometheus.io/scrape: 'true'
        prometheus.io/port: "8080"
    spec:
      containers:
      - name: tomcat
        image: harbor.myarchitect.online/myserver/tomcat-app1:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        securityContext:
          privileged: true
          
#基于service自动发现
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# vim tomcat-svc.yaml
kind: Service  #service 类型
apiVersion: v1
metadata:
  annotations:
    prometheus.io/scrape: 'true'
    prometheus.io/port: "8080"
  name: tomcat-service
  namespace: myserver
spec:
  selector:
    app: tomcat
  ports:
  - nodePort: 31080
    port: 80
    protocol: TCP
    targetPort: 8080
  type: NodePort
  
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# kubectl apply -f tomcat-deploy.yaml -f tomcat-svc.yaml

#查看
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# kubectl get pods -n myserver -o wide
NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE       
tomcat-deployment-798df5459d-mg2gz   1/1     Running   0          2m58s   10.200.218.167   10.0.0.104 
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/1.tomcat/yaml# curl 10.200.218.167:8080/metrics/
# HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously.
...

#promethues上查看,会看到pod和service被自动发现了
http://10.0.0.101:39090/targets


#若是k8s外的Prometheus要发现的话,就配置下,可通过nodeport之类的方式去获取(但只能获取到svc其中一个)
#因为k8s外面Prometheus连接k8s里网络问题,可以通过联邦,每个k8s里部个Prometheus,外面Prometheus采集所有k8s里的Prometheus数据
- job_name: "tomcat-monitor-metrics"
  static_configs: 
    - targets: ["172.31.7.111:31080"]
# systemctl restart prometheus.service

4.1.5:grafana 导入模

grafana地址:    #admin/admin
http://10.0.0.101:33000/

#这里导入现成的模板文件,选下数据源
模板文件位置:
1.prometheus-case-files-y99-v4.zip\1.prometheus-case-files\app-monitor-case\1.tomcat\template\tomcat-dashboard.json

4.2:监控 Redis:

通过 redis_exporter 监控 redis 服务状态。

https://github.com/oliver006/redis_exporter

4.2.1:部署 Redis

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# ls
redis-deployment.yaml  redis-exporter-svc.yaml  redis-redis-svc.yaml

root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# vim redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
      annotations:
        prometheus.io/scrape: 'true'
        prometheus.io/port: "9121"
    spec:
      containers:
      - name: redis
        image: redis:4.0.14    #只提供redis info,不符合Prometheus指标格式
        command: ["/usr/local/bin/docker-entrypoint.sh"]
        args: ["--requirepass","123456"]
        resources:
          requests:
            cpu: 200m
            memory: 156Mi
        ports:
        - containerPort: 6379
      - name: redis-exporter    #边车容器
        image: oliver006/redis_exporter:latest    #把redis数据导出,序列化成Prometheus指标格式
        command: ["/redis_exporter"]
        args:
          - "-redis.addr=redis://localhost:6379"
          - "-redis.password=123456"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
        ports:
        - containerPort: 9121    #Prometheus抓这个端口数据
        
        
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# kubectl apply -f redis-deployment.yaml

#获取指标数据
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# curl 10.200.165.32:9121/metrics

#promethues可以看到已自动发现pod(service没创建,所以通过service发现pod方式无法发现)
http://10.0.0.101:39090/targets

#通过svc自动发现endpoints(测试的,暴露Prometheus端口,没有暴露redis数据端口)
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# vim redis-exporter-svc.yaml
kind: Service  #service 类型
apiVersion: v1
metadata:
  annotations:
    prometheus.io/scrape: 'true'
    prometheus.io/port: "9121"
  name: redis-exporter-service
  namespace: magedu
spec:
  type: NodePort
  ports:
    - port: 9121
      targetPort: 9121
      nodePort: 39121
      protocol: TCP
  selector:
    app: redis
    
#promethues可以看到已自动发现
http://10.0.0.101:39090/targets

#数据端口service,不需要做监控,所以没有配置Prometheus声明
root@ubuntu101:~/1.prometheus-case-files/app-monitor-case/2.redis/yaml# vim redis-redis-svc.yaml
kind: Service  #service 类型
apiVersion: v1
metadata:
#  annotations:
#    prometheus.io/scrape: 'false'
  name: redis-redis-service
  namespace: magedu
spec:
  type: NodePort
  ports:
    - port: 6379
      targetPort: 6379
      nodePort: 36379
      protocol: TCP
  selector:
    app: redis

#注意上面的pod自动发现和service自动发现ep,二选一,否则grafana数据展示会重复导致数据数值翻倍
#拿到指标后,就可以在grafana上导入模板,展示redis当前的指标,这里用本地模板文件,或者使用模板id: 17507
1.prometheus-case-files-y99-v4.zip\1.prometheus-case-files\app-monitor-case\2.redis\redis-dashboard\redis-dashboard.json

redis-grafana

更多的exporter在Prometheus官网找

grafana有些dashboard显示要装插件,要进入grafana里执行命令安装: grafana-cli plugins install ... ,在线装,不一定装的上

有时候网络不行。可以grafana官网下载插件到grafana插件文件夹中

posted @ 2026-07-05 20:17  战斗小人  阅读(8)  评论(0)    收藏  举报