11-Prometheus 基于 K8S 服务发现详解
1. Prometheus 服务发现
Prometheus Server 的数据抓取工作基于 Pull 模型 , 因而 , 它必须要事先知道各 target 的位置 , 然后才能从相应的 Exporter 或 Instrumentation 中抓取数据。
对于小型的系统环境 , 使用 static_configs 指定各 target 即可解决问题 , 但是对于较大的集群不适用 , 尤其不适用于使用容器和基于云的实例的动态集群 , 因为这些实例会经常出现变化、创建、或销毁的情况。
Prometheus 为此专门设计了一组服务发现机制 , 以便于能够基于服务注册中心自动发现、检测、分类可被监控的各 target , 以及更新发生了变动的 target。Prometheus 可以集成到多种不同的开源服务发现工具上 , 以便动态发现需要监控的目标。
在k8s容器环境中由于集群内实例网络地址是动态的 , 我们不可能每次创建或修改实例都将实例IP写入Prometheus的target中 , 借助服务发现我们可以快速的将集群内的资源注册到Prometheus-server中。
Prometheus 可以很好的集成到 Kubernetes 平台上 , 通过其 API Server 动态发现各类被监控的 Pod、Service、Endpoint、Ingress 及 Node 对象 , 还支持基于文件实现的动态发现。
Prometheus目前支持的服务发现类型
prometheus目前支持以下几种的服务发现类型:
基于文件的服务发现
基于
consul的服务发现基于
k8s API的服务发现基于
eureka的服务发现基于
nacos的服务发现基于
DNS的服务发现
2. 什么是 Kubernetes_sd_configs?
Prometheus中k8s服务发现的原理是通过 Kubernetes 的REST API 检索抓取目标 , 并始终与集群状态保持同步。所以我们需要配置Kubernetes_sd_configs来访问K8s API。

比如我们要抓取k8s ingress , 需要为Prometheus指定用于RBAC认证证书和serviceaccount的token。
- job_name: 'kubernetes-ingress'
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
kubernetes_sd_configs:
- role: ingress这里的role为k8s中资源实体如 endpoints、service、pod、node或 ingress , 当指定ingress时 , Prometheus将每个入口地址发现为一个目标。
3. 基于 kubernetes_sd_configs 自动发现配置
准备
Prometheus的自动发现的配置文件并加载[root@VM-12-8-centos kube-prom]# cat prometheus-additional.yaml - job_name: 'blackbox' metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - http://10.1.226.250:6000 - http://10.1.38.97:3000/healthz/ready - http://10.1.116.84:5000 - http://10.1.215.125:7000/healthz/ready - http://10.1.111.235:8000/healthz/ready relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:9115 - job_name: 'kubernetes-service-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: namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: service - source_labels: [__meta_kubernetes_pod_name] target_label: pod action: replace - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - 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: namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: pod运行生成
secret文件[root@VM-12-8-centos kube-prom]# kubectl create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml --dry-run -oyaml > additional-scrape-configs.yaml应用配置进入
Prometheus中[root@VM-12-8-centos kube-prom]# kubectl apply -f additional-scrape-configs.yaml -n monitoring secret/additional-scrape-configs configured运行
curl -XPOST http://10.0.12.8:30090/-/reload热加载一下 , 就可以在dashboard中看到增加的配置了。
修改
prometheus-k8s的ClusterRole权限Prometheus绑定了一个名为prometheus-k8s的ServiceAccount对象 , 而这个对象绑定的是一个名为prometheus-k8s的ClusterRole, 这个角色没有对Service或者Pod的list权限 , 所以需要进行修改[root@VM-12-8-centos manifests]# kubectl edit clusterrole prometheus-k8s -n monitoring -o yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: creationTimestamp: "2022-11-13T14:21:08Z" name: prometheus-k8s resourceVersion: "16164985" selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/prometheus-k8s uid: 7a404fac-9462-486a-a109-65a1ef98e423 rules: - apiGroups: - "" resources: - nodes - services - endpoints - pods - nodes/proxy verbs: - get - list - watch - apiGroups: - "" resources: - configmaps - nodes/metrics verbs: - get - nonResourceURLs: - /metrics verbs: - get
pod配置自动发现pod要自动发现 , 必须在annotations:增加prometheus.io/scrape: "true", 新建一个pod。[root@VM-12-8-centos k8s]# cat PODforheadlesssvr.yml apiVersion: v1 kind: Pod metadata: name: ex-podforheadlesssvr annotations: prometheus.io/scrape: "true" spec: containers: - name: testcontainer image: docker.io/appropriate/curl imagePullPolicy: IfNotPresent command: ['sh', '-c'] args: ['echo "test pod for headless service";sleep 96000'] [root@VM-12-8-centos k8s]# kubectl apply -f ex6_1_4PODforheadlesssvr.yml pod/ex-podforheadlesssvr created [root@VM-12-8-centos k8s]# kubectl get po NAME READY STATUS RESTARTS AGE ex-podforheadlesssvr 1/1 Running 0 3s过一会检查
dashboard, 已经在界面上了
状态为
down, 因为这个pod对应的镜像并没有相关的metrics接口 , 我们主要是用来进行自动发现测试的 , 在服务发现界面。
在
target labels部分
如上操作 , 就可以基于
k8s自动发现 在Prometheus中增加监控项了。
4. Prometheus 基于k8s服务发现案例
下面学习一下 Prometheus 基于k8s服务发现通过Cadvisor监控Kubernetes。
Kubernetes主要提供了如下5种服务发现模式和Prometheus进行集成:
NodePodEndpointsServiceIngress
使用cAdvisor主要需要使用Node服务发现模式 , 配置方式如下所示:
kubernetes_sd_configs:
- role: node
4.1 监控指标
Kubernetes本身监控Node资源利用率Node数量Pods数量(Node)资源对象状态
Pod监控Pod数量(项目)容器资源利用率
应用程序

4.2 监控Kubernetes

4.3 Prometheus通过Cadvisor监控k8s
Kubernetes默认提供cAdvisor和特定节点的时间序列。我们可以创建一个作业来从每个节点的Kubernetes API中抓取这些时间序列。我们可以使用这些时间序列来监控节点 , 以及每个节点上的Docker守护进程和容器。

这里将作业命名为 kubernetes-cadvisor , 并使用服务发现来返回 node 角色的 Kubernetes 节点列表。我们使用https 来抓取指标 , 并指定证书颁发机构和一个本地令牌文件以对 Kubernetes 进行身份验证。
然后我们重新标记时间序列 , 以便从使用 labelmap 发现的元数据标签中创建标签 , 将 __address__ 标签替换为Kubernetes API 服务器的默认 DNS 名称。然后 , 我们使用其中一个元数据标签 , 一个带有节点名称的标签 , 在API 上创建一个新标签 __metrics_path__ , 它将节点名称传递给路径。
4.4 监控K8s集群Pod步骤
K8s RBAC授权现在普罗米修斯要通过服务发现连接到
k8s集群 ,k8s授权普罗米修斯可以访问如下地址[root@k8s-master ~]# kubectl get ep NAME ENDPOINTS AGE kubernetes 192.168.179.102:6443 74dPrometheus -> apiserver(192.168.179.102:6443)->kubelet(cadvisor) 这个过程是需要授权的 , 所以第一步就是授权。[root@k8s-master ~]# cat rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 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 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: kube-system [root@k8s-master ~]# kubectl apply -f rbac.yaml serviceaccount/prometheus created现在要拿到创建
rbac产生的token, , 这是非常关键的 , 让普罗米修斯拿着这个token去访问api那么就具有rbac里面授予的权限了。怎么拿到这个
token呢 , 产生的sa在kube-system上 , 怎么拿到这个token呢 , 产生的sa在kube-system上。[root@k8s-master ~]# kubectl get sa -n kube-system | grep prome prometheus 1 4m59s [root@k8s-master ~]# kubectl describe sa prometheus -n kube-system Name: prometheus Namespace: kube-system Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: prometheus-token-jq2kg Tokens: prometheus-token-jq2kg Events: <none>Token保存在这个secret当中prometheus-token-jq2kg。[root@k8s-master ~]# kubectl describe secret prometheus-token-jq2kg -n kube-system token: eyJhbGciOiJSUzI1NiIsImtpZCI6InR0cTRHNDNQUGFMeUZ5Rnp1azZnSUEyRVU0WEY1dWdEMEYwd056ZnNkWWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJwcm9tZXRoZXVzLXRva2VuLWpxMmtnIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InByb21ldGhldXMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxNDYxYTU1Mi0xZWE0LTRjYWQtOTdhOC05YmE1Zjg2YjhkMmYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06cHJvbWV0aGV1cyJ9.FfRTfjE5ih9ZvCy0XFL1Trc00H7k1s6kkGmFvnkKJghswTLeATRPfziAJqrBYBYY0dA8IK52WEa0JR2TevtotnWOyIXZnv6KWcPb0RObvlL4dxp1ZJyZRAc01rliyukTU2HphgX2NlLnf_TZHMo1bapPf8crDdMlZHoEe42ukMtr1nZrPgChXJCtGoR383bAWDoDrq1nZ7e8xCQnoxEkq_khLO9ypHqAlFfMCG-w0x35uC1Wa06FdoeygW0gABDK_Ltgvz6_IuLM9wLl54SnPZJEPSMfiNpuvN8vDWNUcjqPj1Lqi3eSMKLf7b3zBvlTEcLQKoUQdXBdg-97pfeDVw获取
Token并保存到文件拿到这个
token, 拷贝到普罗米修斯这个节点。[root@k8s-master ~]# kubectl describe secret prometheus-token-jq2kg -n kube-system > token.k8s [root@k8s-master ~]# scp token.k8s root@192.168.179.99:/usr/local/prometheus在普罗米修斯上只保存这
token值 , 其余的全部去掉[root@localhost prometheus]# cat token.k8s eyJhbGciOiJSUzI1NiIsImtpZCI6InR0cTRHNDNQUGFMeUZ5Rnp1azZnSUEyRVU0WEY1dWdEMEYwd056ZnNkWWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJwcm9tZXRoZXVzLXRva2VuLWpxMmtnIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InByb21ldGhldXMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxNDYxYTU1Mi0xZWE0LTRjYWQtOTdhOC05YmE1Zjg2YjhkMmYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06cHJvbWV0aGV1cyJ9.FfRTfjE5ih9ZvCy0XFL1Trc00H7k1s6kkGmFvnkKJghswTLeATRPfziAJqrBYBYY0dA8IK52WEa0JR2TevtotnWOyIXZnv6KWcPb0RObvlL4dxp1ZJyZRAc01rliyukTU2HphgX2NlLnf_TZHMo1bapPf8crDdMlZHoEe42ukMtr1nZrPgChXJCtGoR383bAWDoDrq1nZ7e8xCQnoxEkq_khLO9ypHqAlFfMCG-w0x35uC1Wa06FdoeygW0gABDK_Ltgvz6_IuLM9wLl54SnPZJEPSMfiNpuvN8vDWNUcjqPj1Lqi3eSMKLf7b3zBvlTEcLQKoUQdXBdg-97pfeDVw现在可以让普罗米修斯拿着这个
token访问api了。
创建
Job和kubeconfig_sd_configs**现在可以让普罗米修斯拿着这个
token访问api了 , 这里启用的是k8s服务发现的配置。[root@localhost ~]# vim /usr/local/prometheus/prometheus.yml - job_name: kubernetes-nodes-cadvisor metrics_path: /metrics scheme: https #访问api使用https访问 kubernetes_sd_configs: - role: node #指定服务发现类型的角色为node api_server: https://192.168.179.102:6443 bearer_token_file: /usr/local/prometheus/token.k8s tls_config: insecure_skip_verify: true #跳过https验证 , 因为自签发 , 不受信任 , 跳过证书校验 bearer_token_file: /usr/local/prometheus/token.k8s tls_config: insecure_skip_verify: true #跳过证书 relabel_configs: # 将标签(.*)作为新标签名 , 原有值不变 - action: labelmap regex: __meta_kubernetes_node_label_(.*) # 修改NodeIP:10250为APIServerIP:6443 - action: replace regex: (.*) source_labels: ["__address__"] target_label: __address__ replacement: 192.168.31.61:6443 # 实际访问指标接口 https://NodeIP:10250/metrics/cadvisor 这个接口只能APISERVER访问 , 故此重新标记>标签使用APISERVER代理访问 - action: replace source_labels: [__meta_kubernetes_node_name] target_label: __metrics_path__ regex: (.*) replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor [root@localhost prometheus]# ./promtool check config prometheus.yml Checking prometheus.yml SUCCESS: 0 rule files found


https://192.168.179.102:6443/api/v1/nodes/k8s-node1/proxy/metrics/cadvisor,这些数据就是从这个地址下面拿到的,如果你将该段去掉,可以看到没有重新标记标签会采集不到数据。
# - action: replace # source_labels: [__meta_kubernetes_node_name] # target_label: __metrics_path__ # regex: (.*) # replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

参考链接
构建企业级监控平台系列(二十二):Prometheus 基于 K8S 服务发现详解 (qq.com)