实战:prometheus如何监控k8s集群里的node资源-2022.5

优采云 发布时间: 2022-05-03 04:14

  实战:prometheus如何监控k8s集群里的node资源-2022.5

  

  目录

  关于我

  最后

  实验环境

  k8s:v1.22.2(1 master,2 node)<br />containerd: v1.5.5<br />prometneus: docker.io/prom/prometheus:v2.34.0<br />

  实验软件

  链接:提取码:au4n2022.4.30-p8s监控k8s集群node资源-code

  

  image-203369前置条件

  关于如何将prometheus应用部署到k8s环境里,请查看我的另一篇文章,获取完整的部署方法!。

  

  image-230811

  

  image-222637基础知识

  监控集群节点

  前面我们和大家学习了怎样用 Promethues 来监控 Kubernetes 集群中的应用,但是对于 Kubernetes 集群本身的监控也是非常重要的,我们需要时时刻刻了解集群的运行状态。

  对于集群的监控一般我们需要考虑以下几个方面:

  Kubernetes 集群的监控方案目前主要有以下几种方案:

  不过 kube-state-metrics 和 metrics-server 之间还是有很大不同的,二者的主要区别如下:

  要监控节点其实我们已经有很多非常成熟的方案了,比如 Nagios、zabbix,甚至我们自己来收集数据也可以。我们这里通过 Prometheus 来采集节点的监控指标数据,可以通过 node_exporter 来获取,顾名思义,node_exporter 就是抓取用于采集服务器节点的各种运行指标,目前 node_exporter 支持几乎所有常见的监控点,比如 conntrack,cpu,diskstats,filesystem,loadavg,meminfo,netstat 等,详细的监控点列表可以参考其 Github 仓库。

  我们可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个这样的 Pod,如果我们从集群中删除或者添加节点后,也会进行自动扩展。

  1、创建daemonset资源

  [root@master1 p8s-example]#pwd/root/p8s-example[root@master1 p8s-example]#vim prometheus-node-exporter.yaml

  # prometheus-node-exporter.yaml<br />apiVersion: apps/v1<br />kind: DaemonSet<br />metadata:<br /> name: node-exporter<br /> namespace: monitor<br /> labels:<br /> app: node-exporter<br />spec:<br /> selector:<br /> matchLabels:<br /> app: node-exporter<br /> template:<br /> metadata:<br /> labels:<br /> app: node-exporter<br /> spec:<br /> hostPID: true<br /> hostIPC: true<br /> hostNetwork: true #因为这里用的是hostNetwortk模式,所以后面就不需要创建svc了!<br /> nodeSelector:<br /> kubernetes.io/os: linux<br /> containers:<br /> - name: node-exporter<br /> image: prom/node-exporter:v1.3.1<br /> args:<br /> - --web.listen-address=$(HOSTIP):9100<br /> - --path.procfs=/host/proc<br /> - --path.sysfs=/host/sys<br /> - --path.rootfs=/host/root<br /> - --no-collector.hwmon # 禁用不需要的一些采集器<br /> - --no-collector.nfs<br /> - --no-collector.nfsd<br /> - --no-collector.nvme<br /> - --no-collector.dmi<br /> - --no-collector.arp<br /> - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/containerd/.+|/var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/)<br /> - --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)$<br /> ports:<br /> - containerPort: 9100<br /> env:<br /> - name: HOSTIP<br /> valueFrom:<br /> fieldRef:<br /> fieldPath: status.hostIP #Downward API<br /> resources:<br /> requests:<br /> cpu: 150m<br /> memory: 180Mi<br /> limits:<br /> cpu: 150m<br /> memory: 180Mi<br /> securityContext:<br /> runAsNonRoot: true<br /> runAsUser: 65534<br /> volumeMounts:<br /> - name: proc<br /> mountPath: /host/proc<br /> - name: sys<br /> mountPath: /host/sys<br /> - name: root<br /> mountPath: /host/root<br /> mountPropagation: HostToContainer<br /> readOnly: true<br /> tolerations:<br /> - operator: "Exists"<br /> volumes:<br /> - name: proc<br /> hostPath:<br /> path: /proc<br /> - name: dev<br /> hostPath:<br /> path: /dev<br /> - name: sys<br /> hostPath:<br /> path: /sys<br /> - name: root<br /> hostPath:<br /> path: /<br />

  :warning: 注意:

  

  image-225376

  由于我们要获取到的数据是主机的监控指标数据,而我们的 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 <br />daemonset.apps/node-exporter created<br /><br />[root@master1 p8s-example]#kubectl get pods -nmonitor -l app=node-exporter -o wide<br />NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES<br />node-exporter-6z7dx 1/1 Running 0 39s 172.29.9.52 node1 <br />node-exporter-bbsh6 1/1 Running 0 39s 172.29.9.51 master1 <br />node-exporter-lm46b 1/1 Running 0 39s 172.29.9.53 node2 <br />

  

  image-225819

  部署完成后,我们可以看到在几个节点上都运行了一个 Pod,由于我们指定了 hostNetwork=true,所以在每个节点上就会绑定一个端口 9100。

  ➜ curl 172.29.9.51:9100/metrics<br />...<br />node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/aefe8b1b63c3aa5f27766053ec817415faf8f6f417bb210d266fef0c2da64674/shm"} 1<br />node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/c8652ca72230496038a07e4fe4ee47046abb5f88d9d2440f0c8a923d5f3e133c/shm"} 1<br />node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev"} 0<br />node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev/shm"} 0<br />...<br />

  

  image-255921

  当然如果你觉得上面的手动安装方式比较麻烦,我们也可以使用 Helm 的方式来安装:

  helm upgrade --install node-exporter --namespace monitor stable/prometheus-node-exporter<br />

  3、服务发现

  由于我们这里每个节点上面都运行了 node-exporter 程序,如果我们通过一个 Service 来将数据收集到一起用静态配置的方式配置到 Prometheus 去中,就只会显示一条数据,我们得自己在指标数据中去过滤每个节点的数据。当然我们也可以手动的把所有节点用静态的方式配置到 Prometheus 中去,但是以后要新增或者去掉节点的时候就还得手动去配置。那么有没有一种方式可以让 Prometheus 去自动发现我们节点的 node-exporter 程序,并且按节点进行分组呢?这就是 Prometheus 里面非常重要的服务发现功能了。

  在 Kubernetes 下,Promethues 通过与 Kubernetes API 集成,主要支持5中服务发现模式,分别是:Node、Service、Pod、Endpoints、Ingress。

  [root@master1 p8s-example]# kubectl get node<br />NAME STATUS ROLES AGE VERSION<br />master1 Ready control-plane,master 181d v1.22.2<br />node1 Ready 181d v1.22.2<br />node2 Ready 181d v1.22.2<br />

  1.编写prometheus配置文件

  [root@master1 p8s-example]#pwd/root/p8s-example[root@master1 p8s-example]#vim prometheus-cm.yaml

  # prometheus-cm.yaml<br />apiVersion: v1<br />kind: ConfigMap<br />metadata:<br /> name: prometheus-config<br /> namespace: monitor<br />data:<br /> prometheus.yml: |<br /> global:<br /> scrape_interval: 15s<br /> scrape_timeout: 15s<br /><br /> scrape_configs:<br /> - job_name: 'prometheus'<br /> static_configs:<br /> - targets: ['localhost:9090']<br /><br /> - job_name: 'coredns'<br /> static_configs:<br /> - targets: ['10.244.0.8:9153', '10.244.0.10:9153']<br /><br /> - job_name: 'redis'<br /> static_configs:<br /> - targets: ['redis:9121']<br /><br /> - job_name: 'nodes'<br /> kubernetes_sd_configs:<br /> - role: node<br />

  

  image-207526

  通过指定 kubernetes_sd_configs 的模式为 node,Prometheus 就会自动从 Kubernetes 中发现所有的 node 节点并作为当前 job 监控的目标实例,发现的节点 /metrics 接口是默认的 kubelet 的 HTTP 接口。

  2.部署prometheus配置文件

  [root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml <br />configmap/prometheus-config configured<br /><br />[root@master1 p8s-example]#kubectl exec prometheus-698b6858c9-5xgsm -nmonitor -- cat /etc/prometheus/prometheus.yml<br />

  可以看到prometheus pod的配置文件已经被更新了:

  

  image-244290

  [root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"<br />

  

  image-237176

  看了下prometheus pod日志没什么报错:

  

  image-200878

  [root@master1 p8s-example]#vim prometheus-rbac.yaml

  

  image-254398

  

  image-216722

  

  image-242449

  

  image-205240

  server returned HTTP status 400 Bad Request<br />

  这个是因为 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 的标签:

  

  prometheus webui relabel before

  

  image-202697

  [root@master1 p8s-example]#pwd/root/p8s-example[root@master1 p8s-example]#vim prometheus-cm.yaml

  # prometheus-cm.yaml<br />apiVersion: v1<br />kind: ConfigMap<br />metadata:<br /> name: prometheus-config<br /> namespace: monitor<br />data:<br /> prometheus.yml: |<br /> global:<br /> scrape_interval: 15s<br /> scrape_timeout: 15s<br /><br /> scrape_configs:<br /> - job_name: 'prometheus'<br /> static_configs:<br /> - targets: ['localhost:9090']<br /><br /> - job_name: 'coredns'<br /> static_configs:<br /> - targets: ['10.244.0.8:9153', '10.244.0.10:9153']<br /><br /> - job_name: 'redis'<br /> static_configs:<br /> - targets: ['redis:9121']<br /><br /> - job_name: 'nodes'<br /> kubernetes_sd_configs:<br /> - role: node<br /> relabel_configs:<br /> - source_labels: [__address__]<br /> regex: '(.*):10250'<br /> replacement: '${1}:9100'<br /> target_label: __address__<br /> action: replace<br />

  

  image-242968

  这里就是一个正则表达式,去匹配 __address__ 这个标签,然后将 host 部分保留下来,port 替换成了 9100。

  更新configmap文件:

  [root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml <br />configmap/prometheus-config configured<br />

  

  image-257347

  [root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"<br />

  

  image-212315

  我们可以看到现在已经正常了。

  4.通过 labelmap 属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标数据的标签

  但是还有一个问题就是我们采集的指标数据 Label 标签就只有一个节点的 hostname,这对于我们在进行监控分组分类查询的时候带来了很多不方便的地方,要是我们能够将集群中 Node 节点的 Label 标签也能获取到就很好了。

  

  image-247415

  添加到prometheus-cm.yaml配置文件:

  [root@master1 p8s-example]#pwd/root/p8s-example[root@master1 p8s-example]#vim prometheus-cm.yaml

  ……<br />- job_name: 'kubernetes-nodes'<br /> kubernetes_sd_configs:<br /> - role: node<br /> relabel_configs:<br /> - source_labels: [__address__]<br /> regex: '(.*):10250'<br /> replacement: '${1}:9100'<br /> target_label: __address__<br /> action: replace<br /> - action: labelmap<br /> regex: __meta_kubernetes_node_label_(.+)<br />

  

  image-236755

  添加了一个 action 为 labelmap,正则表达式是 __meta_kubernetes_node_label_(.+) 的配置,这里的意思就是表达式中匹配都的数据也添加到指标数据的 Label 标签中去。

  [root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml <br />configmap/prometheus-config configured<br />

  

  image-256974

  [root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"<br />

  

  image-205683

  符合预期。

  对于 kubernetes_sd_configs 下面可用的元信息标签如下:

  关于 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

  ……<br />- job_name: 'kubelet'<br /> kubernetes_sd_configs:<br /> - role: node<br /> scheme: https<br /> tls_config:<br /> ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt<br /> insecure_skip_verify: true<br /> bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token<br /> relabel_configs:<br /> - action: labelmap<br /> regex: __meta_kubernetes_node_label_(.+)<br />

  

  image-205994

  但是这里需要特别注意的是这里必须使用 https 协议访问,这样就必然需要提供证书,我们这里是通过配置 insecure_skip_verify: true 来跳过了证书校验。但是除此之外,要访问集群的资源,还必须要有对应的权限才可以,也就是对应的 ServiceAccount 棒的 权限允许才可以,我们这里部署的 prometheus 关联的 ServiceAccount 对象前面我们已经提到过了,这里我们只需要将 Pod 中自动注入的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 和 /var/run/secrets/kubernetes.io/serviceaccount/token 文件配置上,就可以获取到对应的权限了。

  以下不影响,是可以出效果的:

  

  image-214497

  [root@master1 p8s-example]#kubectl apply -f prometheus-cm.yaml <br />configmap/prometheus-config configured<br />

  [root@master1 p8s-example]# curl -X POST "http://172.29.9.51:32700/-/reload"<br />

  现在我们再去更新下配置文件,执行 reload 操作,让配置生效,然后访问 Prometheus 的 Dashboard 查看 Targets 路径:

  

  image-251917

  现在可以看到我们上面添加的 kubernetes-kubelet 和 kubernetes-nodes 这两个 job 任务都已经配置成功了,而且二者的 Labels 标签都和集群的 node 节点标签保持一致了。

  现在我们就可以切换到 Graph 路径下面查看采集的一些指标数据了,比如查询 node_load1 指标:

  

  prometheus webui node load1

  我们可以看到将几个节点对应的 node_load1 指标数据都查询出来了。

  同样的,我们还可以使用 PromQL 语句来进行更复杂的一些聚合查询操作,还可以根据我们的 Labels 标签对指标数据进行聚合,比如我们这里只查询 node1 节点的数据,可以使用表达式 node_load1{instance="node1"} 来进行查询:

  

  prometheus webui node1 load1

  到这里我们就把 Kubernetes 集群节点使用 Prometheus 监控起来了,接下来我们再来和大家学习下怎样监控 Pod 或者 Service 之类的资源对象。

  关于我

  我的博客主旨:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线