DevOps全链路实战 | 第 11 天:Prometheus 部署与 ServiceMonitor 指标采集

第 11/19 天

引言

在前面的十天中,我们已经完成了从 K8s 集群搭建、Harbor 镜像仓库、GitLab CI/CD 流水线、Argo CD GitOps 到 SonarQube 代码质量检查的完整构建与部署管道。然而,一个成熟的 DevOps 体系仅有”构建”和”部署”是远远不够的——当应用跑起来之后,我们需要一双”眼睛”来持续观察系统的健康状态,这就是可观测性(Observability)。

可观测性在云原生领域通常由三大支柱组成:指标(Metrics)、日志(Logs)、链路追踪(Traces)。其中,指标采集是最基础也是最先落地的环节。Prometheus 作为 CNCF 毕业项目,凭借其强大的多维数据模型、Pull 模式采集、PromQL 查询语言以及活跃的社区生态,已成为 Kubernetes 环境下指标监控的事实标准。

今天我们将通过 kube-prometheus-stack Helm Chart 一键部署 Prometheus + Grafana + Alertmanager 全家桶,并深入讲解 ServiceMonitor CRD 如何实现自动化的服务指标发现与采集。

K8s

一、核心概念解析

1.1 Prometheus 架构总览

Prometheus 采用基于 HTTP 的 Pull 模式采集指标数据,其核心组件包括:

  • Prometheus Server:核心服务,负责指标的抓取、存储和查询
  • Alertmanager:告警处理组件,负责告警的去重、分组和路由通知
  • Grafana:可视化看板(kube-prometheus-stack 默认集成)
  • Node Exporter:节点级硬件与 OS 指标采集器
  • kube-state-metrics:Kubernetes 对象状态指标采集器

1.2 kube-prometheus-stack 是什么

kube-prometheus-stack 是 Prometheus 社区维护的 Helm Chart,它将上述所有组件打包为一套开箱即用的监控方案,并预配置了大量 Kubernetes 集群监控的 ServiceMonitor、告警规则和 Grafana 看板。相比手动逐个部署各个组件,使用它可以节省大量配置工作。

1.3 ServiceMonitor CRD

ServiceMonitor 是 Prometheus Operator 引入的自定义资源(CRD),它声明式地定义了”如何从某个 Service 关联的 Pod 中抓取指标”。Prometheus Operator 会自动将所有 ServiceMonitor 转换为 Prometheus 配置文件中的 scrape_configs,实现了配置即代码的指标管理方式。当新的 ServiceMonitor 被创建时,Prometheus 会自动发现并开始采集,无需手动 reload。

二、环境准备

2.1 前置条件确认

确保 K8s 集群状态正常,且有可用的 StorageClass 用于持久化存储:

💻 代码示例

# 检查集群节点状态

kubectl get nodes -o wide

 

# 查看可用的 StorageClass

kubectl get storageclass

 

# 确认 Helm 已安装

helm version

2.2 添加 Helm 仓库

💻 代码示例

# 添加 prometheus-community 仓库

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

 

# 添加 grafana 仓库(用于补充看板依赖)

helm repo add grafana https://grafana.github.io/helm-charts

 

# 更新仓库索引

helm repo update

三、部署 kube-prometheus-stack

3.1 自定义 Values 配置

在生产环境中,我们需要对默认配置进行定制,主要包括存储、资源和 ingress 等方面。创建 monitoring-values.yaml:

💻 代码示例

prometheus:

prometheusSpec:

retention: 15d # 指标保留 15 天

storageSpec:

volumeClaimTemplate:

spec:

storageClassName: standard

accessModes: ["ReadWriteOnce"]

resources:

requests:

storage: 50Gi

serviceMonitorSelectorNilUsesHelmValues: false

serviceMonitorSelector:

monitoring: "enabled" # 只采集带 monitoring=enabled 标签的 ServiceMonitor

podMonitorSelector:

monitoring: "enabled"

 

alertmanager:

config:

route:

receiver: "default"

group_by: ["alertname", "namespace"]

group_wait: 30s

group_interval: 5m

repeat_interval: 4h

 

grafana:

adminPassword: "YourStrongPassword123!"

persistence:

enabled: true

size: 10Gi

storageClassName: standard

service:

type: NodePort

nodePort: 30300

 

nodeExporter:

enabled: true

3.2 执行 Helm 部署

💻 代码示例

# 创建监控命名空间

kubectl create namespace monitoring

 

# 部署 kube-prometheus-stack

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack

–namespace monitoring

–values monitoring-values.yaml

–version 65.x.x

 

# 等待所有 Pod 就绪

kubectl wait –for=condition=Ready pods –all -n monitoring –timeout=300s

3.3 验证部署结果

💻 代码示例

# 查看 monitoring 命名空间下所有资源

kubectl get all -n monitoring

 

# 检查 CRD 是否正确安装

kubectl get crd | grep monitoring

预期输出应包含 prometheuses.monitoring.coreos.com、alertmanagers.monitoring.coreos.com、servicemonitors.monitoring.coreos.com 等多个 CRD。

四、ServiceMonitor 实战配置

4.1 为应用暴露指标端点

首先,确保你的应用 Service 已经暴露了 metrics 端口。以下是一个示例应用的 Deployment 和 Service 定义:

💻 代码示例

apiVersion: apps/v1

kind: Deployment

metadata:

name: demo-api

namespace: default

labels:

app: demo-api

spec:

replicas: 3

selector:

matchLabels:

app: demo-api

template:

metadata:

labels:

app: demo-api

spec:

containers:

– name: api

image: registry.example.com/demo-api:v1.0

ports:

– containerPort: 8080

name: http

– containerPort: 9090

name: metrics # 指标端口

# 模拟 /metrics 端点返回 Prometheus 格式指标

env:

– name: METRICS_PORT

value: "9090"

—

apiVersion: v1

kind: Service

metadata:

name: demo-api

namespace: default

labels:

app: demo-api

monitoring: "enabled" # 关键标签

spec:

selector:

app: demo-api

ports:

– name: http

port: 8080

targetPort: 8080

– name: metrics

port: 9090

targetPort: 9090

4.2 创建 ServiceMonitor

创建 demo-servicemonitor.yaml,让 Prometheus 自动发现并采集该应用的指标:

💻 代码示例

apiVersion: monitoring.coreos.com/v1

kind: ServiceMonitor

metadata:

name: demo-api-monitor

namespace: default

labels:

monitoring: "enabled" # 必须匹配 Prometheus 的 serviceMonitorSelector

spec:

selector:

matchLabels:

app: demo-api # 选择带有此标签的 Service

namespaceSelector:

matchNames:

– default # 只在 default 命名空间中查找

endpoints:

– port: metrics # 对应 Service 中的端口名

interval: 15s # 每 15 秒采集一次

scrapeTimeout: 10s # 单次采集超时

path: /metrics # 指标路径

scheme: http

应用并验证:

💻 代码示例

# 创建 ServiceMonitor

kubectl apply -f demo-servicemonitor.yaml

 

# 查看 ServiceMonitor 状态

kubectl get servicemonitor -n default

 

# 查看 Prometheus 中的 Target 状态

kubectl port-forward -n monitoring svc/kube-prometheus-stack-prometheus 9090:9090 &

curl -s http://localhost:9090/api/v1/targets | python3 -m json.tool | grep -A5 "demo-api"

4.3 自定义指标示例

如果你的应用使用 Python(如 FastAPI),可以通过 prometheus-client 库暴露自定义业务指标:

💻 代码示例

from prometheus_client import Counter, Histogram, generate_latest

from fastapi import FastAPI, Response

 

app = FastAPI()

 

# 定义业务指标

http_requests_total = Counter(

'demo_api_requests_total',

'Total API requests',

['method', 'endpoint', 'status']

)

 

request_duration = Histogram(

'demo_api_request_duration_seconds',

'API request duration in seconds',

['endpoint'],

buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0]

)

 

@app.get("/metrics")

def metrics():

return Response(generate_latest(), media_type="text/plain")

 

@app.get("/api/data")

def get_data():

with request_duration.labels(endpoint="/api/data").time():

http_requests_total.labels(

method="GET", endpoint="/api/data", status="200"

).inc()

return {"data": "ok"}

这样 Prometheus 就能采集到包含请求量、响应延迟分布等业务级指标,为后续的 Grafana 看板和 Argo Rollouts 分析提供数据基础。

五、常见问题与排查

5.1 ServiceMonitor 不生效(Target 显示 down)

现象:ServiceMonitor 已创建但 Prometheus Targets 页面中不显示或状态为 down。

排查步骤:

💻 代码示例

# 1. 确认 ServiceMonitor 标签匹配 Prometheus 的 selector

kubectl get prometheus -n monitoring -o jsonpath='{.spec.serviceMonitorSelector}'

 

# 2. 确认 Service 的标签与 ServiceMonitor 的 selector 匹配

kubectl get svc demo-api –show-labels

 

# 3. 确认指标端点可访问

kubectl exec -it <pod-name> — curl -s http://localhost:9090/metrics

 

# 4. 查看 Prometheus 日志

kubectl logs -n monitoring -l app.kubernetes.io/name=prometheus -c prometheus | tail -20

常见原因包括:ServiceMonitor 标签不匹配、Service 端口名与 ServiceMonitor 的 port 字段不一致、应用未正确暴露 /metrics 端点。

5.2 持久化存储问题

如果 PVC 一直处于 Pending 状态,检查 StorageClass 是否存在且有可用容量:

💻 代码示例

kubectl get pvc -n monitoring

kubectl describe pvc -n monitoring

kubectl get storageclass

5.3 资源占用过高

kube-prometheus-stack 默认会采集大量集群指标,在高规模集群中可能造成内存压力。可通过调整 scrape_interval、减少采集目标、或使用 Thanos 做长期存储降采样来缓解。

六、总结

今天我们完成了 Prometheus 监控体系的核心部署:

  1. 通过 kube-prometheus-stack Helm Chart 一键部署了 Prometheus + Grafana + Alertmanager 全套监控组件
  2. 深入理解了 ServiceMonitor CRD 的工作机制,实现了声明式的指标采集配置
  3. 为示例应用暴露了自定义业务指标,打通了”应用 → Service → ServiceMonitor → Prometheus”的完整采集链路
  4. 掌握了 ServiceMonitor 不生效等常见问题的排查方法

这套监控体系不仅采集了集群基础设施指标(节点 CPU/内存、Pod 状态等),还支持通过 ServiceMonitor 灵活接入业务级自定义指标,为后续的告警、看板以及 Argo Rollouts 渐进式交付的指标分析奠定了数据基础。

下期预告

明天我们将发布 第 12 天:Grafana 看板搭建:K8s 标准面板与自定义业务看板,将今天采集到的海量指标通过 Grafana 看板可视化呈现,包括导入社区标准 K8s 面板、自定义业务看板设计,以及与 Prometheus 数据源的无缝对接。

系列大纲

  1. 全链路架构总览:从代码提交到灰度发布的完整管道设计
  2. K8s 集群与网络基础:kubeadm 离线部署与 Cilium 网络插件
  3. Harbor 私有镜像仓库部署与验证:Helm 安装与镜像推送
  4. GitLab CE 自托管部署:代码仓库与项目管理平台
  5. GitLab Runner 配置:K8s Executor 与 RBAC 权限设置
  6. GitLab CI 流水线搭建:.gitlab-ci.yml 与 Kaniko 无守护进程构建
  7. Harbor 镜像版本管理与 Tag 策略配置
  8. Argo CD 部署与 GitOps 配置仓库创建
  9. CI 与 CD 联动:从代码提交到部署的全自动闭环
  10. SonarQube 代码质量检查:SonarQube 部署与 GitLab CI 集成
  11. Prometheus 部署:kube-prometheus-stack 与 ServiceMonitor 指标采集(今天)
  12. Grafana 看板搭建:K8s 标准面板与自定义业务看板
  13. 告警规则与 Alertmanager:钉钉/邮件通知渠道配置
  14. Argo Rollouts 安装与基础概念:CRD 与 Rollout 资源定义
  15. 金丝雀发布实战:setWeight 流量分割与 pause 步骤
  16. AnalysisTemplate 指标分析与自动回滚机制
  17. 全链路端到端演示:代码提交→构建→代码检查→灰度→监控→告警完整流程
  18. 生产化加固要点:Harbor/GitLab/Argo CD/SonarQube 高可用方案
  19. 供应链安全闭环:Trivy 扫描 + cosign 签名 + Kyverno 验签
微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容