17.3.4 Kubernetes服务发现与标签选择
Kubernetes 服务发现机制概览#
Prometheus 通过 Kubernetes API 自动发现集群内的监控目标,支持 Pod、Service、Endpoints、Node、Ingress 等资源类型。其核心流程是:拉取 API 元数据 → relabel 过滤与重写 → 生成实际抓取目标。
下图为原理草图:
典型发现配置示例#
以下示例基于 kube-prometheus 或自建 Prometheus,演示 Pod 发现、标签筛选与注解参数化。
文件路径:/etc/prometheus/prometheus.yml
scrape_configs:
- job_name: "k8s-pods"
kubernetes_sd_configs:
- role: pod
relabel_configs:
# 仅保留显式标记 scrape=true 的 Pod
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
# 从注解中读取采集端口
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: "(.+)"
replacement: "$1"
# __address__ 先只放端口,稍后拼接 IP
- source_labels: [__meta_kubernetes_pod_ip, __address__]
action: replace
target_label: __address__
regex: "(.+);(.+)"
replacement: "$1:$2"
# 自定义采集路径
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: "(.+)"
replacement: "$1"
# 标签映射:namespace、pod、app
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: pod
- source_labels: [__meta_kubernetes_pod_label_app]
action: replace
target_label: app
命令验证配置生效:
# 重新加载 Prometheus 配置(需启用 --web.enable-lifecycle)
curl -X POST http://prometheus:9090/-/reload
# 查看发现到的目标
curl -s http://prometheus:9090/api/v1/targets | jq '.data.activeTargets[].labels'
标签选择与注解约定#
推荐约定统一使用以下注解与标签:
metadata:
labels:
app: order-api
env: prod
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
创建示例 Pod:
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: demo-metrics
labels:
app: demo
env: dev
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9100"
prometheus.io/path: "/metrics"
spec:
containers:
- name: node-exporter
image: prom/node-exporter:v1.6.1
ports:
- containerPort: 9100
EOF
relabeling 规则与目标过滤#
常见 relabel 动作说明:
- keep:仅保留符合条件的目标
- drop:丢弃符合条件的目标
- replace:重写或新增标签
示例:仅保留 env=prod 的 Pod,同时丢弃临时命名空间:
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_env]
action: keep
regex: "prod"
- source_labels: [__meta_kubernetes_namespace]
action: drop
regex: "tmp|sandbox"
多资源发现与使用场景#
不同资源发现类型的实践建议:
# 监控 Node(配合 node-exporter DaemonSet)
- job_name: "k8s-nodes"
kubernetes_sd_configs:
- role: node
scheme: http
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
适用场景:
- pod:微服务实例级监控,便于细粒度定位问题
- endpoints:基于 Service 后端实例发现
- service:用于 blackbox 或对外服务健康检测
- node:主机层指标
- ingress:入口可用性监控
标签管理与一致性规范#
统一标签规范示例:
必须标签:namespace, app, pod, cluster
建议标签:env, version, release
避免标签:request_id、trace_id、user_id(高基数)
命令检查标签基数(估算):
# 查询某指标的不同 label 值数量
curl -G 'http://prometheus:9090/api/v1/series' \
--data-urlencode 'match[]=up' \
--data-urlencode 'start=1h' \
--data-urlencode 'end=now' | jq '.data | length'
安装与权限配置示例#
Kubernetes 中 Prometheus 需具备访问 API 的 RBAC 权限。
示例(最小权限):
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-sd
rules:
- apiGroups: [""]
resources: ["nodes", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-sd
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus-sd
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
应用并验证:
kubectl apply -f rbac.yaml
kubectl -n monitoring get sa prometheus
kubectl auth can-i list pods --as system:serviceaccount:monitoring:prometheus
常见问题与排查思路#
-
未采集到指标
- 检查 Pod 注解是否正确:
bash kubectl get pod demo-metrics -o jsonpath='{.metadata.annotations}'
- 检查 Prometheus 发现页面:http://prometheus:9090/service-discovery -
目标状态为 DOWN
- 校验端口/路径:
bash kubectl exec -it demo-metrics -- wget -qO- localhost:9100/metrics | head
- 检查网络策略或 Service 访问限制 -
目标过多导致资源消耗
- 检查是否缺少keep规则
- 查看目标数量:
bash curl -s http://prometheus:9090/api/v1/targets | jq '.data.activeTargets | length'
练习#
- 新建一个
env=prod的应用 Pod,添加prometheus.io/scrape=true注解,验证其出现在/-/targets。 - 修改 relabel 规则,仅保留
app=demo的 Pod,观察activeTargets数量变化。 - 使用
role: endpoints替换role: pod,对比两种方式的目标标签差异。