实战:prometheus如何监控k8s集群里的node资源-2022.5.1(测试成功)
目录文章目录目录实验环境实验软件前置条件基础知识1、创建daemonset资源2、部署资源3、服务发现1.编写prometheus配置文件2.部署prometheus配置文件3.使用 Prometheus 提供的 `relabel_configs` 中的 `replace` 能力4.通过 `labelmap` 属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标
目录
文章目录
实验环境
k8s:v1.22.2(1 master,2 node)
containerd: v1.5.5
prometneus: docker.io/prom/prometheus:v2.34.0
实验软件
链接:https://pan.baidu.com/s/1GdxitBmmH6JaTmcg8kFn2w?pwd=au4n
提取码:au4n
2022.4.30-p8s监控k8s集群node资源-code
前置条件
- 有k8s环境;
- 已经把prometheus应用部署到k8s环境里;
关于如何将prometheus应用部署到k8s环境里
,请查看我的另一篇文章,获取完整的部署方法!。
https://blog.csdn.net/weixin_39246554/article/details/124498172?spm=1001.2014.3001.5501
基础知识
🍀 监控集群节点
前面我们和大家学习了怎样用 Promethues 来监控 Kubernetes 集群中的应用,但是对于 Kubernetes 集群本身的监控也是非常重要的,我们需要时时刻刻了解集群的运行状态。
对于集群的监控一般我们需要考虑以下几个方面:
- Kubernetes 节点的监控:比如节点的 cpu、load、disk、memory 等指标
- 内部系统组件的状态:比如 kube-scheduler、kube-controller-manager、kubedns/coredns 等组件的详细运行状态
- 编排级的 metrics:比如 Deployment 的状态、资源请求、调度和 API 延迟等数据指标
Kubernetes 集群的监控方案目前主要有以下几种方案:
- Heapster:Heapster 是一个集群范围的监控和数据聚合工具,以 Pod 的形式运行在集群中。 heapster 除了 Kubelet/cAdvisor 之外,我们还可以向 Heapster 添加其他指标源数据,比如 kube-state-metrics。需要注意的是 Heapster 已经被废弃了,后续版本中会使用 metrics-server 代替。
- cAdvisor:cAdvisor 是 Google 开源的容器资源监控和性能分析工具,它是专门为容器而生,本身也支持 Docker 容器。
- kube-state-metrics:kube-state-metrics 通过监听 API Server 生成有关资源对象的状态指标,比如 Deployment、Node、Pod。需要注意的是 kube-state-metrics 只是简单提供一个 metrics 数据,并不会存储这些指标数据,所以我们可以使用 Prometheus 来抓取这些数据然后存储。
- metrics-server:metrics-server 也是一个集群范围内的资源数据聚合工具,是 Heapster 的替代品。同样的,metrics-server 也只是显示数据,并不提供数据存储服务。
不过 kube-state-metrics 和 metrics-server 之间还是有很大不同的,二者的主要区别如下:
- kube-state-metrics 主要关注的是业务相关的一些元数据,比如 Deployment、Pod、副本状态等。
- metrics-server 主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标。
要监控节点其实我们已经有很多非常成熟的方案了,比如 Nagios、zabbix,甚至我们自己来收集数据也可以。我们这里通过 Prometheus 来采集节点的监控指标数据,可以通过 node_exporter 来获取,顾名思义,node_exporter
就是抓取用于采集服务器节点的各种运行指标,目前 node_exporter
支持几乎所有常见的监控点,比如 conntrack,cpu,diskstats,filesystem,loadavg,meminfo,netstat 等,详细的监控点列表可以参考其 Github 仓库。
我们可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个这样的 Pod,如果我们从集群中删除或者添加节点后,也会进行自动扩展。
1、创建daemonset资源
- 在部署
node-exporter
的时候有一些细节需要注意,如下资源清单文件:
[root@master1 p8s-example]#pwd
/root/p8s-example
[root@master1 p8s-example]#vim prometheus-node-exporter.yaml
# prometheus-node-exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitor
labels:
app: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true #因为这里用的是hostNetwortk模式,所以后面就不需要创建svc了!
nodeSelector:
kubernetes.io/os: linux
containers:
- name: node-exporter
image: prom/node-exporter:v1.3.1
args:
- --web.listen-address=$(HOSTIP):9100
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --path.rootfs=/host/root
- --no-collector.hwmon # 禁用不需要的一些采集器
- --no-collector.nfs
- --no-collector.nfsd
- --no-collector.nvme
- --no-collector.dmi
- --no-collector.arp
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/containerd/.+|/var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/)
- --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
ports:
- containerPort: 9100
env:
- name: HOSTIP
valueFrom:
fieldRef:
fieldPath: status.hostIP #Downward API
resources:
requests:
cpu: 150m
memory: 180Mi
limits:
cpu: 150m
memory: 180Mi
securityContext:
runAsNonRoot: true
runAsUser: 65534
volumeMounts:
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: root
mountPath: /host/root
mountPropagation: HostToContainer
readOnly: true
tolerations:
- operator: "Exists"
volumes:
- name: proc
hostPath:
path: /proc
- name: dev
hostPath:
path: /dev
- name: sys
hostPath:
path: /sys
- name: root
hostPath:
path: /
⚠️ 注意:
由于我们要获取到的数据是主机的监控指标数据,而我们的 node-exporter
是运行在容器中的,所以我们在 Pod 中需要配置一些 Pod 的安全策略,这里我们就添加了 hostPID: true
、hostIPC: true
、hostNetwork: true
3个策略,用来使用主机的 PID namespace
、IPC namespace
以及主机网络,这些 namespace 就是用于容器隔离的关键技术,要注意这里的 namespace 和集群中的 namespace 是两个完全不相同的概念。
另外我们还将主机的 /dev
、/proc
、/sys
这些目录挂载到容器中,这些因为我们采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如我们在使用 top
命令可以查看当前 cpu 使用情况,数据就来源于文件 /proc/stat
。使用 free
命令可以查看当前内存使用情况,其数据来源是来自 /proc/meminfo
文件。
另外由于我们集群使用的是 kubeadm
搭建的,所以如果希望 master 节点也一起被监控,则需要添加相应的容忍。
2、部署资源
- 然后直接创建上面的资源对象:
[root@master1 p8s-example]#kubectl apply -f prometheus-node-exporter.yaml
daemonset.apps/node-exporter created
[root@master1 p8s-example]#kubectl get pods -nmonitor -l app=node-exporter -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
node-exporter-6z7dx 1/1 Running 0 39s 172.29.9.52 node1 <none> <none>
node-exporter-bbsh6 1/1 Running 0 39s 172.29.9.51 master1 <none> <none>
node-exporter-lm46b 1/1 Running 0 39s 172.29.9.53 node2 <none> <none>
部署完成后,我们可以看到在几个节点上都运行了一个 Pod,由于我们指定了 hostNetwork=true
,所以在每个节点上就会绑定一个端口 9100。
- 我们可以通过这个端口去获取到监控指标数据:
➜ curl 172.29.9.51:9100/metrics
...
node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/aefe8b1b63c3aa5f27766053ec817415faf8f6f417bb210d266fef0c2da64674/shm"} 1
node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/c8652ca72230496038a07e4fe4ee47046abb5f88d9d2440f0c8a923d5f3e133c/shm"} 1
node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev"} 0
node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev/shm"} 0
...
当然如果你觉得上面的手动安装方式比较麻烦,我们也可以使用 Helm 的方式来安装:
helm upgrade --install node-exporter --namespace monitor stable/prometheus-node-exporter
3、服务发现
由于我们这里每个节点上面都运行了 node-exporter
程序,如果我们通过一个 Service 来将数据收集到一起用静态配置的方式配置到 Prometheus 去中,就只会显示一条数据,我们得自己在指标数据中去过滤每个节点的数据。当然我们也可以手动的把所有节点用静态的方式配置到 Prometheus 中去,但是以后要新增或者去掉节点的时候就还得手动去配置。那么有没有一种方式可以让 Prometheus 去自动发现我们节点的 node-exporter
程序,并且按节点进行分组呢?这就是 Prometheus 里面非常重要的服务发现功能了。
在 Kubernetes 下,Promethues 通过与 Kubernetes API 集成,主要支持5中服务发现模式,分别是:Node
、Service
、Pod
、Endpoints
、Ingress
。
- 我们通过 kubectl 命令可以很方便的获取到当前集群中的所有节点信息:
[root@master1 p8s-example]# kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane,master 181d v1.22.2
node1 Ready <none> 181d v1.22.2
node2 Ready <none> 181d v1.22.2
1.编写prometheus配置文件
- 但是要让 Prometheus 也能够获取到当前集群中的所有节点信息的话,我们就需要利用 Node 的服务发现模式,同样的,在
prometheus.yml
文件中配置如下的 job 任务即可:
[root@master1 p8s-example]#pwd
/root/p8s-example
[root@master1 p8s-example]#vim prometheus-cm.yaml
# prometheus-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitor
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_timeout: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'coredns'
static_configs:
- targets: ['10.244.0.8:9153', '10.244.0.10:9153']
- job_name: 'redis'
static_configs:
- targets: ['redis:9121']
- job_name: 'nodes'
kubernetes_sd_configs:
- role: node
通过指定 kubernetes_sd_configs
的模式为 node
,Prometheus 就会自动从 Kubernetes 中发现所有的 node 节点并作为当前 job 监控的目标实例,发现的节点 /metrics
接口是默认的 kubelet 的 HTTP 接口。
2.部署prometheus配置文件
- prometheus 的 ConfigMap 更新完成后,同样的我们执行 reload 操作,让配置生效:
[root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
[root@master1 p8s-example]#kubectl exec prometheus-698b6858c9-5xgsm -nmonitor -- cat /etc/prometheus/prometheus.yml
可以看到prometheus pod的配置文件已经被更新了:
- 此时就可以执行reload操作了:
[root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"
看了下prometheus pod日志没什么报错:
- 另外需要注意一点的是:之前这边是已经部署了rbac.yaml了的:
[root@master1 p8s-example]#vim prometheus-rbac.yaml
- 配置生效后,我们再去 prometheus 的 dashboard 中查看 Targets 是否能够正常抓取数据,访问
http://任意节点IP:32700
:
- 我们可以看到上面的
nodes
这个 job 任务已经自动发现了我们3个 node 节点,但是在获取数据的时候失败了,出现了类似于下面的错误信息:
server returned HTTP status 400 Bad Request
这个是因为 prometheus 去发现 Node 模式的服务的时候,访问的端口默认是 10250,而默认是需要认证的 https 协议才有权访问的,但实际上我们并不是希望让去访问10250端口的 /metrics
接口,而是 node-exporter
绑定到节点的 9100 端口,所以我们应该将这里的 10250
替换成 9100
,但是应该怎样替换呢?
3.使用 Prometheus 提供的 relabel_configs
中的 replace
能力
这里我们就需要使用到 Prometheus 提供的 relabel_configs
中的 replace
能力了,relabel
可以在 Prometheus 采集数据之前,通过 Target 实例的 Metadata
信息,动态重新写入 Label 的值。除此之外,我们还能根据 Target 实例的 Metadata
信息选择是否采集或者忽略该 Target 实例。比如我们这里就可以去匹配 __address__
这个 Label 标签,然后替换掉其中的端口,如果你不知道有哪些 Label 标签可以操作的话,可以在 Service Discovery
页面获取到相关的元标签,这些标签都是我们可以进行 Relabel 的标签:
- 现在我们来替换掉端口,修改 ConfigMap:
[root@master1 p8s-example]#pwd
/root/p8s-example
[root@master1 p8s-example]#vim prometheus-cm.yaml
# prometheus-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitor
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_timeout: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'coredns'
static_configs:
- targets: ['10.244.0.8:9153', '10.244.0.10:9153']
- job_name: 'redis'
static_configs:
- targets: ['redis:9121']
- job_name: 'nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
这里就是一个正则表达式,去匹配 __address__
这个标签,然后将 host 部分保留下来,port 替换成了 9100。
- 现在我们重新更新配置文件,执行 reload 操作,然后再去看 Prometheus 的 Dashboard 的 Targets 路径下面 kubernetes-nodes 这个 job 任务是否正常了:
更新configmap文件:
[root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
- 执行reload操作:
[root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"
- 查看prometheus web界面:
我们可以看到现在已经正常了。
4.通过 labelmap
属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标数据的标签
但是还有一个问题就是我们采集的指标数据 Label 标签就只有一个节点的 hostname,这对于我们在进行监控分组分类查询的时候带来了很多不方便的地方,要是我们能够将集群中 Node 节点的 Label 标签也能获取到就很好了。
- 这里我们可以通过
labelmap
这个属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标数据的标签:
添加到prometheus-cm.yaml
配置文件:
[root@master1 p8s-example]#pwd
/root/p8s-example
[root@master1 p8s-example]#vim prometheus-cm.yaml
……
- job_name: 'kubernetes-nodes'
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_(.+)
添加了一个 action 为 labelmap
,正则表达式是 __meta_kubernetes_node_label_(.+)
的配置,这里的意思就是表达式中匹配都的数据也添加到指标数据的 Label 标签中去。
- 更新文件,稍等一会儿执行reload操作:
[root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
- 执行reload操作:
[root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"
- 查看prometheus web界面:
符合预期。
🍀 对于 kubernetes_sd_configs
下面可用的元信息标签如下:
__meta_kubernetes_node_name
:节点对象的名称_meta_kubernetes_node_label
:节点对象中的每个标签_meta_kubernetes_node_annotation
:来自节点对象的每个注释_meta_kubernetes_node_address
:每个节点地址类型的第一个地址(如果存在)
关于 kubernets_sd_configs 更多信息可以查看官方文档:kubernetes_sd_config
5.把 kubelet 的监控任务也一并配置上
🍀 另外由于 kubelet 也自带了一些监控指标数据,就上面我们提到的 10250 端口,所以我们这里也把 kubelet 的监控任务也一并配置上:
添加到prometheus-cm.yaml
配置文件:
[root@master1 p8s-example]#pwd
/root/p8s-example
[root@master1 p8s-example]#vim prometheus-cm.yaml
……
- job_name: 'kubelet'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
但是这里需要特别注意的是这里必须使用 https
协议访问,这样就必然需要提供证书,我们这里是通过配置 insecure_skip_verify: true
来跳过了证书校验。但是除此之外,要访问集群的资源,还必须要有对应的权限才可以,也就是对应的 ServiceAccount 棒的 权限允许才可以,我们这里部署的 prometheus 关联的 ServiceAccount 对象前面我们已经提到过了,这里我们只需要将 Pod 中自动注入的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
和 /var/run/secrets/kubernetes.io/serviceaccount/token
文件配置上,就可以获取到对应的权限了。
以下不影响,是可以出效果的:
- 更新文件,稍等一会儿执行reload操作:
[root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
- 执行reload操作:
[root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"
- 验证:
现在我们再去更新下配置文件,执行 reload 操作,让配置生效,然后访问 Prometheus 的 Dashboard 查看 Targets 路径:
现在可以看到我们上面添加的 kubernetes-kubelet
和 kubernetes-nodes
这两个 job 任务都已经配置成功了,而且二者的 Labels 标签都和集群的 node 节点标签保持一致了。
现在我们就可以切换到 Graph 路径下面查看采集的一些指标数据了,比如查询 node_load1 指标:
我们可以看到将几个节点对应的 node_load1
指标数据都查询出来了。
同样的,我们还可以使用 PromQL
语句来进行更复杂的一些聚合查询操作,还可以根据我们的 Labels 标签对指标数据进行聚合,比如我们这里只查询 node1
节点的数据,可以使用表达式 node_load1{instance="node1"}
来进行查询:
到这里我们就把 Kubernetes 集群节点使用 Prometheus 监控起来了,接下来我们再来和大家学习下怎样监控 Pod 或者 Service 之类的资源对象。
关于我
我的博客主旨:
- 排版美观,语言精炼;
- 文档即手册,步骤明细,拒绝埋坑,提供源码;
- 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!
-
个人微信二维码:x2675263825 (舍得), qq:2675263825。
-
个人微信公众号:《云原生架构师实战》
-
个人csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
-
个人已开源干货😘
不服来怼:宇宙中最好用的云笔记 & 其他开源干货:https://www.yuque.com/go/doc/73723298?#
-
个人网站:(计划ing)
最后
好了,关于prometheus如何监控k8s集群里的node资源实验就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!
联系本人帮您解决问题,让我们一起进步!
-
个人微信二维码:x2675263825 (舍得), qq:2675263825。
[外链图片转存中…(img-KBC2XeYD-1651363587257)]
-
个人微信公众号:《云原生架构师实战》
[外链图片转存中…(img-iaEKmzjY-1651363587258)]
-
个人csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
[外链图片转存中…(img-9cyojvKc-1651363587259)]
-
个人已开源干货😘
不服来怼:宇宙中最好用的云笔记 & 其他开源干货:https://www.yuque.com/go/doc/73723298?#
[外链图片转存中…(img-gooNTfyB-1651363587259)]
[外链图片转存中…(img-1xRKMXCr-1651363587260)]
-
个人网站:(计划ing)
最后
好了,关于prometheus如何监控k8s集群里的node资源实验就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!
更多推荐
所有评论(0)