Skip to content

日志与监控入口

kubectl logs 能看当前 Pod 的 stdout/stderr,但 Pod 重建后上一次的日志就没了。kubectl top 能看到当前 CPU/内存快照,但看不到历史趋势。临时排查靠这两样,长期留存、聚合查询和历史趋势分析需要采集链路和指标体系。

Kubernetes 的可观测性分三块:日志(容器 stdout/stderr 和节点文件)、指标(node-exporter、kubelet/cAdvisor、kube-state-metrics、应用 /metrics)、链路(应用内 instrumentation)。集群侧入口主要集中在 Events、日志采集 DaemonSet、Prometheus Operator、ServiceMonitor、PrometheusRule 和 Dashboard。

日志采集链路

容器输出到 stdout/stderr 的日志被 containerd 写入节点的 /var/log/pods/var/log/containers。DaemonSet 形式的日志 Agent 挂载这些目录,读取文件后发送到后端。应用往容器内文件写日志也是一种方式,但需要挂载 volume 让文件持久化、配置日志轮转,并让 Agent 也能读到这个路径。把主要日志输出到 stdout/stderr 是 K8s 生态里采集阻力最小的做法。

DaemonSet 采集

采集 Agent 以 DaemonSet 形式跑在每个节点上,只读挂载节点日志目录:

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-agent
  namespace: logging
spec:
  selector:
    matchLabels:
      app: log-agent
  template:
    metadata:
      labels:
        app: log-agent
    spec:
      containers:
        - name: agent
          image: fluent/fluent-bit:3.2
          volumeMounts:
            - name: varlog
              mountPath: /var/log
              readOnly: true
            - name: varlibdockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers

常见采集工具:

工具定位
Fluent Bit轻量 C 编写,K8s 生态使用广泛,适合作为节点 Agent
VectorRust 编写,转换和路由能力强
FilebeatElastic Stack 体系专用
PromtailLoki 体系专用,和 Grafana 联动自然

EFK 和 Loki 两种后端

方案索引方式优势代价
EFK全文索引全文检索极强,适合审计和复杂查询资源占用高,运维量大
Loki + Promtail + Grafana标签索引低成本,和 Prometheus/Grafana 一套体系不适合全文搜索,偏向标签查询

中小规模集群从 Loki 起步运维压力更小。核心业务日志送 Loki(轻量),审计和安全日志送 Elasticsearch(全文检索)——两者可以并存。

日志里至少保留这些标签字段:

字段用途
namespace按环境或业务线过滤
pod定位具体实例
container区分业务容器和 sidecar
node隔离节点级问题
app/version和 Deployment label 对应,方便对比发布前后日志

Prometheus 指标体系

Prometheus 通过 K8s API 做服务发现,自动找到要抓取的 Pod 和 Service,定期从 /metrics 端点拉取指标。

常见指标来源:

组件提供什么安装方式
node-exporter节点 CPU、内存、磁盘、网络、文件系统DaemonSet
kubelet/cAdvisor容器级别的资源使用kubelet 内嵌
kube-state-metricsK8s 资源对象状态:Pod 阶段、Deployment 副本数、Node ConditionDeployment
应用 /metrics业务 QPS、延迟、错误率、队列长度应用代码内嵌
Ingress/Gateway Controller入口 QPS、状态码、P50/P95/P99Controller 自带
etcdleader、fsync 延迟、DB 大小etcd 自带

Prometheus Operator 的 CRD

Prometheus Operator 把 Prometheus 生态的配置变成几种 CRD:

CRD作用
ServiceMonitor通过 Service label 发现抓取目标
PodMonitor直接通过 Pod label 发现抓取目标
PrometheusRule告警规则和 recording rule
AlertmanagerConfig告警路由

ServiceMonitor 匹配的是 Service 的 label:

yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: demo-app
  namespace: monitoring
  labels:
    release: kube-prometheus-stack   # 必须和 Prometheus CR 的 serviceMonitorSelector 对上
spec:
  namespaceSelector:
    matchNames:
      - demo
  selector:
    matchLabels:
      app: demo-app
  endpoints:
    - port: metrics
      path: /metrics
      interval: 30s

新建 ServiceMonitor 没被抓取时,先查 ServiceMonitor 的 release label 和 Prometheus CR 的 serviceMonitorSelector 是否匹配——两边 label 对不上是常见的"配置了但不生效"的原因。

告警

yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: pod-alerts
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  groups:
    - name: pod.rules
      rules:
        - alert: PodRestartingTooOften
          expr: increase(kube_pod_container_status_restarts_total[15m]) > 3
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Pod 重启频繁"
            description: "namespace={{ $labels.namespace }} pod={{ $labels.pod }} 在 15 分钟内多次重启"

告警的 annotations 里带上 namespace、pod、container、node 这些标签。收到告警时无需再手动 kubectl get pods 定位——告警信息本身指向具体资源。

看板

K8s 相关的 Grafana Dashboard 按不同关注点分层:

看板核心指标
集群总览节点数、Pod 数、资源使用率
Node 详情CPU、内存、磁盘、网络、inode、conntrack
Namespace 维度requests/limits/实际使用的对比
Pod 级别重启次数、OOM 次数、CPU/内存趋势
API Server请求量、延迟分位数、错误率
etcdleader 稳定性、fsync/commit 延迟、DB 大小
入口网关QPS、状态码分布、P95/P99 延迟

Dashboard 要有下钻能力。只看总览的聚合数字,排查时还是要回到 PromQL。

标签基数

指标 label 的值集合太大时——比如把用户 ID、订单号、trace ID 放进 metric label——Prometheus 会在内存里为每个 label 组合维护独立的 time series。几万个用户就是几万条序列,内存和磁盘被高基数 label 撑爆是 Prometheus 常见故障之一。

日志里放这些高基数字段没问题,Loki/Elasticsearch 按需索引。指标 label 放 namespace、app、version、pod、node 这类有限集合的维度。

发布后排查超时问题时,日志和指标按同样的 label 组合(namespace + app + version + pod)联动,从 Grafana 面板点一下告警直接跳到对应时间段和 Pod 的日志——比在两个系统里分别搜索快很多。