Kubernetes 可观测性:Prometheus 监控、日志采集与告警

摘要:可观测性是生产环境 Kubernetes 的关键能力。本文系统介绍可观测性三大支柱(Metrics、Logging、Tracing),Prometheus 架构与 PromQL 查询,Grafana Dashboard 与 AlertManager 告警,EFK 与 Loki 日志方案对比,以及分布式追踪与 kubectl 原生监控命令。文末含 FAQ 与生产建议。


一、可观测性三大支柱详解

可观测性(Observability)是对系统内部状态的推断能力,通过外部输出理解系统行为。Kubernetes 与云原生场景下,通常从三个维度构建可观测性体系。

1.1 三大支柱定义

支柱 核心问题 典型工具 数据形态
Metrics 发生了什么?当前状态如何? Prometheus、Grafana 时序数值(CPU、QPS、延迟)
Logging 为什么发生?具体事件是什么? EFK、Loki 离散事件、文本流
Tracing 在哪个环节发生?调用链如何? Jaeger、OpenTelemetry 分布式 Trace、Span

Metrics 用于趋势分析、容量规划与告警阈值判断;Logging 用于故障排查、审计与根因分析;Tracing 用于跨服务性能瓶颈定位与延迟分解。三者互补,缺一不可。

1.2 架构关系示意

关联
关联
Tracing 追踪
请求链路
Jaeger / OTel
Logging 日志
应用与系统日志
EFK / Loki
Metrics 指标
CPU/内存/QPS
延迟与错误率
Prometheus + Grafana


二、Metrics --- Prometheus 架构与部署

2.1 Prometheus 架构详解

Prometheus 采用 Pull 模型 :Prometheus Server 主动向配置的目标(targets)发起 HTTP 请求拉取指标,目标需暴露 /metrics 端点。相比 Push 模型,Pull 模型由中心端控制采集频率,便于限流与故障隔离。

核心组件

  • Prometheus Server:拉取、存储、查询。内置 TSDB(时间序列数据库),按 2 小时分块存储,支持压缩与保留策略。
  • Retrieval :按 scrape_interval 从 targets 拉取数据。
  • Storage:TSDB 写入本地或远程存储(如 Thanos、VictoriaMetrics)。
  • HTTP Server:提供 PromQL 查询 API 与 Web UI。

TSDB 与 Pull 模型

  • TSDB 采用列式存储,相同时间戳的多个序列压缩存储,查询时按时间范围与标签过滤。
  • Pull 模型优势:中心端控制采集频率、目标无需开放入站端口、故障时 Prometheus 可重试,目标宕机不影响其他采集。

ServiceMonitor :Prometheus Operator 提供的 CRD,用于自动发现并监控 Kubernetes Service。通过 selector 匹配 Service,Prometheus 根据 ServiceMonitor 动态生成 scrape 配置,无需手动维护 targets 列表。

ServiceMonitor 示例

yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: app-metrics
  namespace: production
spec:
  selector:
    matchLabels:
      app: my-app
  namespaceSelector:
    matchNames:
    - production
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
字段 含义
selector.matchLabels 匹配 Service 的 labels
namespaceSelector 指定要监控的 Namespace
endpoints scrape 目标端口、路径、间隔

PromQL 查询
Pull
Pull
Pull
ServiceMonitor 发现
告警评估
通知
Grafana
Prometheus Server
Node Exporter
kube-state-metrics
应用 /metrics
K8s Service
AlertManager
Slack/钉钉/Email

2.2 一键部署(kube-prometheus-stack)

使用 Helm 部署 kube-prometheus-stack 可一次性安装 Prometheus、Grafana、AlertManager、Node Exporter、kube-state-metrics 等组件。

bash 复制代码
# 添加 Helm 仓库
helm repo add prometheus-community \
  https://prometheus-community.github.io/helm-charts
helm repo update

# 安装完整监控栈
helm install monitoring prometheus-community/kube-prometheus-stack \
  -n monitoring --create-namespace \
  -f monitoring-values.yaml
yaml 复制代码
# monitoring-values.yaml
prometheus:
  prometheusSpec:
    retention: 15d
    retentionSize: 45GB
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: fast-ssd
          resources:
            requests:
              storage: 50Gi
    serviceMonitorSelectorNilUsesHelmValues: false

grafana:
  adminPassword: "your-password"
  persistence:
    enabled: true
    size: 10Gi

alertmanager:
  config:
    route:
      receiver: 'slack'
      group_by: ['alertname', 'cluster']
      group_wait: 30s
      group_interval: 5m
    receivers:
    - name: 'slack'
      slack_configs:
      - api_url: 'https://hooks.slack.com/...'
        channel: '#alerts'

关键字段说明

字段 含义
retention 数据保留时长
retentionSize 存储空间上限
storageSpec.volumeClaimTemplate PVC 模板,持久化 TSDB
serviceMonitorSelectorNilUsesHelmValues 是否发现所有 ServiceMonitor

2.3 PromQL 常用查询

场景 PromQL 示例 说明
节点 CPU 使用率 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) 5 分钟平均,按 instance 聚合
节点内存使用率 (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 可用内存占比
Pod CPU 使用率 sum(rate(container_cpu_usage_seconds_total{namespace="production"}[5m])) by (pod) 按 Pod 聚合
Pod 内存使用 (MB) container_memory_working_set_bytes{namespace="production"} / 1024 / 1024 工作集内存
Pod 重启次数 kube_pod_container_status_restarts_total{namespace="production"} 累计重启次数
磁盘使用率 (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 节点磁盘
API Server 延迟 P99 histogram_quantile(0.99, rate(apiserver_request_duration_seconds_bucket[5m])) 请求延迟 99 分位
网络接收速率 sum(rate(container_network_receive_bytes_total{namespace="production"}[5m])) by (pod) 按 Pod 聚合
bash 复制代码
# 在 Prometheus 中执行查询
kubectl port-forward -n monitoring svc/monitoring-prometheus 9090:9090
# 浏览器访问 http://localhost:9090,在 Query 输入 PromQL

监控层级与 RED 方法

层级 关注指标 示例
节点 CPU、内存、磁盘、网络 node_cpu_seconds_totalnode_memory_*
Pod 资源使用 vs limits、重启、OOM container_memory_working_set_bytes
集群 调度成功率、API Server 延迟 scheduler_*apiserver_request_duration_seconds
应用 RED(Rate、Errors、Duration) 自定义 /metrics 暴露 QPS、错误率、P99 延迟

2.4 Grafana Dashboard 配置要点

  1. 数据源 :添加 Prometheus 数据源,URL 通常为 http://monitoring-prometheus:9090
  2. 变量 :使用 $namespace$pod 等变量实现多环境切换。
  3. 面板:选择 Graph / Time series / Stat / Gauge 等,根据指标类型选择合适可视化。
  4. 告警:在面板中配置 Alert 规则,阈值触发后通知 AlertManager 或 Grafana 内置告警。

常用 Dashboard ID(Grafana 官方库):

  • 1860:Node Exporter
  • 315:Kubernetes 集群
  • 6417:Kubernetes Pod 监控

三、AlertManager 告警规则示例

通过 PrometheusRule CRD 定义告警规则,AlertManager 负责去重、分组、抑制与路由。

yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: pod-alerts
  namespace: monitoring
spec:
  groups:
  - name: pod.rules
    rules:
    - alert: PodCrashLooping
      expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.pod }} 在持续重启"
        description: "命名空间 {{ $labels.namespace }} 中 Pod {{ $labels.pod }} 15 分钟内重启次数大于 0"

    - alert: PodMemoryHigh
      expr: |
        (container_memory_working_set_bytes / container_spec_memory_limit_bytes * 100) > 90
        and container_spec_memory_limit_bytes > 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Pod {{ $labels.pod }} 内存使用超过 90%"

    - alert: NodeDiskFull
      expr: |
        (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10
        and mountpoint != "/"
      for: 10m
      labels:
        severity: critical
      annotations:
        summary: "节点 {{ $labels.instance }} 磁盘空间不足 10%"

    - alert: NodeNotReady
      expr: kube_node_status_condition{condition="Ready", status="true"} == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "节点 {{ $labels.node }} 不可用"

应用告警规则

bash 复制代码
kubectl apply -f prometheus-rules.yaml

AlertManager 关键配置

yaml 复制代码
# alertmanager-config.yaml
route:
  receiver: 'default'
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
  - match:
      severity: critical
    receiver: 'critical'
    continue: true
  - match:
      severity: warning
    receiver: 'warning'
inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  equal: ['alertname']
字段 含义
group_wait 首次告警前等待时间
group_interval 同组告警发送间隔
repeat_interval 未解决告警重复发送间隔
inhibit_rules 高级告警抑制低级告警

四、Logging --- 日志方案对比

4.1 EFK vs Loki

方案 采集 存储 查询 特点
EFK Fluent Bit / Fluentd Elasticsearch Kibana 全文检索、复杂查询,资源占用高
Loki Promtail Loki Grafana 仅索引标签,资源占用低,与 Grafana 统一

EFK 适合需要全文检索、复杂过滤的场景;Loki 仿照 Prometheus 标签模型,仅索引 namespacepodcontainer 等标签,不索引日志内容,存储与查询成本更低,适合大规模日志。

4.2 日志采集原理

Kubernetes 将容器 stdout/stderr 写入节点 /var/log/containers/<pod>_<ns>_<container>-<id>.log/var/log/pods/。采集器以 DaemonSet 运行,读取这些文件,附加 namespace、pod、container 等标签后推送到后端。

Promtail 配置示例(Loki 方案):

yaml 复制代码
# promtail-config.yaml
server:
  http_listen_port: 9080
positions:
  filename: /tmp/positions.yaml
clients:
  - url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
  kubernetes_sd_configs:
  - role: pod
  pipeline_stages:
  - json:
      expressions:
        level: level
  - labels:
      level:
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_namespace]
    target_label: namespace
  - source_labels: [__meta_kubernetes_pod_name]
    target_label: pod

Fluent Bit 配置示例(EFK 方案):

yaml 复制代码
# fluent-bit-config.yaml
[INPUT]
  Name              tail
  Path              /var/log/containers/*.log
  Parser            docker
  Tag               kube.*
  Refresh_Interval  5

[FILTER]
  Name                kubernetes
  Match               kube.*
  Kube_URL            https://kubernetes.default.svc:443
  Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token

[OUTPUT]
  Name  es
  Match *
  Host  elasticsearch
  Port  9200
  Logstash_Format On

stdout/stderr
添加 K8s 元数据
Pod 容器
/var/log/containers/
Fluent Bit / Promtail
Elasticsearch / Loki

4.3 kubectl 原生日志命令汇总

bash 复制代码
# 查看 Pod 日志
kubectl logs <pod-name> -n <namespace>

# 实时跟踪
kubectl logs <pod-name> -f -n <namespace>

# 查看前一个容器的日志(崩溃后排查)
kubectl logs <pod-name> --previous -n <namespace>

# 多容器 Pod 指定容器
kubectl logs <pod-name> -c <container-name> -n <namespace>

# 按标签查看(多个 Pod)
kubectl logs -l app=nginx -n <namespace> --all-containers=true

# 显示时间戳
kubectl logs <pod-name> --timestamps -n <namespace>

# 查看最近 1 小时
kubectl logs <pod-name> --since=1h -n <namespace>

# 查看最后 100 行
kubectl logs <pod-name> --tail=100 -n <namespace>

五、Tracing --- 分布式追踪简介

在微服务架构中,单次请求会经过多个服务。链路追踪通过 Trace ID 串联各服务的 Span,记录耗时和调用关系,用于定位延迟瓶颈和错误链。
API Gateway
User Service
Order Service
Payment Service
DB
外部 API

常用方案

  • Jaeger:CNCF 项目,支持多种语言 SDK。
  • OpenTelemetry:统一 Metrics + Logs + Traces 标准,推荐作为遥测采集层,后端可对接 Jaeger、Zipkin 等。

OpenTelemetry 部署要点

  • 使用 OpenTelemetry Collector 作为 Sidecar 或 DaemonSet 采集。
  • 应用通过 OTLP 协议将 Trace 数据发送到 Collector。
  • Collector 可配置 exporter 转发至 Jaeger、Zipkin 等后端。

六、kubectl 原生监控命令汇总

bash 复制代码
# 资源使用概览(需 Metrics Server)
kubectl top nodes
kubectl top pods
kubectl top pods -n production --sort-by=cpu
kubectl top pods -n production --sort-by=memory

# 查看事件(排查调度、镜像拉取等问题)
kubectl get events --sort-by='.lastTimestamp'
kubectl get events -n production -w
kubectl get events -n production --field-selector reason=FailedScheduling

# 查看 Pod 详情(含 Events)
kubectl describe pod <pod-name> -n <namespace>

# 检查 Service 端点
kubectl get endpoints <service-name> -n <namespace>

七、可观测性最佳实践

7.1 Metrics

  • 使用 Prometheus + Grafana 建立统一监控。
  • 配置关键告警(Pod 重启、OOM、节点异常、API Server 延迟)。
  • 应用暴露业务指标(如 /metrics)。
  • 使用 Dashboard 分层监控(节点 / Pod / 应用)。

7.2 Logging

  • 使用结构化日志(JSON),便于解析与检索。
  • 集中收集到 Loki 或 ELK。
  • 日志中包含 request ID,便于与 Tracing 关联。
  • 合理设置日志级别和保留周期。

7.3 Tracing

  • 微服务架构采用 OpenTelemetry 或 Jaeger。
  • 正确传播 trace context(跨服务、跨进程)。
  • 对关键操作记录 span。

八、总结表格

维度 工具 用途
Metrics Prometheus + Grafana 指标监控、趋势分析、告警
Logging EFK / Loki + Promtail 集中日志、检索、审计
Tracing Jaeger / OpenTelemetry 分布式调用链、延迟分解
原生 kubectl top / logs / describe 快速排查、资源概览

九、FAQ

Q1:Prometheus 存储占用过高如何优化?

  • 缩短 retention(如 7d)或设置 retentionSize
  • 使用 recording rules 预聚合高频查询,减少原始数据存储。
  • 将长期数据迁移到 Thanos、VictoriaMetrics 等远程存储。
  • 精简 scrape 目标,避免采集无用指标。

Q2:日志量过大导致 Loki/ES 压力大怎么办?

  • 在采集端(Promtail/Fluent Bit)过滤噪声日志,仅保留 ERROR/WARN 或关键业务日志。
  • 使用 max_sizemax_age 限制单文件大小与保留时间。
  • 分片存储,按 namespace 或 label 做分片策略。
  • 考虑日志采样:对高频 INFO 日志按比例采样。

Q3:告警规则如何调优避免告警风暴?

  • 合理设置 for 持续时间,避免瞬时抖动触发。
  • 使用 group_bygroup_waitgroup_interval 合并相似告警。
  • 配置 inhibit_rules 抑制低级告警(如 Pod 重启被节点故障涵盖)。
  • 告警分级:warning 与 critical 分开路由,critical 走紧急通道。

Q4:ServiceMonitor 如何自动发现自定义应用?

  • 确保应用 Service 暴露 /metrics 端口。
  • 创建 ServiceMonitor,selector 匹配 Service 的 labels。
  • 设置 spec.endpoints 指定 scrape 端口与 path。
  • Prometheus 需配置 serviceMonitorSelectorserviceMonitorSelectorNilUsesHelmValues: false 以发现该 ServiceMonitor。

十、生产建议

  1. 监控:至少覆盖节点、Pod、核心组件(API Server、etcd)及业务关键指标。
  2. 告警:每类告警需有明确处理流程,定期演练。
  3. 日志:统一格式(JSON)、统一采集,保留期与成本平衡。
  4. 追踪:关键微服务接入 Tracing,便于定位跨服务问题。
  5. 存储:Prometheus 数据保留与存储容量规划,建议预留 20% 余量。
  6. 安全:Grafana、Prometheus 控制台需限制访问,生产环境启用认证与 TLS。

kubectl 监控命令速查

命令 用途
kubectl top nodes 节点 CPU/内存使用
kubectl top pods -A 全集群 Pod 资源
kubectl get events -A --sort-by='.lastTimestamp' 按时间排序事件
kubectl describe pod <pod> Pod 详情与 Events
kubectl logs <pod> --previous 崩溃前容器日志

生产环境检查清单 :部署前确认 Prometheus retention 与存储容量;Grafana 与 Prometheus 启用认证;告警规则设置合理的 forrepeat_interval;日志采集端配置过滤与采样,避免日志爆炸。

可观测性选型建议 :中小规模优先 Loki(与 Grafana 统一、成本低);大规模日志检索选 EFK;微服务必接 Tracing;核心业务指标需自定义暴露 /metrics

kubectl 与 Prometheus 配合 :日常排查先用 kubectl topkubectl logskubectl describe 快速定位;历史趋势与多维度分析用 Prometheus + Grafana;告警由 AlertManager 统一推送,避免遗漏。

Metrics Server 部署 (kubectl top 前置条件):kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml。若节点证书自签名,需在 metrics-server Deployment 中添加 --kubelet-insecure-tls(仅限测试环境)。

总结:可观测性三大支柱(Metrics、Logging、Tracing)缺一不可;Prometheus Pull 模型 + ServiceMonitor 实现 K8s 原生监控;PromQL 掌握常用查询即可覆盖大部分场景;告警需合理配置去重与抑制;日志方案按规模与成本选 EFK 或 Loki;kubectl 原生命令与 Prometheus 配合使用可覆盖从快速排查到深度分析的全流程。

相关推荐
2401_834120872 小时前
spring-cloud-kubernetes与SpringCloud Gateway
spring cloud·kubernetes·gateway
yunteng5213 小时前
Sealos部署k8s集群
云原生·容器·kubernetes·sealos
星星乘坐的船6 小时前
基于Kubernetes Python SDK实现Job创建
linux·python·kubernetes
好学且牛逼的马7 小时前
从“配置地狱“到“云原生时代“:Spring Boot 1.x到4.x演进全记录与核心知识点详解
hive·spring boot·云原生
岱宗夫up8 小时前
FastAPI进阶3:云原生架构与DevOps最佳实践
前端·python·云原生·架构·前端框架·fastapi·devops
技术栈壳9 小时前
了解K8s
云原生·容器·kubernetes
Tadas-Gao9 小时前
微服务注册中心选型深度分析:Eureka、Nacos与新一代替代方案
java·分布式·微服务·云原生·eureka·架构·系统架构
m0_488913019 小时前
新手小白也能学会的Dify本地部署教程(超详细)
人工智能·搜索引擎·云原生·eureka·开源·大模型·产品经理
AI开发架构师9 小时前
大数据领域Eureka的服务注册中心搭建
大数据·ai·云原生·eureka