Kubernetes 让基础设施变得可编排,但也让故障排查变得多层次。 一个请求失败可能是因为应用代码问题、Pod 资源不足、节点磁盘压力、网络策略拦截、DNS 解析超时、Ingress 配置错误、API Server 响应慢,或者 etcd 存储满了。K8s 可观测性的目标是建立从集群到容器的全链路可视性。
一、K8s 分层监控模型
1.1 五层架构
Kubernetes 可观测性分层:
Layer 5: Application(应用层)
├── 应用指标(RED:Rate/Errors/Duration)
├── 业务指标(订单数、转化率)
├── APM 追踪(OpenTelemetry)
└── 日志(结构化 JSON)
Layer 4: Container(容器层)
├── CPU / Memory / Disk IO / Network
├── 容器进程(PID 压力)
├── 容器重启次数
└── OOMKilled / Evicted
Layer 3: Pod(编排层)
├── 副本数 vs 期望数
├── 就绪探针 / 存活探针状态
├── Pod 调度延迟
└── 亲和性/反亲和性冲突
Layer 2: Node(节点层)
├── CPU / Memory / Disk / Network
├── 节点状态(Ready/NotReady)
├── 内核压力(Pressure)
└── 节点污点/污点容忍
Layer 1: Cluster(控制平面层)
├── API Server 延迟/错误率
├── etcd 延迟/存储/领袖选举
├── Scheduler 调度延迟/失败数
└── Controller Manager 性能
二、核心组件指标
2.1 kubelet 与 cAdvisor
# kubelet 指标
# Pod 启动延迟
kubelet_pod_start_duration_seconds_count
# 容器运行时操作延迟
kubelet_runtime_operations_duration_seconds{operation_type=~"create_container|pull_image"}
# PLEG(Pod Lifecycle Event Generator)延迟
kubelet_pleg_relist_duration_seconds
# cAdvisor 容器指标
# 容器 CPU 使用率
rate(container_cpu_usage_seconds_total{container!=""}[5m])
# 容器内存使用
container_memory_working_set_bytes{container!=""}
# 容器网络 IO
rate(container_network_receive_bytes_total[5m])
rate(container_network_transmit_bytes_total[5m])
# 容器文件系统使用
container_fs_usage_bytes{container!=""}
2.2 Metrics Server
# Metrics Server 提供 kubectl top 能力
kubectl top nodes
# NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
# node-01 850m 21% 8192Mi 51%
# node-02 1200m 30% 10240Mi 64%
kubectl top pods --all-namespaces
# NAMESPACE NAME CPU(cores) MEMORY(bytes)
# default nginx-7d8c9b4f5-x2b3c 5m 128Mi
# default api-5f4d8c9b2-a1b2c 150m 512Mi
# Metrics Server HPA 指标
# kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods
2.3 Node Exporter
# 节点 CPU
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 节点内存
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) /
node_memory_MemTotal_bytes * 100
# 节点磁盘
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) /
node_filesystem_size_bytes{mountpoint="/"} * 100
# 节点网络
rate(node_network_receive_bytes_total{device!="lo"}[5m])
rate(node_network_transmit_bytes_total{device!="lo"}[5m])
# 节点压力
node_pressure_cpu_waiting_seconds_total
node_pressure_memory_waiting_seconds_total
node_pressure_io_waiting_seconds_total
三、K8s 核心告警规则
# kubernetes-alerts.yml
groups:
- name: kubernetes-critical
rules:
# Pod 频繁重启
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[10m]) > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.pod }} is crash looping"
# Pod 未就绪
- alert: PodNotReady
expr: |
kube_pod_status_phase{phase=~"Pending|Unknown|Failed"} == 1
for: 15m
labels:
severity: warning
# Pod OOMKilled
- alert: PodOOMKilled
expr: |
kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} == 1
labels:
severity: warning
# 节点 NotReady
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="false"} == 1
for: 5m
labels:
severity: critical
# 节点磁盘压力
- alert: NodeDiskPressure
expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1
for: 2m
labels:
severity: warning
# 节点内存压力
- alert: NodeMemoryPressure
expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
for: 2m
labels:
severity: warning
# Job 失败
- alert: JobFailed
expr: kube_job_status_failed{job_name=~".*"} > 0
for: 0m
labels:
severity: warning
# HPA 达到最大副本
- alert: HPAMaxReplicas
expr: |
kube_horizontalpodautoscaler_status_current_replicas
==
kube_horizontalpodautoscaler_spec_max_replicas
for: 10m
labels:
severity: warning
annotations:
summary: "HPA {{ $labels.horizontalpodautoscaler }} at max replicas"
- name: kubernetes-control-plane
rules:
# API Server 延迟
- alert: APIServerHighLatency
expr: |
histogram_quantile(0.99,
sum(rate(apiserver_request_duration_seconds_bucket[5m])) by (le)
) > 1
for: 5m
labels:
severity: warning
# etcd 领袖选举频繁
- alert: EtcdFrequentLeaderChanges
expr: |
rate(etcd_server_leader_changes_seen_total[1h]) > 0
for: 5m
labels:
severity: critical
# etcd DB 大小
- alert: EtcdDatabaseHigh
expr: etcd_mvcc_db_total_size_in_bytes / etcd_server_quota_backend_bytes > 0.8
for: 5m
labels:
severity: warning
# Scheduler 调度失败
- alert: SchedulerFailures
expr: rate(scheduler_schedule_attempts_total{result="unschedulable"}[5m]) > 0
for: 10m
labels:
severity: warning
四、K8s Events 与 Audit Logs
4.1 Events 监控
# 查看 Pod 事件
kubectl describe pod <pod-name>
# 查看所有 Warning 事件
kubectl get events --field-selector type=Warning --sort-by='.lastTimestamp'
# 按原因筛选
kubectl get events --field-selector reason=FailedScheduling
# 用 stern 实时查看日志
stern --all-namespaces --selector app=api
4.2 Audit Logs
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["pods"]
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
- level: Request
omitStages:
- RequestReceived
nonResourceURLs:
- /healthz*
- /version
users:
- system:kube-proxy
verbs: ["get"]
# API Server 启用审计日志
kube-apiserver \
--audit-policy-file=/etc/kubernetes/audit-policy.yaml \
--audit-log-path=/var/log/audit.log \
--audit-log-maxsize=100 \
--audit-log-maxbackup=10
五、网络可观测性
5.1 CNI 监控
# Calico 指标(如启用 Felix 指标)
# 网络策略命中
felix_active_local_endpoints
# Cilium 指标
cilium_endpoint_count
cilium_drop_total{reason="Policy denied"}
# Flannel 指标
flannel_subnets
5.2 CoreDNS
# DNS 查询速率
coredns_dns_requests_total
# DNS 查询延迟
coredns_dns_request_duration_seconds_bucket
# DNS 查询失败
coredns_dns_responses_total{rcode="NXDOMAIN"}
coredns_dns_responses_total{rcode="SERVFAIL"}
# 缓存命中率
coredns_cache_hits_total
coredns_cache_misses_total
5.3 Ingress
# Nginx Ingress Controller
nginx_ingress_controller_requests
nginx_ingress_controller_nginx_process_requests
# 请求延迟
histogram_quantile(0.99,
sum by (le, ingress) (rate(nginx_ingress_controller_request_duration_seconds_bucket[5m]))
)
# 5xx 错误
nginx_ingress_controller_requests{status=~"5.."}
六、存储可观测性
6.1 PVC 监控
# PVC 使用率
(
kubelet_volume_stats_used_bytes
/
kubelet_volume_stats_capacity_bytes
) * 100
# PVC 接近满
kubelet_volume_stats_available_bytes / kubelet_volume_stats_capacity_bytes < 0.1
# StorageClass 配额
kube_persistentvolumeclaim_resource_requests_storage_bytes
6.2 CSI Driver 指标
# CSI Driver 暴露了标准的 gRPC 指标
# 需要 CSI 驱动支持
# 示例:创建 PVC 延迟
csi_sidecar_operations_seconds_bucket{driver="csi-driver-name", method_name="CreateVolume"}
七、排障工具链
| 工具 | 用途 | 命令 |
|---|---|---|
| kubectl | 基础查询 | kubectl get/describe/logs/top |
| k9s | 交互式 TUI | k9s |
| stern | 多 Pod 日志聚合 | stern --selector app=api |
| kubectl-trace | BPF 追踪 | kubectl trace run node-01 -e '...' |
| inspektor-gadget | K8s 专用 eBPF | kubectl gadget trace tcp |
| kubectl-debug | 调试容器 | kubectl debug pod-xxx --image=busybox |
| kor | 清理孤儿资源 | kor all |
参考与延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。