云原生k8s10 pushgateway,prometheus Federation(联邦集群),Prometheus与Exporter安全认证,手动k8s部署Prometheus一套,Prometheus自动发现,relabel机制与语法,kube-state-metrics,监控JVM和redis
pushgateway 简介:
pushgateway通常用于临时的指标数据收集。 pushgateway不支持数据拉取(pull模式),需要客户端主动将数据推送给pushgateway。 #pushgateway默认会把数据存在内存里,一重启数据就没了 pushgateway可以单独运行在一个节点,然后需要自定义监控脚本把需要监控的主动推送给pushgateway的API接口,然后pushgateway再等待prometheus server抓取数据,即 pushgateway本身没有任何抓取监控数据的功能,目前pushgateway只能被动的等待数据从客户端进行推送。 --persistence.file="" #数据保存的文件,默认只保存在内存中 --persistence.interval=5m #数据持久化的间隔时间(每隔多久往上面保存的文件做数据持久化)

部署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进行绘图了

客户端推送多条数据-方式一:
#对应地址: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主要负责抓取指标,如果数据量大,grafana从它这查数据,会有性能问题。核心Prometheus可以写入victory数据库,grafana直接读victory数据库的数据而非通过核心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联邦节点加的

grafana 验证数据(16098)

这是扩展功能,一般用不上; 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已有数据源,要修改数据源的认证)

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
为了了解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:
#可以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。可以单独部署一个,如上所示,自己部署的更好管理些
#和二进制安装效果效果相同,单机用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/
#可以使用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)是响应延迟时间,决定了性能

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 中部署的目标资源.
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抓取后序列化后的指标

为了更好的识别监控指标,便于后期调用数据匹配、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
source_labels:源标签,没有经过 relabel 处理之前的标签名字 target_label:通过 action 处理之后生成新的标签名字(不删除原有旧标签) #保留情况没有这个标签,看action怎么做 regex:自定义的值或正则表达式匹配,功能是用于匹配源标签的值 replacement:通过分组替换后标签(target_label)对应的/()/() $1:$2 #类似对括号内正则,通过$1,$2进行引用(标签分组引用)
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所有标签名称,其它匹配的标签都将从标签集中删除
#测试删掉下面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
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
node #node节点 service #发现service pod #通过pod注解发现pod endpoints #基于svc注解发现endpoints(pod),有的场景pod不一定都有svc Endpointslice #对endpoint进行切片 ingress #发现ingress
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:
#对应被监控项上的注解如下: 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.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匹配抓取数据
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 #另一种方式不在这指定,在发现时通过正则匹配,属于先发现后过滤,把发现后的结果丢弃,不如上面直接指定名称空间去发现好
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_(.+) #加上前缀 #匹配的目的数据:

# 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
# 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
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.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
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并授权。
这个账号是给服务发现使用的,去使用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:
#这里有的通,有的不通。像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基于第三方的服务发现实现方式
consul方式: 如果服务能注册到consul中,Prometheus通过consul读取已经注册的服务并对他们进行指标的抓取
2.3:consul_sd_configs:
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

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
#这里用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中拿的)
注册: # 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
把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"] } ]
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会自动发现并更新

用/etc/hosts文件或者dns服务器解析都行
服务很小, 功能很多, 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
#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网页看下是否能收集到这些指标

3.5:grafana 导入模板
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
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"]
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
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
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

更多的exporter在Prometheus官网找
grafana有些dashboard显示要装插件,要进入grafana里执行命令安装: grafana-cli plugins install ... ,在线装,不一定装的上
有时候网络不行。可以grafana官网下载插件到grafana插件文件夹中
浙公网安备 33010602011771号