promethes服务发现
本章说明: 适配不同场景的注册中心类型,基于k8s api的prometheus监控
基于Kubernetes API的服务发现
在Kubernetes(K8s)容器集群中,Pod、Node等资源会频繁经历创建、调度、销毁等生命周期变化,传统静态配置或简单服务发现已无法适配。Prometheus通过直接调用Kubernetes API实现的服务发现机制,能实时感知集群资源变动,自动完成监控目标的发现与更新,是容器场景下的最优选择
核心原理:API驱动的动态感知
Prometheus基于Kubernetes API的服务发现,核心是通过"权限认证-资源监听-元标签生成-目标加工"的链路,实现监控目标的全自动化管理,无需第三方注册中心介入,
- 原理如下:
- 权限认证:Prometheus通过K8s的Service Account机制获取API访问权限,确保能合法查询、监听集群资源。
- 资源监听 :通过配置
kubernetes_sd_configs指定"资源角色"(如Node、Pod、Service),Prometheus会持续监听对应资源的CRUD(创建、读取、更新、删除)事件。 - 元标签生成 :发现资源后,Prometheus自动为每个目标生成前缀为
__meta_kubernetes_*的元标签,封装资源的核心信息(如Pod命名空间、节点标签、服务端口等)。 - 目标加工与抓取 :通过
relabel_configs过滤无效目标、提取业务标签、拼接访问地址,最终生成标准化监控目标,按scrape_interval周期抓取指标。
- **核心优势:**与K8s集群原生集成,无需额外部署组件;支持细粒度资源过滤;能实时同步资源变动,适配容器动态调度特性。
前置条件:K8s权限配置(RBAC)
K8s默认开启RBAC(基于角色的访问控制),需为Prometheus创建Service Account并绑定权限,确保其能访问集群API。以下为标准权限配置流程: 还没学到k8s仅先记录一下
-
权限配置文件(prometheus-rbac.yaml)
创建命名空间、Service Account、ClusterRole和ClusterRoleBinding,遵循"最小权限原则"配置权限:
bash# 1. 创建独立命名空间(建议监控组件单独部署) apiVersion: v1 kind: Namespace metadata: name: monitoring --- # 2. 创建Service Account(Prometheus将使用该账号访问API) apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: monitoring --- # 3. 定义集群角色(明确可访问的资源和操作) apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] # 核心API组(Node、Pod、Service等基础资源) resources: ["nodes", "nodes/metrics", "pods", "services", "endpoints"] verbs: ["get", "list", "watch"] # 仅允许查询和监听,禁止修改 - apiGroups: ["apps"] # 应用API组(Deployment、StatefulSet等) resources: ["deployments", "statefulsets"] verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"] # 允许访问节点的/metrics端点 verbs: ["get"] --- # 4. 绑定角色与账号(将ClusterRole绑定到Service Account) apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: monitoring roleRef: kind: ClusterRole name: prometheus apiGroup: rbac.authorization.k8s.io -
执行部署命令
bash# 应用权限配置 kubectl apply -f prometheus-rbac.yaml # 验证权限(查看Service Account是否创建成功) kubectl get sa -n monitoring # 预期输出:NAME SECRETS AGE # prometheus 1 10s
配置场景
K8s服务发现支持多种资源角色,以下为Node(节点监控)、Pod(容器应用监控)、Service(服务监控)三大核心场景的完整配置示例,可直接复用。
-
支持的资源类型及核心标签:
资源类型 作用 核心元标签示例 Node 监控 K8s 节点 __meta.kubernetes_node_name(节点名)Pod 监控容器实例 __meta.kubernetes_pod_ip(Pod IP)Service 监控服务端点 __meta.kubernetes_service_name(服务名)Endpoint 监控服务后端 __meta.kubernetes_endpoint_ready(就绪状态)Ingress 监控入口路由 __meta.kubernetes_ingress_path(路由路径)
Node资源发现(监控集群节点)
监控K8s集群节点的CPU、内存、磁盘等硬件资源,依赖Node Exporter(需提前在各节点部署,默认暴露9100端口)。在Node角色的服务发现中,Prometheus会自动生成一系列节点相关的元数据标签,可用于目标过滤、标签加工等场景,
-
核心元数据标签如下:
元数据标签名称 说明 示例 __meta.kubernetes_node_nameK8s集群中的节点名称 node-10-4-50-130 __meta.kubernetes_node_label_<labelname>节点的自定义标签,替换为实际标签名 __meta.kubernetes_node_label_env=production __meta.kubernetes_node_labelpresent_<labelname>节点是否存在指定标签,返回布尔值 __meta.kubernetes_node_labelpresent_env=true __meta.kubernetes_node_annotation_<annotation>节点的自定义注解,替换为实际注解名 __meta.kubernetes_node_annotation_node_type=worker __meta.kubernetes_node_annotationpresent_<annotation>节点是否存在指定注解,返回布尔值 __meta.kubernetes_node_annotationpresent_node_type=true __meta.kubernetes_node_address_<address_type>节点的地址信息,<address_type>为地址类型 __meta.kubernetes_node_address_NodeInternalIP=10.4.50.130 **注意:**节点监控中instance标签的默认取值来自__meta.kubernetes_node_name(节点名称),而非
__address__(节点IP),可通过relabel_configs自定义调整。 -
yml示例
bashglobal: scrape_interval: 15s # 全局抓取间隔 evaluation_interval: 15s # 规则评估间隔 scrape_configs: - job_name: 'k8s-node-monitor' # 配置K8s服务发现,角色为Node kubernetes_sd_configs: - role: node # 可选:限定监控的命名空间(不配置则监控全集群) namespaces: names: ["monitoring", "default"] # 标签重写:过滤目标、添加自定义标签 relabel_configs: # 1. 仅保留生产环境节点(节点标签需提前配置env=production) - source_labels: [__meta_kubernetes_node_label_env] regex: production action: keep # 2. 拼接Node Exporter访问地址(节点IP:9100) - source_labels: [__address__] target_label: __address__ replacement: "${1}:9100" # 3. 将节点名作为自定义标签,便于查询过滤 - source_labels: [__meta_kubernetes_node_name] target_label: node_name # 抓取配置 scheme: http metrics_path: /metrics
Pod资源发现(监控业务容器)
监控集群内业务Pod的应用指标(如Java应用的JVM指标、自定义业务指标),需通过Pod注解标记可抓取的目标。在Pod角色的服务发现中,Prometheus会生成丰富的元数据标签,涵盖Pod的命名空间、标签、注解、容器等信息,
-
核心元数据标签如下:
元数据标签名称 说明 示例 __meta_kubernetes_pod_namePod的名称 demo-app-7f9d6c5f4d-2xqzk __meta_kubernetes_pod_namespacePod所属的命名空间 default __meta_kubernetes_pod_label_<labelname>Pod的自定义标签,替换为实际标签名 __meta_kubernetes_pod_label_app=demo-app __meta_kubernetes_pod_annotation_<annotation>Pod的自定义注解,替换为实际注解名 __meta_kubernetes_pod_annotation_prometheus_io_scrape=true __meta_kubernetes_pod_container_namePod内容器的名称 demo-app __meta_kubernetes_pod_host_ipPod所在节点的IP地址 10.4.50.130 __meta_kubernetes_pod_ipPod的IP地址 10.244.1.5 __meta_kubernetes_pod_readyPod的就绪状态(true/false) true -
yml示例
bashscrape_configs: - job_name: 'k8s-pod-monitor' kubernetes_sd_configs: - role: pod # 资源角色为Pod relabel_configs: # 1. 仅抓取标注了prometheus.io/scrape=true的Pod(核心过滤规则) - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] regex: true action: keep # 2. 从Pod注解获取指标路径(默认/metrics,可自定义) - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] regex: (.+) target_label: __metrics_path__ replacement: $1 # 3. 从Pod注解获取暴露端口(如注解prometheus.io/port: "8080") - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] regex: ([^:]+)(?::\d+)?;(\d+) target_label: __address__ replacement: $1:$2 # 4. 添加Pod命名空间、名称标签,便于聚合分析 - source_labels: [__meta_kubernetes_pod_namespace] target_label: k8s_namespace - source_labels: [__meta_kubernetes_pod_name] target_label: k8s_pod_name # 5. 过滤掉非业务命名空间的Pod(如kube-system) - source_labels: [__meta_kubernetes_pod_namespace] regex: kube-system action: drop -
业务Pod注解配置示例(Deployment.yaml中添加):
ymlapiVersion: apps/v1 kind: Deployment metadata: name: demo-app namespace: default spec: replicas: 2 template: metadata: annotations: prometheus.io/scrape: "true" # 允许Prometheus抓取 prometheus.io/port: "8080" # 应用暴露指标的端口 prometheus.io/path: "/actuator/prometheus" # 自定义指标路径(如Spring Boot应用) spec: containers: - name: demo-app image: demo-app:v1.0 ports: - containerPort: 8080
Service资源发现(监控服务集群)
监控K8s Service对应的后端端点,适合数据库、缓存等有固定服务地址的中间件监控场景。在Service角色的服务发现中,Prometheus生成的元数据标签聚焦于服务的核心信息,如服务名、端口、选择器等,
-
核心元数据标签如下:
元数据标签名称 说明 示例 __meta_kubernetes_service_nameService的名称 mysql-service __meta_kubernetes_service_namespaceService所属的命名空间 middleware __meta_kubernetes_service_label_<labelname>Service的自定义标签,替换为实际标签名 __meta_kubernetes_service_label_app=middleware __meta_kubernetes_service_port_nameService的端口名称 mysql-port __meta_kubernetes_service_port_numberService的端口号 3306 __meta_kubernetes_service_port_protocolService的端口协议(TCP/UDP) TCP __meta_kubernetes_service_cluster_ipService的集群IP地址 10.96.123.45 __meta_kubernetes_service_selector_<key>Service的选择器键值对,替换为选择器键 __meta_kubernetes_service_selector_app=mysql -
yml示例
bashscrape_configs: - job_name: 'k8s-service-monitor' kubernetes_sd_configs: - role: service # 资源角色为Service relabel_configs: # 1. 仅抓取标签为app=middleware的服务(如MySQL、Redis) - source_labels: [__meta_kubernetes_service_label_app] regex: middleware action: keep # 2. 提取服务端口名称作为标签 - source_labels: [__meta_kubernetes_service_port_name] target_label: service_port_name # 3. 拼接服务访问地址(Service ClusterIP:端口) - source_labels: [__meta_kubernetes_service_cluster_ip, __meta_kubernetes_service_port_number] target_label: __address__ replacement: "${1}:${2}" metrics_path: /metrics scheme: http
验证与运维关键事项
- 配置验证方法
- WebUI验证 :访问Prometheus WebUI(默认
http://<Prometheus-IP>:9090),进入"Status → Targets"页面,对应Job下的目标状态为"UP"表示发现成功。 - API验证 :通过Prometheus API查询发现的目标列表:
curl http://<Prometheus-IP>:9090/api/v1/targets | jq .data.activeTargets - 动态测试:新建或删除符合过滤规则的Pod/Node,观察Prometheus Target列表是否在15秒内(与scrape_interval一致)同步更新。
- WebUI验证 :访问Prometheus WebUI(默认
- 核心注意事项
- 权限安全:严禁授予Prometheus集群管理员(cluster-admin)权限,避免权限泄露导致安全风险。
- 目标过滤优化 :务必通过
relabel_configs过滤无关目标(如kube-system命名空间的系统Pod),减少Prometheus抓取压力。 - 注解规范 :业务Pod需统一注解格式(如
prometheus.io/*前缀),避免因注解不规范导致发现失败。 - 元标签活用 :
__meta_kubernetes_*元标签包含丰富资源信息,可用于构建精细化监控视图(如按命名空间、节点分组)。 - 高可用适配:Prometheus建议部署为StatefulSet,结合K8s API的Watch机制,确保服务发现的连续性,避免单点故障。
- 性能调优 :大规模集群(千级以上Pod)建议调大
kubernetes_sd_configs的refresh_interval(默认30秒),避免频繁API调用影响K8s APIServer性能。
常见问题排查常见问题排查
| 问题现象 | 排查方向 |
|---|---|
| Target状态为"Down" | 1. 检查目标Pod/Node是否正常运行;2. 验证指标端口是否能访问(如telnet <IP> <端口>);3. 确认metrics路径是否正确 |
| 无目标被发现 | 1. 检查RBAC权限是否配置正确(kubectl describe sa prometheus -n monitoring);2. 验证relabel_configs过滤规则是否过于严格;3. 查看Prometheus日志是否有API访问错误 |
| 目标更新延迟 | 1. 调整kubernetes_sd_configs的refresh_interval参数;2. 检查K8s APIServer是否存在性能瓶颈 |