一个运行在 Kubernetes 上的分布式系统,出问题时最难回答的问题是"发生了什么"。单机时代,登录服务器查看进程状态和日志文件,基本能还原现场。容器化之后,Pod 随时可能被调度到不同节点,崩溃后立即重启,原始日志消失,这套方法彻底失效。可观测性(Observability)是对这个问题的系统性回答:通过在系统内部埋点、采集、存储和展示三类信号——Metrics(指标)、Logging(日志)、Tracing(链路追踪)——让工程师在不登录服务器的情况下理解系统行为。

Kubernetes 本身对可观测性有明确的架构分工。采集点(kubelet 内嵌的 cAdvisor、node-exporter DaemonSet、应用 SDK)由各组件负责暴露,聚合层(Prometheus、metrics-server)负责拉取和存储,展示层(Grafana、Jaeger UI)负责查询和可视化。这种"采集点内建、存储和展示留给生态"的设计,让 Kubernetes 本身保持简洁,同时允许不同规模的集群选择不同的存储方案。

理解可观测性的关键区分点在于:kube-state-metrics 和 metrics-server 看起来相似,实际上服务完全不同的场景;DaemonSet 日志采集和 sidecar 日志采集各有适用边界;OpenTelemetry 正在成为三类信号的统一采集标准,但具体的存储和展示仍然分散。

架构全景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Node 层
└── node-exporter DaemonSet
→ CPU、内存、磁盘、网络(硬件级别)
└── kubelet /metrics/cadvisor
→ 容器 CPU、内存、网络 I/O(Pod 级别)

集群层
└── kube-state-metrics Deployment
→ K8s 对象状态:Deployment rollout 进度、Pod pending 数量、
Node condition、PVC 绑定状态(不是实时资源用量)
└── metrics-server Deployment
→ 实时 CPU/内存用量(HPA 和 kubectl top 的数据源)
数据窗口短(约 15s),不持久化

应用层
└── Prometheus SDK / OpenTelemetry SDK
→ 业务指标:请求 QPS、延迟 P99、错误率、队列深度

日志流
Pod stdout/stderr
/var/log/containers/<pod>_<ns>_<container>-<id>.log(节点上)
→ Fluentbit DaemonSet 采集 → Loki / Elasticsearch

链路追踪
App SDK(OTel)→ OTel Collector → Jaeger / Tempo → Grafana

Metrics:三层采集架构

node-exporter:节点硬件指标

node-exporter 以 DaemonSet 形式运行,在每个节点上暴露 /metrics 端点,采集 CPU、内存、磁盘 I/O、网络接口、文件描述符等操作系统级别的指标。这些指标是排查节点资源瓶颈的基础,例如 node_disk_io_time_seconds_total 可以判断磁盘是否饱和。

cAdvisor:容器资源用量

cAdvisor(Container Advisor)内嵌在 kubelet 进程中,通过 /metrics/cadvisor 端点暴露容器级别的资源用量,包括 container_cpu_usage_seconds_totalcontainer_memory_working_set_bytes 等。这是 Prometheus 抓取容器指标的主要数据源。

kube-state-metrics vs metrics-server:两者的本质区别

这是最常见的混淆点,值得专门澄清:

kube-state-metrics 监听 Kubernetes API 对象的状态,把对象状态转换为 Prometheus 格式的指标。它回答的是"集群里有多少个 Pod 处于 Pending 状态"“这个 Deployment 的期望副本数和就绪副本数各是多少”“这个 Node 的 Ready condition 是否为 True”。这些是离散的状态值,不是连续的资源用量数据。kube-state-metrics 的数据通常持久化到 Prometheus,用于告警和长期趋势分析。

metrics-server 实现了 Kubernetes Metrics API(metrics.k8s.io),提供实时的 CPU 和内存用量数据,数据窗口约 15 秒,不持久化。它的数据源来自 kubelet 的 /metrics/resource 端点(而非 cAdvisor 的完整 metrics)。HPA controller 通过 metrics-server 获取 Pod 的实时 CPU 用量来决定是否扩缩容,kubectl top nodekubectl top pod 也依赖 metrics-server。

两者不能互相替代:metrics-server 不存储历史数据,无法做趋势分析;kube-state-metrics 不提供实时资源用量,HPA 无法使用它。

Prometheus Operator:自动化 scrape 配置

Prometheus Operator 通过 ServiceMonitor CRD 让 Prometheus 自动发现监控目标。用户声明一个 ServiceMonitor 对象,描述要监控哪个 namespace 下的哪类 Service(通过 label selector),Prometheus Operator 把它转换为 Prometheus 的 scrape_config,实现监控目标的动态注册。新增一个服务的监控,只需 apply 一个 ServiceMonitor 对象,无需重启 Prometheus 或修改配置文件。

AlertmanagerConfig CRD 同理:用户声明告警规则(PrometheusRule)和路由配置(AlertmanagerConfig),Operator 自动注入到 Alertmanager 配置。

kube-prometheus-stack 是 Prometheus Operator 的生产级打包方案(Helm Chart),一次安装包含:Prometheus Operator、Prometheus、Alertmanager、Grafana、node-exporter DaemonSet、kube-state-metrics、默认告警规则集(涵盖 etcd、API Server、kubelet、节点资源等 200+ 规则)。在新集群上建立基础可观测性,helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack 是最快路径,5-10 分钟即可获得开箱即用的 Grafana Dashboard。

Logging:日志采集架构

容器日志的存储位置

容器的 stdout 和 stderr 由容器运行时(containerd/CRI-O)捕获,写入节点上的 /var/log/containers/ 目录,文件名格式为 <pod-name>_<namespace>_<container-name>-<container-id>.log。kubelet 负责管理这些日志文件的轮转(log rotation)。

kubectl logs <pod> 实际上是 kubelet 读取这些文件并通过 API 返回给客户端,--previous 参数读取上一个容器实例的日志(Pod 重启后当前容器的日志不包含重启前的内容)。

DaemonSet 采集 vs Sidecar 模式

DaemonSet 模式:在每个节点上运行一个 Fluentbit(或 Fluentd)实例,挂载节点的 /var/log/containers/ 目录,采集所有 Pod 的日志,发送到 Loki 或 Elasticsearch。这是最常见的部署模式,资源效率高(每节点一个采集进程),不需要修改应用 Pod 的配置。

Sidecar 模式:在每个需要采集日志的 Pod 中注入一个日志采集 sidecar 容器。适用于应用把日志写入文件(非 stdout)的场景,或需要对不同 Pod 的日志做不同处理的场景。代价是每个 Pod 增加一个 sidecar 容器的资源开销,且 Pod 数量多时总资源消耗显著高于 DaemonSet 模式。

生产环境的主流选择是 DaemonSet 模式,应用统一输出到 stdout/stderr,由 Fluentbit 采集。Sidecar 模式仅在有特殊需求(如遗留应用日志写文件)时使用。

Loki vs Elasticsearch

Loki 的设计理念是"日志的 Prometheus":只对标签(labels)建立索引,不对日志内容全文索引。查询时先用标签过滤(如 {app="nginx", namespace="prod"}),再在过滤结果中做文本搜索(LogQL)。存储成本远低于 Elasticsearch(通常低 10 倍以上),适合日志量大、查询模式以标签过滤为主的场景。

Elasticsearch 对日志内容全文索引,支持复杂的全文搜索和聚合分析,适合需要在日志内容上做复杂查询的场景(如安全审计、合规分析)。但存储成本和运维复杂度都显著高于 Loki。

Tracing:链路追踪

OpenTelemetry:统一采集标准

OpenTelemetry(OTel)是 CNCF 的可观测性标准项目,把 Metrics、Logging、Tracing 的采集 SDK 和协议统一化。核心组件:

OTel SDK:应用侧的埋点库,支持 Java、Go、Python、Node.js 等主流语言,负责生成 trace span 和 metric 数据。

OTel Collector:独立的采集代理,接收来自应用 SDK 的数据(支持多种协议:OTLP、Jaeger、Zipkin),做过滤、采样、批处理后,转发到后端(Jaeger、Tempo、Prometheus)。

在 Kubernetes 上,OTel Collector 通常以 DaemonSet(节点级采集)或 Deployment(集中式采集)部署。通过 Cert-manager 和 OTel Operator,可以实现 Pod 的自动 sidecar 注入,无需修改应用代码即可获取基础的 HTTP 和 gRPC trace 数据。

Jaeger / Tempo:trace 存储

Jaeger 是 CNCF 的链路追踪存储和展示系统,支持 Cassandra、Elasticsearch 作为后端存储。Tempo 是 Grafana Labs 的链路追踪存储,与 Loki 类似,只对 trace ID 索引,通过 Loki 的标签查询找到 trace ID,再用 trace ID 查询 Tempo。Tempo + Loki + Grafana 的组合实现了"从日志跳转到 trace"的关联查询,是当前轻量级可观测性栈的流行选择。

eBPF 可观测性:无侵入式采集

传统的应用层可观测性依赖 SDK 埋点,需要修改应用代码。eBPF(Extended Berkeley Packet Filter)是 Linux 内核的动态可编程机制,允许在不修改内核代码和应用代码的情况下,在内核事件(系统调用、网络包、函数调用)触发时执行自定义逻辑,实现"零侵入"的可观测性采集。

在 Kubernetes 场景中,eBPF 可观测性的典型应用:

网络流量可观测性:Cilium 的 Hubble 组件通过 eBPF 在网络层拦截 Pod 间的所有流量,生成 L4/L7 级别的流量拓扑图和延迟统计,无需在应用中注入任何代码。可以看到"Pod A 的哪个接口调用了 Pod B 的哪个接口,延迟是多少"。

自动 trace 注入:Pixie(CNCF 项目)通过 eBPF 自动采集应用的 HTTP、gRPC、MySQL、Redis 等协议的请求-响应对,生成 trace span,无需应用集成 OTel SDK。适合遗留应用或无法修改源码的场景。

性能剖析(Profiling):Parca、Pyroscope 通过 eBPF 采集 CPU 火焰图,每隔固定时间采样所有进程的调用栈,持续 profiling 让定位 CPU 热点从"复现问题时手动触发"变为"随时可查历史数据"。

eBPF 可观测性的限制:需要 Linux 内核 4.14+(部分功能需要 5.x+),某些云服务商的节点内核版本或安全策略可能限制 eBPF 使用。Windows 节点不支持 eBPF。

告警与 SLO:从指标到响应

Prometheus 告警规则

Prometheus 的告警规则(PrometheusRule CRD)定义了何时触发告警。规则本质是 PromQL 表达式,持续满足条件超过 for 指定时长后,触发告警并发送到 Alertmanager。

常见的集群级别告警:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Pod 重启频率过高
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[5m]) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} is crash looping"

# Node 磁盘压力
- alert: NodeDiskPressure
expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1
for: 2m
labels:
severity: critical

# Deployment 可用副本数低于期望
- alert: DeploymentReplicasMismatch
expr: |
kube_deployment_spec_replicas
!= kube_deployment_status_replicas_available
for: 10m
labels:
severity: warning

Alertmanager 负责告警的路由、分组和去重:把同一个 Deployment 的多个 Pod 告警合并为一条,按 severity 路由到不同的通知渠道(PagerDuty、Slack、Email)。

SLO:从告警转向服务水平目标

传统的基于阈值的告警(CPU > 80% 持续 5 分钟)有大量误报,工程师对告警产生疲劳。SLO(Service Level Objective)是更成熟的可观测性实践:把业务目标(99.9% 的请求在 200ms 内响应)转化为 error budget(每月允许 43.8 分钟不满足 SLO),只有 error budget 消耗速度过快时才触发紧急告警。

在 Kubernetes 上实现 SLO 监控的常见工具:

  • Sloth:根据 SLO 定义自动生成 PrometheusRule
  • pyrra:SLO 感知的 Prometheus recording rules 生成器
  • Google SLO Generator:遵循 SRE 手册的 SLO 实现

Grafana Dashboard 分层

生产环境的 Grafana dashboard 通常分三层:

集群总览层:节点数量、Pod 调度成功率、API Server 延迟、etcd 响应时间。出现红色时,可以下钻到下一层。

Namespace/服务层:按 namespace 展示 Pod CPU/内存用量、Deployment 就绪状态、HPA 扩缩容历史。定位问题所在的服务。

Pod/容器层:单个 Pod 的 CPU throttling 率(container_cpu_cfs_throttled_seconds_total)、OOMKill 次数、网络 I/O。定位具体原因。

Grafana 的 Exemplar 功能把 Prometheus 的某个具体数据点(如某个高延迟请求的 P99)关联到对应的 trace ID,点击后直接跳转到 Jaeger/Tempo 查看该请求的完整调用链。这是 Metrics → Tracing 关联查询的核心机制。

Prometheus 远程写入与长期存储

Prometheus 本地存储默认保留 15 天数据,对于长期趋势分析(季度容量规划、年度 SLO 报告)不够用。remote_write 配置让 Prometheus 把采集到的 metrics 同步推送到外部存储:

1
2
3
4
5
remote_write:
- url: "https://cortex.example.com/api/prom/push"
queue_config:
max_samples_per_send: 10000
capacity: 100000

常用的远程写入后端:Thanos Receive(接收并持久化到对象存储)、Cortex/Mimir(水平扩展的 Prometheus 兼容存储)、VictoriaMetrics(高压缩率的时序数据库,写入性能优于原生 Prometheus)。远程写入引入网络延迟和反压风险,queue_config 中的 capacity 是内存队列容量,网络中断时缓冲写入请求,超出容量后丢弃最旧数据而不阻塞 Prometheus 本地采集。

采样策略与成本控制

链路追踪最大的成本挑战是数据量:高流量系统每秒产生数万条 trace,全量存储代价极高。OTel Collector 支持多种采样策略:

头部采样(Head-based sampling):在 trace 开始时随机决定是否采样(如 1%),简单但会丢失所有低频异常 trace。

尾部采样(Tail-based sampling):等 trace 完整结束后,基于 trace 的结果(是否有错误、延迟是否超阈值)决定是否保存。需要把同一 trace 的所有 span 路由到同一个 Collector 实例(通过 trace ID 做一致性 hash),工程复杂度较高但质量好。

优先级采样(Priority sampling):错误 trace 100% 保留,慢 trace(P99 以上)高比例保留,正常 trace 低比例随机采样。是实际生产中最常用的折中方案。

API Server 与 etcd 的自身可观测性

Kubernetes 的控制面组件本身也需要被监控。API Server 暴露的关键指标:

  • apiserver_request_total:按动词(GET/LIST/WATCH/CREATE/UPDATE)和资源类型分类的请求计数,用于分析 API Server 负载来源。
  • apiserver_request_duration_seconds:API 请求延迟分布,P99 超过 1s 通常意味着 etcd 或网络有问题。
  • apiserver_current_inflight_requests:当前进行中的请求数,有 mutating 和 readOnly 两个维度的上限(默认 200/400)。

etcd 的关键指标:

  • etcd_server_leader_changes_seen_total:leader 切换次数,频繁切换说明 etcd 集群不稳定(通常是网络或磁盘 I/O 问题)。
  • etcd_disk_wal_fsync_duration_seconds:WAL 日志的 fsync 延迟,P99 超过 10ms 说明磁盘 I/O 成为瓶颈,会拖慢整个集群的写操作。
  • etcd_mvcc_db_total_size_in_bytes:etcd 数据库当前大小,接近 quota(默认 2GB)时需要压缩历史版本(etcdctl compact)或扩大 quota。

这些指标由 kube-prometheus-stack Helm chart 自动收集,对应的告警规则也预置在 chart 中(KubeAPIErrorsHighetcdHighNumberOfLeaderChanges 等)。

日志结构化与查询效率

结构化日志的重要性

非结构化日志(纯文本)在 Loki 中只能做全文搜索,效率低。结构化日志(JSON 格式)可以把关键字段(request_id、user_id、status_code、latency_ms)作为 Loki 的 label 或 structured metadata,查询时直接过滤,速度快一个数量级。

Java 应用推荐用 logback + logstash-logback-encoder 输出 JSON 日志,Go 应用推荐 zap 或 slog(Go 1.21+ 标准库),Node.js 应用推荐 pino。标准字段名遵循 OpenTelemetry 语义约定(service.nametrace_idspan_id)便于跨工具关联。

Loki 的 label 基数(cardinality)是关键性能约束:label 的不同取值组合数决定了 Loki 需要维护的 stream 数量。pod_name 不适合作为 label(Pod 数量多时 cardinality 极高),应该作为 structured metadata 或在查询时用正则过滤。推荐的 label 集合:namespaceappcontainerlevel(日志级别),其余字段通过 | json 管道在查询时动态解析。

LogQL 常用查询模式

Loki 的 LogQL 语法示例:

1
2
3
4
5
6
7
8
9
10
11
# 过滤某 namespace 下特定 Pod 的日志
{namespace="prod", pod=~"myapp-.*"} |= "ERROR"

# 解析 JSON 日志并按 status_code 过滤
{app="nginx"} | json | status_code >= 500

# 计算每分钟错误率
rate({namespace="prod"} |= "error" [1m])

# 从日志中提取 latency 字段并计算 P99
{app="myservice"} | json | unwrap latency_ms | quantile_over_time(0.99, [5m])

LogQL 的 | json 管道操作符会自动解析 JSON 日志行,把 JSON 字段提取为可过滤的 label,结合 unwrap 可以做数值聚合(类似 PromQL),把日志系统的分析能力提升到接近 Metrics 的水平。

可运行实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. 检查 metrics-server 是否安装
kubectl get deployment metrics-server -n kube-system

# 2. 查看节点和 Pod 资源用量(依赖 metrics-server)
kubectl top node
kubectl top pod -A

# 3. 查看 Pod 日志(当前实例)
kubectl logs -n kube-system deploy/coredns

# 4. 查看 Pod 上一个实例的日志(重启后用)
kubectl logs -n kube-system <pod-name> --previous

# 5. 实时跟踪日志
kubectl logs -f deploy/myapp --tail=50

# 6. 查看节点上的容器日志文件位置(需要节点访问权限)
kubectl debug node/<node-name> -it --image=busybox -- ls /host/var/log/containers/

# 7. 安装 kube-state-metrics(用 Helm)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install kube-state-metrics prometheus-community/kube-state-metrics -n monitoring --create-namespace

# 8. 端口转发访问 kube-state-metrics 指标
kubectl port-forward -n monitoring svc/kube-state-metrics 8080:8080 &
curl http://localhost:8080/metrics | grep kube_deployment_status_replicas

# 9. 对比 kube-state-metrics 和 metrics-server 的输出
kubectl top pod -A # metrics-server:实时资源用量
curl http://localhost:8080/metrics | grep kube_pod_status_phase # kube-state-metrics:Pod 状态分布

实验结果映射到 K8s 对象

kubectl top node 的数据来自 metrics-server 聚合的 kubelet /metrics/resource 端点,刷新间隔约 15 秒。如果 metrics-server 未安装,HPA 将无法工作(kubectl describe hpa 会显示 unable to fetch metrics)。

curl http://localhost:8080/metrics | grep kube_deployment_status_replicas 的输出展示了 kube-state-metrics 把 Deployment 对象的 .status.replicas.status.readyReplicas 等字段转换为 Prometheus gauge 指标。这些指标可以用于告警规则,例如"期望副本数和就绪副本数不一致持续 5 分钟"触发 PagerDuty。

Fluentbit 采集到的日志中,Kubernetes metadata(Pod name、namespace、container name、node name)由 Fluentbit 的 kubernetes filter 插件从 kubelet API 查询并附加到日志记录,这让后续在 Loki 中按 namespace 或 Pod 过滤日志成为可能。

多集群可观测性

单集群的可观测性方案相对直接,多集群场景引入了额外复杂度:每个集群的 Prometheus 独立运行,如何聚合查询?

Thanos 和 Cortex 是解决多集群 Metrics 聚合的两条主流路径。Thanos 在每个集群的 Prometheus 旁部署 Sidecar,把数据上传到对象存储(S3/GCS/OSS),由中央 Thanos Query 组件跨集群联邦查询。Cortex 则把 Prometheus 改造为水平可扩展的远程写入模式,所有集群的 metrics 推送到中央 Cortex,统一存储和查询。两者都支持全局视图(cross-cluster PromQL),区别在于 Thanos 保留本地 Prometheus 完整能力,Cortex 架构更集中但运维复杂度更高。

日志多集群聚合较简单:Fluentbit 的 output 直接指向中央 Loki 或 Elasticsearch 集群,加上 cluster label 区分来源即可。Trace 数据同理,OTel Collector 把 trace 发往中央 Jaeger/Tempo,按 cluster resource attribute 做过滤。

实践中,小规模多集群(3-5 个)通常用 Grafana 的多数据源功能(在同一个 Dashboard 里配置多个 Prometheus 数据源),免去 Thanos/Cortex 的运维成本。规模超过 10 个集群后,统一存储层带来的查询效率和运维简化才开始值回部署成本。

模式提炼

可观测性是"白盒 + 标准接口":系统主动暴露内部状态(白盒),通过标准化的接口(Prometheus 格式、OTel 协议)让任何兼容工具采集。Kubernetes 把采集点内建到核心组件(kubelet、API Server 都暴露 /metrics),把存储和展示留给生态选择。

三类信号的关联查询是可观测性成熟度的标志:从 Grafana dashboard 看到某时刻 P99 延迟飙升(Metrics),跳转到该时间段的相关 Pod 日志(Logging),再通过 trace ID 查看具体请求的调用链(Tracing),这条路径在 Grafana + Loki + Tempo 的组合下可以全程不离开同一个界面。

工程迁移表

传统模式 Kubernetes 等价 关键差异
Spring Actuator /metrics Prometheus SDK + /metrics endpoint 拉取模型(Prometheus pull)vs 推送
JVM JMX cAdvisor + Prometheus JMX exporter 容器感知,无需手动配置端口
ELK Stack (Filebeat+ES+Kibana) Fluentbit + ES + Kibana 或 Loki + Grafana Loki 成本更低,ES 查询更强
Zipkin Jaeger / Tempo + OTel SDK OTel 统一了多语言 SDK
Nagios / Zabbix Prometheus + Alertmanager 声明式告警规则,云原生集成

常见误解

误解一:kube-state-metrics 和 metrics-server 功能相同

两者的数据来源和用途完全不同。kube-state-metrics 监听 Kubernetes API 对象状态,回答"集群对象处于什么状态",数据持久化到 Prometheus,支持长期趋势分析。metrics-server 提供实时 CPU/内存用量,服务于 HPA 和 kubectl top,数据窗口短,不持久化。可以同时部署两者,它们不冲突。

误解二:kubectl logs 适合生产日志分析

kubectl logs 只能查看单个 Pod 的当前实例日志,无法跨 Pod 搜索,无法查看已删除 Pod 的历史日志,也无法做聚合分析。生产环境日志分析需要集中式日志系统(Loki/Elasticsearch):Fluentbit 把所有 Pod 的日志采集到中央存储,保留足够长的历史(通常 7-30 天),支持跨 Pod、跨 namespace 的搜索和过滤。kubectl logs 是开发调试工具,不是生产分析工具。

误解三:sidecar 日志采集比 DaemonSet 更推荐

sidecar 日志采集适合特定场景(应用写文件日志、需要对不同 Pod 做不同处理),不是通用推荐。DaemonSet 模式资源效率更高(每节点一个采集进程 vs 每 Pod 一个 sidecar),配置更简单,是生产环境的主流选择。选择 sidecar 模式需要有明确的理由,而不是默认选项。

练习

  1. 在本地集群安装 metrics-server(kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml),验证 kubectl top nodekubectl top pod 可以正常工作,然后创建一个 HPA(kubectl autoscale deployment myapp --cpu-percent=50 --min=1 --max=5),用压测工具(hey 或 ab)打流量,观察 HPA 扩容过程中 kubectl get hpa -w 的 TARGETS 字段变化。

  2. 部署 kube-state-metrics,端口转发后用 curl 查看指标,找出以下三类信息:当前集群中处于 Pending 状态的 Pod 数量(kube_pod_status_phase)、某个 Deployment 的期望副本数和就绪副本数(kube_deployment_status_replicas vs kube_deployment_status_replicas_ready)、某个 Node 的 Ready condition(kube_node_status_condition)。

  3. 用 Helm 安装 Loki Stack(helm install loki grafana/loki-stack --set grafana.enabled=true),在 Grafana 中配置 Loki 数据源,用 LogQL 查询某个 namespace 的所有 Pod 日志({namespace="default"}),然后过滤包含"error"的日志行({namespace="default"} |= "error")。对比 kubectl logs 和 Loki 查询的体验差异。

系列导航

参考资料