- 云原生
- 可观测性
- 指标监控
- 监控大盘
- 告警
【免费下载链接】kube-prometheus
Use Prometheus to monitor Kubernetes and applications running on Kubernetes
本文是 kube-prometheus 官方指南 monitoring-other-namespaces.md 的深化解读。默认部署下 Prometheus 只对default、kube-system以及监控栈自身所在命名空间拥有 RBAC 发现权限,本文讲解如何通过 jsonnet 中的prometheus.namespaces变量为任意命名空间生成Role/RoleBinding,并结合ServiceMonitor让 Prometheus 采集目标应用指标,读完即可在自己的.jsonnet构建脚本中落地一套多命名空间监控方案。
为什么需要额外授权:默认 RBAC 只覆盖少数命名空间
kube-prometheus 采用RBAC 最小授权原则。Prometheus 的 ServiceMonitor 服务发现依赖 prometheus-operator 通过 Kubernetes API 读取目标命名空间中的Service、Pod、EndpointSlice(或Endpoints)、Ingress等资源,而读取这些资源必须要有对应命名空间内的 RBAC 权限。
默认情况下,这份权限只被授予三个命名空间:
defaultkube-system- 监控栈自身所在的命名空间(由
values.common.namespace决定,默认是monitoring)
这一点可以从源码得到直接印证。在 prometheus.libsonnet 中,prometheus组件的默认配置硬编码了这三个命名空间:
namespaces:: ['default', 'kube-system', defaults.namespace],其中defaults.namespace即为构建时传入的栈部署命名空间。也就是说,如果你在任意其他命名空间(例如业务应用所在的foo)中创建了ServiceMonitor,但该命名空间不在授权列表内,Prometheus 将无法发现并抓取其中的服务——即使 ServiceMonitor 本身已经创建成功。
对应的 RBAC 资源定义位于 prometheus-roleSpecificNamespaces.yaml(Role)与 prometheus-roleBindingSpecificNamespaces.yaml(RoleBinding),由make generate构建后静态渲染生成。从渲染结果可以看到,prometheus-k8s这一Role在default、kube-system、monitoring三个命名空间各有一份,规则覆盖:
discovery.k8s.io下的endpointslices- 核心组(
"")下的services、pods extensions与networking.k8s.io下的ingresses
verbs 均为get、list、watch;而RoleBinding则将monitoring命名空间中的prometheus-k8sServiceAccount 绑定到这些Role上。
核心变量:prometheus.namespaces
要监控更多命名空间,只需要在 jsonnet 构建脚本里扩充prometheus.namespaces列表。该变量在 prometheus.libsonnet 中被消费:构建器会为列表中的每一个命名空间分别生成一份Role(roleSpecificNamespaces)和一份RoleBinding(roleBindingSpecificNamespaces)。
其中Role的具体规则还受serviceDiscoveryRole配置影响:
- 当
serviceDiscoveryRole == 'EndpointSlice'(默认值)时,额外授予discovery.k8s.io/endpointslices的get、list、watch权限; - 当
serviceDiscoveryRole == 'Endpoints'时,改为授予核心组的endpoints权限; - 其他取值会直接触发 jsonnet 断言
error 'Invalid serviceDiscoveryRole: ' + ...。
无论哪种模式,services、pods以及extensions/networking.k8s.io下的ingresses的只读权限始终会被授予。
对应RoleBinding的生成逻辑(prometheus.libsonnet)会为每个命名空间生成一个RoleBinding,将prometheus-k8sServiceAccount 绑定到该命名空间内的prometheus-k8sRole上。
操作步骤:为命名空间foo生成 Role 与 RoleBinding
在构建清单时,把目标命名空间加入prometheus.namespaces数组即可。下面是与原指南一致、可在真实构建中直接使用的 jsonnet 示例:
local kp = (import 'kube-prometheus/main.libsonnet') + { values+:: { common+: { namespace: 'monitoring', }, prometheus+:: { namespaces: ["default", "kube-system", "monitoring", "foo"], }, }, }; { 'setup/0namespace-namespace': kp.kubePrometheus.namespace } + { ['setup/prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.filter((function(name) name != 'serviceMonitor' && name != 'prometheusRule'), std.objectFields(kp.prometheusOperator)) } + // serviceMonitor and prometheusRule are separated so that they can be created after the CRDs are ready { 'prometheus-operator-serviceMonitor': kp.prometheusOperator.serviceMonitor } + { 'prometheus-operator-prometheusRule': kp.prometheusOperator.prometheusRule } + { 'kube-prometheus-prometheusRule': kp.kubePrometheus.prometheusRule } + { ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } + { ['blackbox-exporter-' + name]: kp.blackboxExporter[name] for name in std.objectFields(kp.blackboxExporter) } + { ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) } + { ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } + { ['kubernetes-' + name]: kp.kubernetesControlPlane[name] for name in std.objectFields(kp.kubernetesControlPlane) } { ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } + { ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } + { ['prometheus-adapter-' + name]: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) }几点实操要点:
- 务必保留默认的三个命名空间。
namespaces是一个完整的替换列表而不是追加操作,示例中显式写出了default、kube-system、monitoring,再追加foo;如果只写["foo"],会丢掉基础命名空间的授权。 - 若使用
namespaces+: [...](+:表示追加合并),则可以在不重写默认值的前提下增量添加,这正是 additional-namespaces.jsonnet 中推荐的做法。 - 构建方式不变:将上述 jsonnet 交给
jsonnet与jsonnet-bundler渲染成 YAML 后,再按 docs/customizing.md 的流程生成manifests目录中的清单并kubectl apply。
增量追加更稳妥:官方示例 additional-namespaces.jsonnet
仓库 examples/additional-namespaces.jsonnet 提供了一个更简洁的增量写法:利用 jsonnet 的+:字段合并语义,在默认三个命名空间之上追加业务命名空间,无需手工维护完整列表:
local kp = (import 'kube-prometheus/main.libsonnet') + { values+:: { common+: { namespace: 'monitoring', }, prometheus+: { namespaces+: ['my-namespace', 'my-second-namespace'], }, }, }; { ['00namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } + { ['0prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } + { ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } + { ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } + { ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } + { ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } + { ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) }该示例渲染后会为my-namespace与my-second-namespace各生成一份prometheus-k8sRole与RoleBinding,与 prometheus-roleSpecificNamespaces.yaml、prometheus-roleBindingSpecificNamespaces.yaml 中已有条目的结构完全一致,只是把metadata.namespace替换为目标命名空间。
为每个额外命名空间定义 ServiceMonitor
有了 RBAC 授权,Prometheus 才具备在该命名空间内发现目标的能力;但要让指标真正被抓取,还必须在目标命名空间中创建ServiceMonitor资源。
通常来说,为命名空间内的应用创建
ServiceMonitor是该命名空间使用者的职责;如果希望与整套集群监控基础设施使用同一套 jsonnet 工具链进行生成,可以按下面的方式在构建脚本中一并产出。
仓库 examples/additional-namespaces-servicemonitor.jsonnet 展示了如何在 jsonnet 中内联定义 ServiceMonitor,并随其他组件一起渲染输出:
local kp = (import 'kube-prometheus/main.libsonnet') + { values+:: { common+: { namespace: 'monitoring', }, prometheus+:: { namespaces+: ['my-namespace', 'my-second-namespace'], }, }, exampleApplication: { serviceMonitorMyNamespace: { apiVersion: 'monitoring.coreos.com/v1', kind: 'ServiceMonitor', metadata: { name: 'my-servicemonitor', namespace: 'my-namespace', }, spec: { jobLabel: 'app', endpoints: [ { port: 'http-metrics', }, ], selector: { matchLabels: { 'app.kubernetes.io/name': 'myapp', }, }, }, }, }, }; { ['00namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } + { ['0prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } + { ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } + { ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } + { ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } + { ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } + { ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) } + { ['example-application-' + name]: kp.exampleApplication[name] for name in std.objectFields(kp.exampleApplication) }这个 ServiceMonitor 的关键字段含义如下:
| 字段 | 作用 | 示例取值 |
|---|---|---|
metadata.namespace | 必须与目标应用所在命名空间一致,ServiceMonitor 与目标Service同处一个命名空间 | my-namespace |
spec.jobLabel | 指定从目标 Service 的哪个标签取值作为 Prometheusjob标签 | app |
spec.endpoints[].port | 目标 Service 上承载指标接口的端口名(需与 Service 中定义的端口名严格一致) | http-metrics |
spec.selector.matchLabels | 用于匹配目标 Service 的标签选择器,决定哪些 Service 被纳入采集 | app.kubernetes.io/name: myapp |
重要提醒:请确保你的 Service 资源带有正确的标签(例如app: myapp或示例中的app.kubernetes.io/name: myapp)。Prometheus 正是利用这些 Kubernetes 标签在命名空间内完成服务发现与目标匹配的——如果 Service 缺少与selector对应的标签,ServiceMonitor 将永远匹配不到任何端点,也就不会有任何抓取任务。
ServiceMonitor属于 prometheus-operator 的 CRD(monitoring.coreos.com/v1),其 CRD 定义由 manifests/setup/0servicemonitorCustomResourceDefinition.yaml 提供。Prometheus 一侧的serviceMonitorSelector与serviceMonitorNamespaceSelector均为空(见 prometheus.libsonnet),表示 Prometheus 会选中集群内(且自身有权访问的命名空间内)所有 ServiceMonitor,这也是只需要靠 RBAC 列表来控制可见性的原因。
变体一:监控全部命名空间(需谨慎)
如果业务上确实需要覆盖整个集群,官方提供all-namespacesmixin,见 examples/all-namespaces.jsonnet 与 monitoring-all-namespaces.md:
local kp = (import 'kube-prometheus/main.libsonnet') + (import 'kube-prometheus/addons/all-namespaces.libsonnet') + { values+:: { common+: { namespace: 'monitoring', }, prometheus+: { namespaces: [], }, }, };其底层实现(all-namespaces.libsonnet)做了两件事:
- 在
prometheus.clusterRole中追加集群级规则:endpointslices、services、endpoints、pods、ingresses的get/list/watch; - 将
roleSpecificNamespaces与roleBindingSpecificNamespaces置为null,同时把prometheus.namespaces清空,避免再为具体命名空间生成重复的 Role/RoleBinding。
安全警告:这种配置在集群(尤其是多租户集群)中可能带来安全隐患——它让 Prometheus 对整个集群拥有可见性,可能超出某些被安全策略锁定的命名空间的预期。请仅在完全受信的单租户集群中使用,并评估合规要求。
采用该方案后,仍需按上文“为每个额外命名空间定义 ServiceMonitor”一节的方式,为实际要监控的服务创建 ServiceMonitor。
变体二:直接手写 RBAC 清单(不使用 jsonnet)
如果团队不使用 jsonnet 构建流程,也可以参考 manifests/prometheus-roleSpecificNamespaces.yaml 中现有的Role模板,为每个目标命名空间手工复制一份,将metadata.namespace改为目标命名空间;再在 manifests/prometheus-roleBindingSpecificNamespaces.yaml 中为每个命名空间添加对应的RoleBinding,subjects固定指向monitoring命名空间下的prometheus-k8sServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: prometheus-k8s namespace: foo roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring手工维护的缺点是无法随构建流程自动同步,新增命名空间时需要人工补两份资源,因此官方推荐优先使用 jsonnet 变量方案。
验证与故障排查
部署完成后,可以通过以下方式验证授权是否生效、采集是否正常:
- 检查 RBAC 资源是否就位:
kubectl get role,rolebinding -n foo应能看到prometheus-k8s的Role与RoleBinding。 - 观察 Prometheus 抓取状态:进入 Prometheus UI 的
Status → Targets页面,或执行kubectl -n monitoring exec进入 Prometheus Pod 后查询/api/v1/targets,确认my-namespace下出现对应抓取目标且状态为UP。 - 核对 Service 标签:若
Targets页面始终为空,优先检查目标Service的标签是否与ServiceMonitor.spec.selector.matchLabels匹配(参见 example-app.yaml 中的 Service 与标签写法)。 - 确认 ServiceMonitor 被选中:
kubectl get servicemonitor -n my-namespace确认资源存在;由于 Prometheus 的serviceMonitorSelector/serviceMonitorNamespaceSelector为空,只要命名空间在授权列表内即可被自动纳入。
相关资源速查:
- 指南原文:docs/monitoring-other-namespaces.md
- 增量追加命名空间示例:examples/additional-namespaces.jsonnet
- 连带 ServiceMonitor 的完整示例:examples/additional-namespaces-servicemonitor.jsonnet
- RBAC 生成逻辑:jsonnet/kube-prometheus/components/prometheus.libsonnet
- 全命名空间方案:docs/customizations/monitoring-all-namespaces.md
- 云原生
- 可观测性
- 指标监控
- 监控大盘
- 告警
【免费下载链接】kube-prometheus
Use Prometheus to monitor Kubernetes and applications running on Kubernetes
相关推荐
kube-prometheus自定义ServiceMonitor:监控特定命名空间应用
kube prometheus自定义ServiceMonitor:监控特定命名空间应用 1. 痛点与挑战:Kubernetes多命名空间监控困境 在复杂的Kub
云原生可观测性指标监控监控大盘告警kube-prometheus 监控附加命名空间:通过 jsonnet 扩展 Prometheus 抓取范围与 ServiceMonitor 实战指南
kube prometheus 监控附加命名空间:通过 jsonnet 扩展 Prometheus 抓取范围与 ServiceMonitor 实战指南 导读 在
云原生可观测性指标监控监控大盘告警kube-prometheus 全命名空间监控指南:使用 all-namespaces mixin 监控集群所有命名空间
kube prometheus 全命名空间监控指南:使用 all namespaces mixin 监控集群所有命名空间 本指南基于 kube promethe
云原生可观测性指标监控监控大盘告警
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考