第 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 如何实现自动化的服务指标发现与采集。

一、核心概念解析
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 监控体系的核心部署:
- 通过
kube-prometheus-stackHelm Chart 一键部署了 Prometheus + Grafana + Alertmanager 全套监控组件 - 深入理解了 ServiceMonitor CRD 的工作机制,实现了声明式的指标采集配置
- 为示例应用暴露了自定义业务指标,打通了”应用 → Service → ServiceMonitor → Prometheus”的完整采集链路
- 掌握了 ServiceMonitor 不生效等常见问题的排查方法
这套监控体系不仅采集了集群基础设施指标(节点 CPU/内存、Pod 状态等),还支持通过 ServiceMonitor 灵活接入业务级自定义指标,为后续的告警、看板以及 Argo Rollouts 渐进式交付的指标分析奠定了数据基础。
下期预告
明天我们将发布 第 12 天:Grafana 看板搭建:K8s 标准面板与自定义业务看板,将今天采集到的海量指标通过 Grafana 看板可视化呈现,包括导入社区标准 K8s 面板、自定义业务看板设计,以及与 Prometheus 数据源的无缝对接。
系列大纲
- 全链路架构总览:从代码提交到灰度发布的完整管道设计
- K8s 集群与网络基础:kubeadm 离线部署与 Cilium 网络插件
- Harbor 私有镜像仓库部署与验证:Helm 安装与镜像推送
- GitLab CE 自托管部署:代码仓库与项目管理平台
- GitLab Runner 配置:K8s Executor 与 RBAC 权限设置
- GitLab CI 流水线搭建:.gitlab-ci.yml 与 Kaniko 无守护进程构建
- Harbor 镜像版本管理与 Tag 策略配置
- Argo CD 部署与 GitOps 配置仓库创建
- CI 与 CD 联动:从代码提交到部署的全自动闭环
- SonarQube 代码质量检查:SonarQube 部署与 GitLab CI 集成
- Prometheus 部署:kube-prometheus-stack 与 ServiceMonitor 指标采集(今天)
- Grafana 看板搭建:K8s 标准面板与自定义业务看板
- 告警规则与 Alertmanager:钉钉/邮件通知渠道配置
- Argo Rollouts 安装与基础概念:CRD 与 Rollout 资源定义
- 金丝雀发布实战:setWeight 流量分割与 pause 步骤
- AnalysisTemplate 指标分析与自动回滚机制
- 全链路端到端演示:代码提交→构建→代码检查→灰度→监控→告警完整流程
- 生产化加固要点:Harbor/GitLab/Argo CD/SonarQube 高可用方案
- 供应链安全闭环:Trivy 扫描 + cosign 签名 + Kyverno 验签

















暂无评论内容