服务发现¶
由于我们这里每个节点上面都运行了 node-exporter
程序,当然我们也可以手动的把所有节点用静态的方式配置到 Prometheus 中去,但是以后要新增或者去掉节点的时候就还得手动去配置,那么有没有一种方式可以让 Prometheus 去自动发现我们节点的 node-exporter
程序,并且按节点进行分组呢?这就是 Prometheus 里面非常重要的服务发现功能了。
节点发现¶
在 Kubernetes 下,Promethues 通过与 Kubernetes API 集成,主要支持 5 中服务发现模式,分别是:Node
、Service
、Pod
、Endpoints
、Ingress
。
我们通过 kubectl 命令可以很方便的获取到当前集群中的所有节点信息:
☸ ➜ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane,master 55d v1.22.2
node1 Ready <none> 55d v1.22.2
node2 Ready <none> 55d v1.22.2
但是要让 Prometheus 也能够获取到当前集群中的所有节点信息的话,我们就需要利用 Node 的服务发现模式,同样的,在 prometheus.yml
文件中配置如下的 job 任务即可:
- job_name: "nodes"
kubernetes_sd_configs:
- role: node
通过指定 kubernetes_sd_configs
的模式为node
,Prometheus 就会自动从 Kubernetes 中发现所有的 node 节点并作为当前 job 监控的目标实例,发现的节点 /metrics
接口是默认的 kubelet 的 HTTP 接口。
prometheus 的 ConfigMap 更新完成后,同样的我们执行 reload 操作,让配置生效:
☸ ➜ kubectl apply -f kubectl apply -f https://p8s.io/docs/k8s/manifests/prometheus/config-4.yaml
# 隔一会儿执行reload操作
☸ ➜ curl -X POST "http://10.244.2.46:9090/-/reload"
配置生效后,我们再去 prometheus 的 dashboard 中查看 Targets 是否能够正常抓取数据:
我们可以看到上面的 nodes
这个 job 任务已经自动发现了我们 3 个 node 节点,但是在获取数据的时候失败了,出现了类似于下面的错误信息:
server returned HTTP status 400 Bad Request
这个是因为 prometheus 去发现 Node 模式的服务的时候,访问的端口默认是 10250,而默认是需要认证的 https 协议才有权访问的,但实际上我们并不是希望让去访问 10250 端口的 /metrics
接口,而是 node-exporter
绑定到节点的 9100 端口,所以我们应该将这里的 10250
替换成 9100
,但是应该怎样替换呢?
relabel¶
这里我们就需要使用到 Prometheus 提供的 relabel_configs
中的 replace
能力了,relabel
可以在 Prometheus 采集数据之前,通过 Target 实例的 Metadata
信息,动态重新写入 Label 的值。除此之外,我们还能根据 Target 实例的 Metadata
信息选择是否采集或者忽略该 Target 实例。比如我们这里就可以去匹配 __address__
这个 Label 标签,然后替换掉其中的端口,如果你不知道有哪些 Label 标签可以操作的话,可以切换到 Service Discovery 页面找到 nodes
任务,下面的 Discovered Labels
就是我们可以操作的标签:
现在我们来替换掉端口,修改 ConfigMap:
- 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 路径下面 nodes 这个 job 任务是否正常了:
我们可以看到现在已经正常了,但是还有一个问题就是我们采集的指标数据 Label 标签就只有一个节点的 hostname,这对于我们在进行监控分组分类查询的时候带来了很多不方便的地方,要是我们能够将集群中 Node 节点的 Label 标签也能获取到就很好了。这里我们可以通过 labelmap
这个属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标数据的标签:
- 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 标签中去。
重新配置后的监控目标标签就多了很多了:
对于 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
另外由于 kubelet 也自带了一些监控指标数据,就上面我们提到的 10250 端口,所以我们这里也把 kubelet 的监控任务也一并配置上:
- 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 操作,让配置生效,然后访问 Prometheus 的 Dashboard 查看 Targets 路径:
现在可以看到我们上面添加的 kubelet
和 nodes
这两个 job 任务都已经配置成功了,而且二者的 Labels 标签都和集群的 node 节点标签保持一致了。
现在我们就可以切换到 Graph 路径下面查看采集的一些指标数据了,比如查询 node_load1 指标:
我们可以看到将 3 个节点对应的 node_load1
指标数据都查询出来了,同样的,我们还可以使用 PromQL
语句来进行更复杂的一些聚合查询操作,还可以根据我们的 Labels 标签对指标数据进行聚合。
到这里我们就把 Kubernetes 集群节点使用 Prometheus 监控起来了,接下来我们再来和大家学习下怎样监控 Pod 或者 Service 之类的资源对象。