Prometheus 面试题
30 道题- 分类
- 可观测性
- 子分类
- metrics
- 题目数
- 30 道
1 Prometheus 的核心架构和设计理念是什么?
答案:
Prometheus 是一款基于拉取(Pull)模型的指标监控和时间序列数据库,遵循开箱即用和自治原则。
核心架构:
graph TD
A["Targets<br/>(Exporters)"] -->|"/metrics (Pull)"| B["Prometheus Server<br/>(TSDB + 采集)"]
B --> C["Alertmanager"]
B --> D["Grafana"]
B --> E["Remote Storage"]
设计理念:
| 原则 | 说明 |
|---|---|
| Pull 模型 | Server 主动拉取目标指标,无需 Agent 主动推送 |
| 自治 | 单个 Server 独立运行,不依赖分布式存储 |
| 标签模型 | 指标通过 Label 标识维度,支持灵活聚合 |
| PromQL | 专有时序查询语言,支持多维分析和聚合 |
| 高效压缩 | 自研 TSDB,块压缩,单节点支持百万活跃序列 |
2 Prometheus 的 Pull 模型和 Push 模型各自的优缺点是什么?
答案:
Prometheus 默认采用 Pull 模型,通过 Pushgateway 和 Remote Write 补充 Push 场景。
对比分析:
| 维度 | Pull 模型 | Push 模型 |
|---|---|---|
| 采集控制 | Server 端控制采集频率 | Client 端控制推送频率 |
| 健康检测 | Pull 超时即判定目标不可用 | Push 中断需额外心跳检测 |
| 防火墙穿越 | 需目标可达 | Client 主动连接,可穿越 NAT |
| 自动发现 | 天然支持(通过 SD) | 需服务注册中心 |
| 扩展性 | 需 LB 层做分片 | 天然分布 |
| 批处理任务 | 任务结束后无法 Pull | Pushgateway 支持 |
| 配置变更 | 修改 scrape_config 即可 | 需修改 Client 端配置 |
适用场景:
Pull 模型:
- 长期运行的 Service/Worker
- K8s 环境(Pod 生命周期匹配)
- 需要健康检测的场景
Push 模型(Pushgateway/Remote Write):
- 批处理任务(CronJob、CI 任务)
- 短生命周期任务
- NAT 网络环境
- 边缘设备采集
3 Prometheus 的四种指标类型(Metric Types)是什么?
答案:
Prometheus Client 库定义四种核心指标类型,各有不同的语义和使用场景。
| 指标类型 | 数据结构 | 典型场景 | 示例 |
|---|---|---|---|
| Counter | 只增不减的累计值 | 请求计数、错误计数 | http_requests_total |
| Gauge | 可增可减的瞬时值 | CPU 使用率、内存使用量 | node_memory_usage_bytes |
| Histogram | 分桶计数 + 总和 + 总数 | 请求延迟分布、响应大小 | http_request_duration_seconds |
| Summary | 分位数计算 + 总和 + 总数 | 延迟分位数(预计算) | http_request_duration_seconds |
Counter 特点:
- 重启后归零,rate() / irate() 函数计算速率
- 不可用于减法运算(需 reset() 处理重置)
Gauge 特点:
- 可直接进行加减运算
- delta() 函数计算时间范围内的变化量
Histogram 与 Summary 区别:
| 维度 | Histogram | Summary |
|---|---|---|
| 分位数计算 | 查询端 (PromQL) | 客户端预计算 |
| 聚合能力 | 支持 sum 聚合 | 不支持聚合 |
| 配置灵活性 | 自定义 Bucket | 自定义分位数 + 衰减窗口 |
| 资源消耗 | Client 端轻量 | Client 端较重 |
| 推荐场景 | 需要跨实例聚合 | 无法接受降精度 |
4 PromQL 的核心函数 rate() 和 irate() 的区别是什么?
答案:
rate() 和 irate() 均为 Counter 类型指标计算每秒增长率,但计算方式不同。
核心区别:
| 维度 | rate() | irate() |
|---|---|---|
| 计算方式 | 区间内平均增长率 | 区间内最后两个样本的瞬时增长率 |
| 对峰值敏感度 | 平滑(平均) | 敏感(捕捉最新变化) |
| 抗噪能力 | 强(区间平均) | 弱(两样本易受毛刺影响) |
| 返回结果 | 始终 >= 0 | 始终 >= 0 |
| 推荐场景 | 告警规则、慢速变化的指标 | 快速变化的指标、短时间窗口 |
示例:
# rate() - 5m 内平均每秒请求数
rate(http_requests_total[5m])
# irate() - 最后两个点的瞬时速率
irate(http_requests_total[5m])
选择建议:
rate():
- 告警规则(避免峰值误告警)
- 容量规划(关注趋势而非毛刺)
- 长时间窗口(1h/1d)的聚合
irate():
- Grafana 图表(显示更精细的曲线)
- 短时间窗口的快速指标
- 故障排查(观察最新变化)
5 Prometheus TSDB 的存储结构是什么样的?
答案:
Prometheus TSDB 采用块存储(Block)结构,按时间窗口组织数据,支持高效压缩和查询。
存储目录结构:
/data/
├── 01EM6Q6A1Z1Z1Z1Z1Z1Z1Z1Z1Z1/ # Block 目录(ULID 命名)
│ ├── chunks/
│ │ └── 000001 # 压缩后的样本数据块
│ ├── index # 倒排索引(Label → Series)
│ ├── meta.json # Block 元数据(时间范围、样本数)
│ ├── tombstones # 删除标记
│ └── wal/ # WAL(预写日志)
│ ├── 000001.wal
│ └── 000002.wal
├── 01EM6Q6A1Z1Z1Z1Z1Z1Z1Z1Z1Z2/
├── chunks_head/ # 当前正在写入的 chunk
│ └── 000001
├── wal/ # 当前 WAL
│ ├── 000003.wal
│ └── 000004.wal
└── lock # 文件锁
写入流程:
```mermaid
graph TD
A["样本到达"] --> B["内存中 Head Chunk"]
B -->|"写入 WAL(故障恢复)"| WAL["WAL"]
B --> C["Head Chunk 满 2h"]
C --> D["冻结"]
D --> E["写入磁盘 Block"]
E --> F["Block 压缩"]
F --> G["合并"]
G --> H["删除过期 Block"]
**压缩合并:**
原始 Block(2h 块): Block-A (14:00-16:00) Block-B (16:00-18:00) Block-C (18:00-20:00) Block-D (20:00-22:00)
合并后(10h 块): Block-ABCD (14:00-22:00) → 更小的总体积,更快的查询
6 Prometheus 的服务发现(Service Discovery)机制有哪些?
答案:
Prometheus 支持多种服务发现机制,动态管理采集目标。
支持的服务发现:
| 服务发现类型 | 适用场景 | 刷新机制 |
|---|---|---|
| kubernetes_sd_configs | K8s Pod/Service/Endpoint | Watch API 实时更新 |
| consul_sd_configs | Consul 注册中心 | Watch/轮询 |
| file_sd_configs | 文件方式定义 Target | 文件修改自动刷新 |
| dns_sd_configs | DNS SRV 记录 | DNS 轮询 |
| ec2_sd_configs | AWS EC2 实例 | API 轮询 |
| azure_sd_configs | Azure VM | API 轮询 |
| gce_sd_configs | GCP GCE 实例 | API 轮询 |
| openstack_sd_configs | OpenStack 实例 | API 轮询 |
| nerve_sd_configs | Airbnb Nerve | ZK 监听 |
| serverset_sd_configs | Google Serverset | ZK 监听 |
| triton_sd_configs | Joyent Triton | API 轮询 |
| eureka_sd_configs | Netflix Eureka | API 轮询 |
| docker_sd_configs | Docker 容器 | Docker API |
| digitalocean_sd_configs | DigitalOcean Droplets | API 轮询 |
| http_sd_configs | HTTP 接口 | HTTP 轮询 |
K8s SD 示例:
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
action: keep
regex: myapp
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
file_sd 示例:
scrape_configs:
- job_name: 'file-based-targets'
file_sd_configs:
- files:
- /etc/prometheus/targets/*.json
refresh_interval: 5m
7 Prometheus relabeling 机制的作用和常见用法是什么?
答案:
Relabeling 是 Prometheus 在采集前对 Target 标签进行动态修改、过滤和重命名的机制。
Relabeling 动作:
| 动作 | 作用 | 示例 |
|---|---|---|
| replace | 替换标签值(默认) | 修改标签名或值 |
| keep | 保留匹配的 Target | 过滤掉不符合条件的 Target |
| drop | 丢弃匹配的 Target | 排除特定 Target |
| hashmod | 对源标签值做 Hash 取模 | 用于分片 |
| labelmap | 匹配并映射标签 | 将 _meta* 标签改为最终标签 |
| labeldrop | 删除匹配的标签 | 删除高基数标签 |
| labelkeep | 保留匹配的标签 | 仅保留需要的标签 |
| keepequal | 保留值相等的 Target | 条件保留 |
| dropequal | 丢弃值相等的 Target | 条件丢弃 |
常见用法:
relabel_configs:
# 1. 只采集带有 annotation 的 Pod
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
# 2. 设置采集路径
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
# 3. 映射 K8s 标签到最终标签
- source_labels: [__meta_kubernetes_pod_label_app]
action: replace
target_label: app
# 4. 删除高基数标签
- regex: "__meta_kubernetes_pod_uid|__meta_kubernetes_pod_controller_uid"
action: labeldrop
# 5. 保留特定标签
- regex: "app|component|tier|namespace"
action: labelkeep
执行顺序:
1. 从 SD 获取 __meta_* 标签
2. 应用 relabel_configs(顺序执行)
3. 应用 metric_relabel_configs
4. 写入 TSDB
8 Prometheus 告警规则的生命周期和管理方式是什么?
答案:
Prometheus 告警从规则评估到通知经过多个状态转换。
告警状态机:
graph TD
START["评估规则"] --> PENDING["Pending<br/>首次触发(未到 for 持续时间)"]
PENDING -->|"for 持续期间"| FIRING["Firing<br/>持续触发(发送通知)"]
FIRING -->|"规则恢复(不再触发)"| RESOLVED["Resolved<br/>已解决(可选发送)"]
RESOLVED --> DONE["(恢复正常)"]
告警规则示例:
groups:
- name: node-alerts
interval: 10s
rules:
- alert: NodeCPUUsageHigh
expr: (100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "Node XQOPEN $labels.instance XQCLOSE CPU usage > 80%"
description: "Node XQOPEN $labels.instance XQCLOSE CPU usage is XQOPEN $value | humanizePercentage XQCLOSE"
- alert: NodeDiskSpaceFull
expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.1
for: 10m
labels:
severity: critical
annotations:
summary: "Node XQOPEN $labels.instance XQCLOSE disk space < 10%"
Alertmanager 配置:
route:
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'pagerduty'
- match:
severity: warning
receiver: 'slack'
receivers:
- name: 'pagerduty'
pagerduty_configs:
- routing_key: <key>
- name: 'slack'
slack_configs:
- api_url: <webhook>
channel: '#alerts'
9 Prometheus 的记录规则(Recording Rules)有什么作用?
答案:
Recording Rules 预计算复杂或高频查询的 PromQL 表达式,将结果存储为新的时间序列,降低查询延迟和 Server 负载。
使用场景:
| 场景 | 说明 | 示例 |
|---|---|---|
| 复杂计算 | 耗时长或复杂的 PromQL | 百分比计算、多层聚合 |
| Dashboard 加速 | Grafana 面板频繁查询 | 预计算后直接查询 |
| 聚合降精度 | 高精度 → 低精度 | 原始 15s → 5m 聚合 |
| 跨实例聚合 | 多实例汇总 | 集群级别指标 |
配置示例:
groups:
- name: node-recording
interval: 1m
rules:
- record: node:node_cpu_utilization:ratio
expr: (1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])))
- record: node:node_memory_utilization:ratio
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
- record: node:node_disk_utilization:ratio
expr: (1 - avg by(instance, device) (rate(node_disk_io_time_seconds_total[5m])))
最佳实践:
命名规范: level:metric:aggregation
例如: node:node_cpu_utilization:ratio
- level: 数据来源层(node/container/service)
- metric: 指标名称
- aggregation: 聚合方式(ratio/avg/p99/rate)
注意事项:
- 避免递归引用
- 设置合适的评估间隔
- 监控记录规则的性能和资源消耗
- 及时清理不再使用的记录规则
10 Prometheus 的 Remote Write 和 Remote Read 机制是什么?
答案:
Remote Write/Read 是 Prometheus 与外部存储系统交互的标准协议,分别实现数据导出和查询。
Remote Write:
```mermaid
graph TD
A["Prometheus Server"] -->|"Remote Write<br/>Snappy 压缩 + Protobuf 编码"| B["接收端<br/>Cortex / Thanos Receiver / VictoriaMetrics"]
B --> C["长期存储 / 全局视图"]
**配置:**
```yaml
remote_write:
- url: "http://thanos-receiver:19291/api/v1/receive"
name: "thanos-receive"
write_relabel_configs:
- source_labels: [__name__]
regex: "node_.*"
action: keep
queue_config:
capacity: 2500
max_samples_per_send: 500
batch_send_deadline: 5s
min_backoff: 30ms
max_backoff: 100ms
Remote Read:
remote_read:
- url: "http://thanos-query:9090/api/v1/read"
read_recent: true
required_matchers:
job: "node"
对比分析:
| 维度 | Remote Write | Remote Read |
|---|---|---|
| 数据流向 | Prometheus → 外部存储 | 外部存储 → Prometheus |
| 协议 | Snappy + Protobuf | Snappy + Protobuf |
| 可靠性 | 队列 + 重试机制 | 直接查询 |
| 典型用途 | 长期存储、全局聚合 | 历史数据回查 |
| 性能影响 | 异步写入,低影响 | 取决于远程存储延迟 |
注意事项:
Remote Write:
- 失败数据本地保留(队列持久化)
- 配置 write_relabel_configs 控制写入范围
- 监控 remote_storage_queue_highest_sent_timestamp_seconds
Remote Read:
- 默认不查询远程(仅本地)
- 设置 read_recent=true 包含近期数据
- 查询性能取决于远程存储
11 Prometheus 的 High Cardinality(高基数)问题是什么?如何解决?
答案:
高基数指时间序列的标签组合数量过大,导致 TSDB 性能和资源消耗急剧增加。
高基数的影响:
| 指标 | 正常(< 10 万序列) | 高基数(> 100 万序列) | 极高基数(> 1000 万序列) |
|---|---|---|---|
| 内存 | < 2GB | 8-16GB | 32GB+ |
| 查询延迟 | < 100ms | 1-5s | 30s+ |
| TSDB 压缩 | 正常 | 缓慢 | 失败 |
| 磁盘 IO | 低 | 高 | 极高 |
常见高基数场景:
1. URL 路径作为标签(/api/users/123 → 每个用户一个序列)
2. Request ID/UUID 作为标签
3. 用户 ID / Session ID 作为标签
4. 精确时间戳作为标签
5. IP 地址 + Port 组合
解决方案:
# 1. Relabel 丢弃高基数标签
metric_relabel_configs:
- source_labels: [__name__]
regex: "http_request_duration_seconds"
action: keep
- source_labels: [url]
regex: "/api/users/[0-9]+"
replacement: "/api/users/{id}"
action: replace
# 2. 聚合降精度(Recording Rules)
record: service:http_requests_total:rate5m
expr: sum by(service, method, status) (rate(http_requests_total[5m]))
# 3. 限制采集标签数
scrape_configs:
- job_name: 'myapp'
params:
collect[]: ['default']
relabel_configs:
- regex: "request_id|session_id|user_id"
action: labeldrop
监控高基数:
# 时间序列数量
count by (__name__) ({__name__=~".+"})
# 标签基数
count(count by (url) (http_requests_total))
# 内存中序列数
prometheus_tsdb_head_series
12 Prometheus 联邦(Federation)机制的工作原理是什么?
答案:
Prometheus 联邦允许一个 Prometheus Server 从另一个 Prometheus Server 拉取聚合后的指标,实现层级式的监控架构。
联邦层级:
全局 Prometheus(Global View)
│
├── 区域 Prometheus-A(Region-A)
│ ├── 节点采集器(Node Exporters)
│ └── 应用采集器(App Exporters)
│
├── 区域 Prometheus-B(Region-B)
│ ├── 节点采集器
│ └── 应用采集器
│
└── Service Mesh Prometheus
└── 服务指标
配置:
# 全局 Prometheus 配置(从区域 Prometheus 拉取聚合指标)
scrape_configs:
# 联邦采集(拉取预聚合指标)
- job_name: 'federate-region-a'
scrape_interval: 30s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{__name__=~"node:.*"}'
- '{__name__=~"service:.*"}'
static_configs:
- targets:
- 'prometheus-region-a:9090'
- job_name: 'federate-region-b'
scrape_interval: 30s
metrics_path: '/federate'
params:
'match[]':
- '{__name__=~"node:.*"}'
static_configs:
- targets:
- 'prometheus-region-b:9090'
联邦模式对比:
| 模式 | 描述 | 适用场景 |
|---|---|---|
| 层级联邦 | 上层 Pull 下层聚合指标 | 多数据中心、多团队 |
| 跨服务联邦 | 一个服务 Pull 另一个服务的指标 | Service Mesh 场景 |
| 对等联邦 | 互为联邦实现高可用 | 小规模 HA |
注意事项:
1. honor_labels: true 保持原始标签
2. 只采集聚合指标,避免原始指标重复
3. 全局 Prometheus 资源消耗较低(仅存储聚合数据)
4. 区域性 Prometheus 故障不影响全局视图
5. 联邦非实时,存在数据延迟(取决于 scrape_interval)
13 Prometheus 的 Operator 模式(Prometheus Operator)是什么?
答案:
Prometheus Operator 是基于 Kubernetes Operator 模式的 Prometheus 管理方案,通过 CRD 简化 Prometheus 集群的部署和管理。
核心 CRD:
| CRD | 作用 | 说明 |
|---|---|---|
| Prometheus | Prometheus Server 实例 | 定义副本数、资源、存储、配置 |
| Alertmanager | Alertmanager 实例 | 定义集群配置、模板 |
| ServiceMonitor | Service 的指标采集配置 | 基于 Service label 选择目标 |
| PodMonitor | Pod 的指标采集配置 | 直接采集 Pod 指标 |
| PrometheusRule | 告警和记录规则 | Prometheus 规则管理 |
| Probe | Blackbox Exporter 探针 | 网络探测配置 |
| AlertmanagerConfig | Alertmanager 接收者配置 | 路由、接收者、抑制规则 |
ServiceMonitor 示例:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: example-app
spec:
selector:
matchLabels:
app: example-app
endpoints:
- port: http
interval: 15s
path: /metrics
namespaceSelector:
matchNames:
- default
Prometheus CRD 示例:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: k8s
spec:
replicas: 2
resources:
requests:
memory: 4Gi
storage:
volumeClaimTemplate:
spec:
storageClassName: ssd
resources:
requests:
storage: 100Gi
serviceMonitorSelector:
matchLabels:
app: monitored
ruleSelector:
matchLabels:
role: alert-rules
14 Prometheus 的数据保留和数据压缩机制是什么?
答案:
Prometheus 通过块合并、压缩和保留策略管理 TSDB 的数据生命周期。
保留策略配置:
# 启动参数
--storage.tsdb.retention.time=15d # 数据保留时间(默认 15d)
--storage.tsdb.retention.size=100GB # 数据保留大小限制
--storage.tsdb.retention.size=0 # 0=不限大小
压缩合并流程:
graph TD
subgraph "2h 块"
A["Block-A<br/>14:00-16:00"]
B["Block-B<br/>16:00-18:00"]
C["Block-C<br/>18:00-20:00"]
D["Block-D<br/>20:00-22:00"]
end
A --> AB["Block-A+B<br/>10h 块"]
B --> AB
C --> CD["Block-C+D"]
D --> CD
AB --> ABCD["Block-A+B+C+D<br/>合并最终块"]
CD --> ABCD
压缩级别:
| 级别 | 块大小 | 压缩比例 | 说明 |
|---|---|---|---|
| L1 | 2h | 原始数据 | 最新数据,不压缩 |
| L2 | 10h | ~2:1 | 第一次合并 |
| L3 | 50h | ~4:1 | 第二次合并 |
| L4 | 250h | ~8:1 | 最终压缩 |
磁盘空间计算:
8 个样本/序列 × 16 bytes = 128 bytes/原始样本
压缩后平均 ~1.3 bytes/样本
估算公式:
序列数 × 样本数 × 1.3 bytes = 存储大小
示例:
100 万序列 × 15s 间隔 × 15d
= 100万 × (86400/15 × 15) × 1.3
≈ 100万 × 86400 × 1.3
≈ 112GB
15 Prometheus 的内存使用和性能优化策略是什么?
答案:
Prometheus 的内存消耗主要来自 TSDB Head 中活跃的时间序列数据。
内存消耗模型:
内存 ≈ 活跃序列数 × 每个序列占用(~2KB)
分解:
- 倒排索引: ~序列数 × 标签数 × 100 bytes
- Head Chunk: ~序列数 × (chunk 大小) = ~序列数 × 1KB
- WAL 缓存: ~序列数 × 0.5KB
- 查询缓存: 额外开销
优化策略:
# 1. 启动参数优化
--storage.tsdb.min-block-duration=2h # 默认 2h
--storage.tsdb.max-block-duration=48h # 最大块大小
--storage.tsdb.retention.time=15d
--storage.tsdb.retention.size=100GB
# 2. 资源限制
--memory.series=500000 # 最大序列数限制
--memory.chunks=500000 # 最大 chunk 数限制
# 3. 采集优化
scrape_configs:
- job_name: 'myapp'
scrape_interval: 30s # 降低采集频率
scrape_timeout: 10s
relabel_configs:
- action: labeldrop # 丢弃高基数标签
regex: "tmp|temp|request_id"
监控内存:
# TSDB Head 序列数
prometheus_tsdb_head_series
# 内存中的 Chunk 数
prometheus_tsdb_head_chunks
# 内存使用率
process_resident_memory_bytes / process_virtual_memory_bytes
# 每个序列的内存估算
process_resident_memory_bytes / prometheus_tsdb_head_series
16 Prometheus 在 K8s 中的采集方式有哪几种?
答案:
Prometheus 在 K8s 中支持多种角色的服务发现和数据采集。
采集角色:
| 角色 | 采集范围 | 说明 |
|---|---|---|
| pod | 单个 Pod | 采集 Pod 中容器的 metrics 端点 |
| service | Service 后端 | 采集 Service 背后的 Pod |
| endpoints | Endpoint 对象 | 采集 Endpoint 关联的 Pod |
| ingress | Ingress 对象 | 采集 Ingress 的指标 |
| node | 节点 | 采集 Node Exporter 等节点指标 |
完整配置示例:
scrape_configs:
# 1. Pod 采集(基于 annotation)
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
# 2. Service 采集(基于 label)
- job_name: 'kubernetes-services'
kubernetes_sd_configs:
- role: service
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: "true"
# 3. Node 采集
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# 4. Kubelet 采集
- job_name: 'kubernetes-kubelet'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/$1/proxy/metrics
17 Prometheus 的 Alertmanager 集群模式是如何工作的?
答案:
Alertmanager 通过 Gossip 协议实现集群节点间的告警去重、分组和静默同步。
集群架构:
graph TD
PROM["Prometheus"] -->|"Alert"| AM["Alertmanager"]
AM --> GOSSIP["Gossip (Mesh)"]
GOSSIP --> A["A"]
GOSSIP --> B["B"]
GOSSIP --> C["C"]
AM --> SLACK["Slack"]
AM --> EMAIL["Email"]
集群配置:
# Alertmanager 启动参数(三个节点)
alertmanager --cluster.listen-address=0.0.0.0:9094 \
--cluster.peer=alertmanager-0:9094 \
--cluster.peer=alertmanager-1:9094 \
--cluster.peer=alertmanager-2:9094 \
--config.file=/etc/alertmanager/alertmanager.yml
Prometheus 端配置:
# 配置多个 Alertmanager
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager-0:9093
- alertmanager-1:9093
- alertmanager-2:9093
scheme: http
timeout: 10s
api_version: v2
工作机制:
1. Prometheus 将告警发送到所有 Alertmanager 节点
2. Alertmanager 通过 Gossip 同步告警通知状态
3. 已发送的通知不会被重复发送(去重)
4. 一个节点故障,其他节点继续处理
5. 分组和抑制规则在所有节点一致
Gossip 同步内容:
- 告警通知的已发送状态
- 静默规则
- 节点成员变更
18 Prometheus 的 HTTP API 支持哪些操作?
答案:
Prometheus 提供完整的 HTTP API,覆盖数据查询、元数据管理和管理操作。
API 端点:
| 端点 | 方法 | 用途 |
|---|---|---|
| /api/v1/query | GET/POST | 瞬时查询 |
| /api/v1/query_range | GET/POST | 范围查询 |
| /api/v1/series | GET/POST | 序列匹配查询 |
| /api/v1/labels | GET | 标签名列表 |
| /api/v1/label/{name}/values | GET | 标签值列表 |
| /api/v1/metadata | GET | 指标元数据 |
| /api/v1/alerts | GET | 活跃告警 |
| /api/v1/rules | GET | 规则列表 |
| /api/v1/targets | GET | 采集目标状态 |
| /api/v1/targets/metadata | GET | 目标元数据 |
| /api/v1/query_exemplars | GET/POST | Exemplar 查询 |
| /api/v1/status/config | GET | 运行时配置 |
| /api/v1/status/tsdb | GET | TSDB 状态 |
| /api/v1/status/buildinfo | GET | 构建信息 |
| /api/v1/status/runtimeinfo | GET | 运行时信息 |
| /api/v1/admin/tsdb/snapshot | POST | 创建快照 |
| /api/v1/admin/tsdb/delete_series | POST | 删除序列 |
| /api/v1/admin/tsdb/clean_tombstones | POST | 清理墓碑 |
查询示例:
# 瞬时查询
curl 'http://localhost:9090/api/v1/query?query=up{job="node"}&time=1717000000'
# 范围查询
curl 'http://localhost:9090/api/v1/query_range?query=rate(http_requests_total[5m])&start=1717000000&end=1717003600&step=15'
# 标签值查询
curl 'http://localhost:9090/api/v1/label/__name__/values'
# 创建快照
curl -XPOST 'http://localhost:9090/api/v1/admin/tsdb/snapshot'
19 Prometheus 的 WAL(Write-Ahead Log)机制是什么?
答案:
WAL 是 Prometheus TSDB 的预写日志,用于确保数据持久性和故障恢复。
WAL 结构:
/data/wal/
├── 000001.wal # WAL 文件(按序号递增)
├── 000002.wal
├── 000003.wal
└── checkpoint.000002/ # WAL 检查点
├── 000000.wal
└── 000001.wal
写入流程:
```mermaid
graph TD
A["样本到达"] --> B["写入 WAL(先写日志)"]
B --> C["写入内存 Head Chunk(后写数据)"]
C --> D["批量提交(2h 后冻结)"]
D --> E["冻结 Chunk"]
E --> F["删除对应 WAL 段"]
F --> G["写入 Block"]
**故障恢复:**
正常启动: WAL → 回放到 Head Chunk → 恢复内存状态
非正常关闭: 扫描 WAL → 找到未冻结的样本 → 重建 Head Chunk 丢弃不完整的 WAL 段 → 确保数据一致性
WAL 损坏: 自动截断损坏的 WAL 段 记录错误日志: “WAL segment corrupted” 丢失损坏段的数据
**WAL 配置:**
```bash
--storage.tsdb.wal-compression # WAL 压缩(默认开启)
--storage.tsdb.wal-segment-size=128MB # WAL 段大小(默认 128MB)
20 Prometheus 的 staleness(数据过期机制)是如何判断的?
答案:
Prometheus 通过样本的最后更新时间判断时间序列是否过期(staleness)。
过期判定规则:
默认过期时间: 5 分钟(从最新样本开始)
判定逻辑:
当前时间 - 最新样本的时间戳 > 5m → 标记为 stale
标记为 stale 后 → 查询中不返回该序列
Stale Marker:
目标离线时,Prometheus 写入一个 Stale NaN
Stale Marker 后的序列在下次采集前不可见
Stale 影响:
# 查询结果受 stale 影响
up{job="node"} # 如果 node 离线 >5m → 不返回结果
# rate() 函数对 stale 的处理
rate(http_requests_total[5m]) # 5m 窗口内无新数据 → 返回 0
# 使用 offset 可以查询即使被 staleness 的数据
up offset 10m # 查 10 分钟前的数据
避免 Stale 影响:
# 对于 pushgateway 这类非持续采集的目标
scrape_configs:
- job_name: 'pushgateway'
honor_labels: true
static_configs:
- targets: ['pushgateway:9091']
# 使用 keep_dropped_targets 配置保留周期
21 Prometheus 的 Label 模型和设计要求是什么?
答案:
Prometheus 的标签模型是其多维数据模型的基础,设计上遵循特定的约束和最佳实践。
标签模型约束:
| 约束项 | 规则 |
|---|---|
| 标签名 | 字母、数字、下划线,长度 <= 256 |
| 标签值 | 任意 UTF-8 字符串 |
| __ 前缀 | 系统保留标签(name、metrics_path 等) |
| 标签数量 | 无硬限制(实际受性能和基数约束) |
| 唯一标识 | 指标名 + 所有标签的组合唯一标识一个时间序列 |
内置标签:
| 标签 | 含义 |
|---|---|
| name | 指标名 |
| address | 采集地址(host:port) |
| metrics_path | Metrics 路径 |
| scheme | 协议(http/https) |
| scrape_interval | 采集间隔 |
| scrape_timeout | 采集超时 |
| job | 作业名 |
| instance | 实例(默认 address) |
标签设计原则:
最佳实践:
- 标签基数控制在 < 100 个唯一值
- 区分维度(service、method、status)而非实体(user_id、request_id)
- 统一命名风格(蛇形命名)
- 标签值有界(method ∈ [GET,POST,PUT,DELETE])
- 避免在标签中嵌入可变信息(IP、时间戳)
反例:
http_requests_total{user_id="12345", request_id="abc-def", timestamp="1717000000"}
→ 每个请求产生新序列,基数爆炸
正例:
http_requests_total{service="api-gateway", method="GET", status="200"}
→ 序列数有限,可聚合
22 Prometheus 的 scrape_interval 和 evaluation_interval 的关系是什么?
答案:
scrape_interval 控制数据采集频率,evaluation_interval 控制规则评估频率,两者既有协作也有约束。
定义:
| 参数 | 作用 | 默认值 | 影响 |
|---|---|---|---|
| scrape_interval | 每秒采集一次目标 | 1m | 数据精度和存储量 |
| evaluation_interval | 每间隔评估一次规则 | 1m | 告警响应延迟 |
约束关系:
规则评估不能快于数据采集:
evaluation_interval >= scrape_interval
否则规则评估时取到的是重复的旧数据
PromQL 窗口大小建议 >= 4 × scrape_interval:
rate(metric[5m]) 对 15s 采集间隔是合理的(20 个样本点)
rate(metric[1m]) 对 15s 采集间隔偏小(4 个样本点)
规则配置:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- 'alerts.yml'
- 'recording.yml'
groups:
- name: example
interval: 30s # 覆盖全局 evaluation_interval
rules:
- alert: ...
23 Prometheus 的 textfile collector 有什么用?
答案:
Textfile Collector 是 Node Exporter 等组件的辅助功能,允许将非标准格式的指标通过文件方式暴露给 Prometheus。
工作机制:
```mermaid
graph TD
A["批处理/CronJob"] --> B["生成 .prom 文件<br/>(自定义指标格式)"]
B --> C["Node Exporter 定期读取<br/>(--collector.textfile.directory)"]
C --> D["与 Node Exporter 指标合并"]
D --> E["Prometheus 采集 /metrics"]
**使用场景:**
CronJob 执行结果指标
- 备份成功/失败计数
- 日志轮转状态
- 系统维护任务状态
自定义系统指标
- RAID 阵列状态
- 硬件健康检测
- 许可证到期日
遗留系统指标
- Shell 脚本采集的指标
- 不支持 Prometheus Client 的应用
**配置示例:**
```bash
# Node Exporter 启动
./node_exporter --collector.textfile.directory=/var/lib/node_exporter/textfile
# CronJob 生成指标
#!/bin/bash
echo "# HELP backup_last_success Backups last success timestamp" > /var/lib/node_exporter/textfile/backup.prom
echo "# TYPE backup_last_success gauge" >> /var/lib/node_exporter/textfile/backup.prom
echo "backup_last_success $(date +%s)" >> /var/lib/node_exporter/textfile/backup.prom
文本文件格式:
# HELP my_metric Description
# TYPE my_metric gauge
my_metric{label="value"} 42 1717000000
24 Prometheus 的 Pushgateway 的正确使用方式是什么?
答案:
Pushgateway 是 Prometheus Push 模型的关键组件,允许批处理任务和短生命周期任务推送指标。
架构:
```mermaid
graph TD
A["批处理任务"] -->|"Push<br/>HTTP PUT/POST"| B["Pushgateway (:9091)"]
B -->|"Pull<br/>/metrics"| C["Prometheus Server"]
**正确场景 vs 错误场景:**
| 场景 | 是否推荐 | 原因 |
|------|---------|------|
| **CronJob 执行结果** | 推荐 | 任务执行完即消失 |
| **CI/CD 流水线** | 推荐 | Pipeline 执行状态 |
| **批处理脚本** | 推荐 | 无法长期运行 |
| **Service 指标** | 不推荐 | 应使用 Pull 模型 |
| **高频率指标** | 不推荐 | Pushgateway 成为瓶颈 |
| **实例级指标** | 不推荐 | 无法区分实例 |
**操作示例:**
```bash
# 推送单个指标
echo "job_duration_seconds 42.5" | curl --data-binary @- http://pushgateway:9091/metrics/job/myjob
# 推送带标签的指标
cat <<EOF | curl --data-binary @- http://pushgateway:9091/metrics/job/myjob/instance/myinstance
# TYPE job_success gauge
job_success{status="completed"} 1
# TYPE job_duration_seconds gauge
job_duration_seconds 42.5
EOF
# 删除 job 的所有指标
curl -X DELETE http://pushgateway:9091/metrics/job/myjob
注意事项:
1. Pushgateway 是"指标缓存",不持久化
2. 务必在任务结束时 DELETE 清理指标
3. Pushgateway 不是 Prometheus 的替代品
4. 使用 honor_labels: true 保留 job/instance 标签
5. 监控 Pushgateway 自身指标(pushgateway_metrics_total)
25 Prometheus 的 blackbox exporter 支持的探测方式有哪些?
答案:
Blackbox Exporter 是 Prometheus 生态中用于网络探测的组件,支持多种协议的目标可达性和质量检测。
探测模块:
| 模块 | 协议 | 探测方式 | 典型场景 |
|---|---|---|---|
| http_2xx | HTTP/HTTPS | GET/HEAD 请求 | Web 服务可用性 |
| http_post_2xx | HTTP/HTTPS | POST 请求 | API 端点检测 |
| tcp_connect | TCP | TCP 端口连接 | 端口可用性 |
| icmp | ICMP | Ping 探测 | 主机连通性 |
| dns | DNS | DNS 查询 | DNS 解析质量 |
| grpc | gRPC | gRPC 健康检查 | gRPC 服务检测 |
| ssh | SSH | SSH 握手 | SSH 服务检测 |
| tls | TLS | TLS 握手 | 证书过期检测 |
配置示例:
# blackbox-exporter 配置
modules:
http_2xx:
prober: http
timeout: 5s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2"]
valid_status_codes: [200, 301, 302]
preferred_ip_protocol: "ip4"
tcp_connect:
prober: tcp
timeout: 5s
icmp:
prober: icmp
timeout: 5s
icmp:
preferred_ip_protocol: "ip4"
dns:
prober: dns
dns:
query_name: "example.com"
query_type: "A"
valid_rcodes: [NOERROR]
Prometheus 采集配置:
scrape_configs:
- job_name: 'blackbox-http'
metrics_path: /probe
params:
module: [http_2xx]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
static_configs:
- targets:
- 'https://example.com'
- 'https://api.example.com/health'
- job_name: 'blackbox-icmp'
metrics_path: /probe
params:
module: [icmp]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
static_configs:
- targets:
- '192.168.1.1'
- '10.0.0.1'
26 Prometheus 的高可用方案有哪几种?
答案:
Prometheus 的高可用方案从简单的主备到全局聚合,不同方案在一致性、资源消耗和复杂度上各有取舍。
方案对比:
| 方案 | 架构 | 数据一致性 | 复杂度 | 适用规模 |
|---|---|---|---|---|
| 双跑(Dual Run) | 两个 Prometheus 采集相同 Target | 最终一致 | 低 | 小型 |
| HA Pair + 联邦 | 主备 + 上层联邦聚合 | 最终一致 | 中 | 中型 |
| Thanos | Sidecar + 对象存储 | 强一致 | 中 | 中大型 |
| VictoriaMetrics | VMCluster 架构 | 强一致 | 低 | 大/超大型 |
| Cortex | 微服务架构 | 强一致 | 高 | 大型 |
双跑方案:
graph TD
TA["Target-A"] --> P1["Prom-1"]
TB["Target-B"] --> P2["Prom-2"]
P1 --> GRAFANA["Grafana<br/>(PromQL 聚合)"]
P2 --> GRAFANA
Thanos 方案:
graph TD
TA["Target-A"] --> P1["Prom-1<br/>+Sidecar"]
TB["Target-B"] --> P2["Prom-2<br/>+Sidecar"]
P1 --> TQ["Thanos<br/>Query"]
P2 --> TQ
TQ --> G["Grafana"]
关键指标:
双跑:
- RTO: 分钟级(切换查询源)
- RPO: 近零(双写)
- 资源: 2× 存储和计算
Thanos:
- RTO: 秒级(Query 无状态)
- RPO: 近零(对象存储)
- 资源: Prometheus + Sidecar + 对象存储
VictoriaMetrics:
- RTO: 秒级(无状态组件)
- RPO: 近零(副本机制)
- 资源: VictoriaMetrics 集群
27 Prometheus 的 TSDB 索引结构是怎么样的?
答案:
Prometheus TSDB 的索引采用倒排索引结构,支持高效的标签条件查询。
索引层次:
graph TD
subgraph "1. 符号表 Symbol Table"
A["'up' → ID=1<br/>'job' → ID=2<br/>'instance' → ID=3<br/>'api-server' → ID=4<br/>'localhost:9090' → ID=5<br/>..."]
end
subgraph "2. 倒排索引 Posting"
B["job='api-server' → [1,5,10,15,...]<br/>instance='local' → [1,2,3,4,...]<br/>__name__='up' → [1,2,5,8,...]"]
end
subgraph "3. 序列文件 Series"
C["Series ID: 1<br/>Labels: job='api-server'<br/>instance='localhost:9090'<br/>Chunks: [chunk1, chunk2]"]
end
A --> B --> C
查询执行路径:
up{job="api-server", instance="localhost:9090"}
1. 查找 __name__="up" → Posting List A [1, 2, 5, 8]
2. 查找 job="api-server" → Posting List B [1, 5, 10, 15]
3. 查找 instance="localhost:9090" → Posting List C [1, 2, 3]
4. Intersect(A, B, C) → [1]
5. 通过 Series ID=1 获取 Chunk 和样本数据
28 Prometheus 的 Exemplar 机制是什么?
答案:
Exemplar 是 OpenMetrics 标准的一部分,允许在时序数据中嵌入对应用层 Trace 的引用,实现 Metrics 到 Trace 的关联。
Exemplar 结构:
格式:
metric_name{labels} value timestamp # {trace_id="abc123", span_id="def456"} 42
示例:
http_request_duration_seconds_bucket{method="GET",le="0.1"} 15 1717000000 # {trace_id="abc123", span_id="def456"} 0.095
配置:
# Prometheus Server 开启 Exemplar 存储
--enable-feature=exemplar-storage
# 存储配置(默认 100000 个 Exemplar)
--storage.tsdb.exemplar-exemplars-per-series=100
查询 Exemplar:
# 查询 Exemplar 数据
http_request_duration_seconds_bucket{trace_id="abc123"}
# API 查询
GET /api/v1/query_exemplars?query=http_request_duration_seconds_bucket
应用场景:
1. 高延迟请求 → 查看具体 Trace
发现 P99 延迟 > 1s,通过 Exemplar 找到对应的 Trace ID
2. 错误请求 → 关联详细日志
Metrics 显示错误率升高,查 Exemplar 获取 Trace ID
3. 慢查询追踪
Database 延迟异常,关联到具体的查询 Trace
29 Prometheus 的查询性能优化策略有哪些?
答案:
Prometheus 查询性能受数据量、时间范围和查询复杂度影响,优化策略覆盖查询语句和架构层面。
查询优化:
| 策略 | 方法 | 效果 |
|---|---|---|
| 减少时间范围 | 缩小查询窗口 | 减少扫描的数据量 |
| 使用记录规则 | 预计算复杂查询 | 秒级响应 |
| 精确匹配标签 | 使用 = 而非 =~ | 利用索引 |
| 避免 heavy 函数 | 少用 quantile_over_time | 减少计算开销 |
| 优化 step 参数 | 增大 step | 减少返回的样本数 |
PromQL 优化示例:
# 慢查询(全序列扫描)
avg without(cpu, mode)(
rate(node_cpu_seconds_total[5m])
)
# 优化(先缩小范围)
avg by(instance, mode)(
rate(node_cpu_seconds_total{mode!="idle"}[5m])
)
架构优化:
# 使用记录规则预计算
groups:
- name: prometheus_recording
interval: 1m
rules:
- record: service:http_requests:rate1m
expr: sum by(service, method, status) (rate(http_requests_total[1m]))
# 增加本地缓存
--storage.tsdb.retention.time=30d
--storage.tsdb.min-block-duration=2h
--query.max-concurrency=20
--query.timeout=2m
--query.max-samples=50000000
30 Prometheus 的安全机制和认证方式是什么?
答案:
Prometheus 原生安全功能较为基础,需结合反向代理或专用组件实现完整的认证授权。
支持的安全机制:
| 机制 | 原生支持 | 说明 |
|---|---|---|
| Basic Auth | 采集端(scrape) | 目标端支持 Basic Auth 认证 |
| Bearer Token | 采集端 | 支持静态 Token 和文件读取 |
| TLS/mTLS | 两端 | 支持配置证书 |
| OAuth2 | 采集端 | 支持 OAuth2 客户端凭证 |
| RBAC | 不支持(需反向代理) | Nginx/Envoy 前置 |
| 审计日志 | 不支持 | 需外部方案 |
认证配置:
# Prometheus 采集带认证的目标
scrape_configs:
- job_name: 'authenticated-target'
scheme: https
tls_config:
ca_file: /etc/prometheus/ca.crt
cert_file: /etc/prometheus/client.crt
key_file: /etc/prometheus/client.key
insecure_skip_verify: false
basic_auth:
username: 'prometheus'
password_file: /etc/prometheus/.password
# 或 Bearer Token
authorization:
type: Bearer
credentials_file: /etc/prometheus/token
# 或 OAuth2
oauth2:
client_id: 'prometheus'
client_secret_file: /etc/prometheus/client_secret
token_url: 'https://auth.example.com/token'
scopes: ['metrics:read']
# Alertmanager Basic Auth
alerting:
alertmanagers:
- scheme: https
tls_config:
ca_file: /etc/prometheus/ca.crt
basic_auth:
username: 'alertmanager'
password: '<password>'
static_configs:
- targets: ['alertmanager.example.com:9093']
反向代理方案:
# Nginx 反向代理 Prometheus API
server {
listen 443 ssl;
server_name prometheus.example.com;
location / {
auth_basic "Prometheus";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:9090;
}
location /api/v1/ {
# 只允许特定角色访问写 API
if ($request_method = POST) {
satisfy any;
allow 10.0.0.0/8;
deny all;
}
proxy_pass http://localhost:9090;
}
}