从零搭建一个单节点 K8S 可观测实验室(十二):告警与故障注入——从 Pending、Firing 到故障恢复 📅 发布时间:2026/8/24 14:42:04 👁 浏览次数: 上一篇我们让这套 Kubernetes 可观测实验室真正产生了变化。通过 ApacheBench 压测HTTP 请求 ↓ Demo 应用负载变化 ↓ Prometheus 采集 Metrics ↓ Grafana Dashboard同时Nginx Access Log ↓ Fluent Bit ↓ Loki ↓ Grafana Explore也就是说现在我们已经可以回答系统现在发生了什么但是还有一个问题如果没人一直盯着 Grafana 呢生产环境显然不能依靠人工不断刷新 Dashboard。所以这一篇继续向前让 Kubernetes 监控系统自己发现异常并进入告警流程。最终完成故障发生 ↓ Metric 变化 ↓ PrometheusRule ↓ Alert ↓ Grafana Alerting ↓ 故障恢复一、这一次继续使用 Grafana上一篇已经创建K8S Lab Runtime OverviewDashboard。其中已经包含Demo Pod CPU Demo Pod Memory Host-Only RX Host-Only TX Demo Available Replicas这一篇不重新创建 Dashboard。因为告警实验真正需要观察的是状态变化而不是继续增加大量 Panel。只增加一个CrashLoop Restart Count用于后面的 CrashLoopBackOff 实验。二、增加 Restart Count Panel进入Grafana → Dashboards → K8S Lab Runtime Overview增加一个 Stat Panel。PromQLsum( kube_pod_container_status_restarts_total{ namespaceproduction, pod~crashloop-demo-.* } ) or vector(0)名称CrashLoop Restart Count正常情况下0后面制造 CrashLoopBackOff 时0 ↓ 1 ↓ 2 ↓ 3可以直观看到 Container 是否不断重启。最终 DashboardDemo Pod CPU Demo Pod Memory Host-Only RX Host-Only TX Demo Available Replicas CrashLoop Restart Count已经足够。三、创建 PrometheusRule前面我们已经安装kube-prometheus-stack所以这里不直接修改 Prometheus 配置。使用 Kubernetes CRDPrometheusRule创建告警规则。这一次只创建三个Rule用途DemoDeploymentUnavailable服务不可用LabCrashLoopContainer 崩溃LabHighCPUCPU 持续过高3.1 创建 Rule创建nano k8s-lab-alerts.yaml内容apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: k8s-lab-alerts namespace: monitoring labels: release: prometheus spec: groups: - name: k8s-lab-alerts rules: - alert: DemoDeploymentUnavailable expr: | kube_deployment_status_replicas_available{ namespaceproduction, deploymentjenkins-k8s-demo } 1 for: 1m labels: severity: critical annotations: summary: Demo deployment unavailable - alert: LabCrashLoop expr: | increase( kube_pod_container_status_restarts_total{ namespaceproduction, pod~crashloop-demo-.* }[5m] ) 3 for: 1m labels: severity: critical annotations: summary: CrashLoopBackOff detected - alert: LabHighCPU expr: | ( sum by(namespace,pod)( rate( container_cpu_usage_seconds_total{ namespaceproduction, pod~cpu-stress-.* }[1m] ) ) * 1000 ) 300 for: 1m labels: severity: warning annotations: summary: CPU usage is high应用kubectl apply -f k8s-lab-alerts.yaml检查kubectl get prometheusrule \ -n monitoring应该看到k8s-lab-alerts这里有一个容易踩坑的地方。由于我们使用的是kube-prometheus-stackPrometheus 默认通过 Label Selector 查找需要加载的 PrometheusRule。因此labels: release: prometheus非常重要。如果 Label 不匹配Kubernetes 中可以看到 PrometheusRule 创建成功但是 Prometheus 不会加载这条规则。四、故障类型与对应指标三个 Rule 分别模拟生产环境中常见的三类问题故障类型观察指标告警等级Deployment 副本不可用服务异常Available ReplicaCriticalCrashLoopBackOff应用异常Restart CountCriticalCPU 持续升高资源压力CPU UsageWarning可以看到不同问题需要不同 Metrics。监控系统不是简单判断CPU 高 ↓ 报警而是根据业务场景选择什么指标 ↓ 代表什么异常 ↓ 什么情况下需要通知五、在 Grafana 查看 Alert Rule这一次不再主要使用 Prometheus Web UI。直接打开Grafana → Alerting → Alert rules应该可以看到DemoDeploymentUnavailable LabCrashLoop LabHighCPU当前系统正常No Alert这是正确状态。Grafana 这里主要用于查看 Rule查看当前 Alert查看状态变化。Prometheus Web UI 仍然可以用于PromQL 调试Rule 是否加载Target 检查。但日常观察统一使用 Grafana。六、为什么 Alert Rule 里面有 Pending period创建完三个 Rule 后在 GrafanaAlerting → Alert rules → k8s-lab-alerts展开其中任意一个 Rule例如LabCrashLoop可以看到Pending period 1m这个值对应 YAMLfor: 1m这里需要理解 Prometheus Alert 的状态变化。一个 Rule 主要由两部分组成expr负责判断当前指标是否满足异常条件。例如Available Replica 1表示Deployment 没有可用副本或者5分钟内 Restart Count 增加超过 3 次表示Container 可能持续崩溃for负责判断这个异常状态是否持续足够长时间。例如for: 1m表示如果异常只持续几秒异常 ↓ Pending ↓ 恢复 ↓ Inactive不会真正触发告警。只有异常条件满足 ↓ 持续超过 1 分钟 ↓ Firing所以一次完整状态变化是正常 ↓ Inactive 故障条件满足 ↓ Pending 持续超过 Pending period ↓ Firing 故障恢复 ↓ Resolved这里还有一个细节本实验中的三个 RuleDemoDeploymentUnavailable LabCrashLoop LabHighCPU都设置for: 1m主要是为了让实验现象容易观察。实际生产环境不会全部统一设置。例如服务不可用for: 5m避免发布过程中短暂波动。CPU 高for: 10m因为短时间 CPU 峰值很常见。CrashLoopfor: 2m因为持续崩溃通常需要更快响应。所以expr决定什么情况算异常。而for决定异常持续多久才值得报警。这也是为什么 Prometheus Alert 不只是Metric 超过阈值 ↓ 马上报警而是Metric 异常 ↓ 持续观察 ↓ 确认不是瞬态变化 ↓ 触发 Alert七、故障实验一Deployment Scale 到 0删除 Pod 的实验容易受到 Kubernetes 自愈速度影响。所以这一次直接制造一个确定持续的故障Deployment 没有可用副本执行kubectl scale deployment \ jenkins-k8s-demo \ -n production \ --replicas0查看kubectl get deployment \ -n production应该看到READY 0/0 AVAILABLE 07.1 Grafana 查看 Replica打开K8S Lab Runtime Overview之前Demo Available Replicas 1现在0这就是故障状态。7.2 Grafana 查看 Alert进入Alerting → Alert rules找到DemoDeploymentUnavailable状态变化正常 ↓ Pending ↓ Firing进入 Firing 后可以看到severitycritical说明Deployment 没有可用实例已经持续超过 Rule 设置时间。八、恢复业务恢复kubectl scale deployment \ jenkins-k8s-demo \ -n production \ --replicas1等待kubectl get pods \ -n production恢复ContainerCreating ↓ RunningGrafanaDemo Available Replicas 0 ↓ 1AlertFiring ↓ Resolved到这里完成第一个完整闭环业务故障 ↓ Metric 异常 ↓ PrometheusRule ↓ Alert ↓ 恢复九、故障实验二CrashLoopBackOff第二个实验模拟Container 不断崩溃。创建nano crashloop-demo.yaml内容apiVersion: apps/v1 kind: Deployment metadata: name: crashloop-demo namespace: production spec: replicas: 1 selector: matchLabels: app: crashloop-demo template: metadata: labels: app: crashloop-demo spec: containers: - name: crashloop-demo image: busybox:1.36 command: - sh - -c args: - | echo $(date) simulated crash sleep 5 exit 1应用kubectl apply \ -f crashloop-demo.yaml观察kubectl get pods \ -n production \ -w状态Running ↓ Error ↓ CrashLoopBackOff十、Grafana 查看 Restart Count回到 DashboardGrafana → Dashboards → K8S Lab Runtime Overview查看CrashLoop Restart Count可以看到0 ↓ 1 ↓ 2 ↓ 3说明Container 正在不断重启。这时候 Kubernetes 并不是简单地认为Container 退出一次就是故障。而是观察Container 是否持续退出Restart Count 是否持续增加是否进入 CrashLoopBackOff。这也是为什么我们使用increase( kube_pod_container_status_restarts_total[5m] )作为告警条件。十一、LabCrashLoop Alert进入Grafana → Alerting → Alert rules查看LabCrashLoop状态Inactive ↓ Pending ↓ Firing展开以后severitycritical说明Container 在短时间内发生多次重启。此时 Metrics 已经告诉我们哪个 Pod 出问题。但是还不知道为什么会崩溃。这就需要 Logs。十二、Metrics 找到问题Logs 找原因现在进入Grafana → Explore → Loki查询{namespaceproduction} | simulated crash可以看到simulated crash simulated crash simulated crash因为每次 Container 重启都会执行echo $(date) simulated crash所以排障流程变成Alert ↓ Restart Count 增加 ↓ CrashLoopBackOff ↓ Loki 查看日志 ↓ 找到 simulated crash这就是Metrics 告诉你哪里异常Logs 帮你找到原因。在真实生产环境中也是类似流程监控发现异常 ↓ 定位服务 ↓ 查看指标变化 ↓ 查看日志 ↓ 分析根因十三、恢复 CrashLoop删除kubectl delete deployment \ crashloop-demo \ -n production之后LabCrashLoop Firing ↓ Resolved到这里完成第二个故障闭环Container 异常退出 ↓ Restart Count 增加 ↓ PrometheusRule ↓ Alert ↓ Loki 定位原因 ↓ 恢复十四、故障实验三CPU Stress最后测试资源告警。创建nano cpu-stress.yaml内容apiVersion: apps/v1 kind: Deployment metadata: name: cpu-stress namespace: production spec: replicas: 1 selector: matchLabels: app: cpu-stress template: metadata: labels: app: cpu-stress spec: containers: - name: cpu-stress image: busybox:1.36 command: - sh - -c args: - | while true; do : done resources: requests: cpu: 100m limits: cpu: 500m这里增加requests: cpu: 100m是为了让 Kubernetes 调度时明确知道这个 Pod 至少需要多少 CPU。同时limits: cpu: 500m限制最大 CPU 使用量。应用kubectl apply \ -f cpu-stress.yaml十五、观察 CPUGrafanaExplore → Prometheus查询sum by(pod)( rate( container_cpu_usage_seconds_total{ namespaceproduction, pod~cpu-stress-.* }[1m] ) ) * 1000可以看到CPU 接近 500 mCPU说明cpu-stress正在持续占用 CPU。十六、LabHighCPU Alert等待CPU 300m 持续 1 分钟GrafanaLabHighCPU状态Inactive ↓ Pending ↓ Firing这一次severitywarning因为 CPU 高并不一定代表服务已经不可用。它和DeploymentUnavailable属于不同严重程度。例如服务不可用 业务已经中断 Critical CPU 偏高 可能存在风险 Warning生产环境通常会根据影响范围设置不同等级。十七、清理实验环境删除测试 Deploymentkubectl delete deployment \ crashloop-demo \ cpu-stress \ -n production确认业务恢复kubectl get deployment \ -n production应该只剩jenkins-k8s-demo并且READY 1/1十八、总结上一篇让监控数据真正动起来。这一篇让监控系统自己发现问题。我们没有增加新的组件。只是利用已有的Prometheus Grafana Alertmanager Loki完成三个故障实验。实验一Deployment 不可用replicas0 ↓ Available Replica 0 ↓ DemoDeploymentUnavailable ↓ Alert验证服务副本异常时监控系统可以发现。实验二CrashLoopBackOffContainer crash ↓ Restart Count 增加 ↓ LabCrashLoop ↓ Loki 查看原因验证Metrics 负责发现异常Logs 负责定位原因。实验三CPU StressCPU 持续升高 ↓ LabHighCPU ↓ warning Alert验证资源类问题也可以通过指标提前发现。最终完整链路Kubernetes ↓ Metrics ↓ Prometheus ↓ PrometheusRule ↓ Alert ↓ Grafana Alerting ↓ Loki 排障 ↓ Recovery到了这里这套单节点 K8S 可观测实验室已经不只是能看到系统状态。而是能发现问题并帮助定位问题。从最开始kubectl get pods只能看到Running Pending CrashLoopBackOff到现在Metric ↓ Rule ↓ Alert ↓ Log ↓ Recovery已经形成了一套完整的 Kubernetes 故障发现流程。到这里这套单节点 K8S 可观测实验室也已经完成了从状态查看 ↓ 指标采集 ↓ Metrics 可视化 ↓ 日志分析 ↓ 告警发现 ↓ 故障定位 ↓ 恢复验证的一整套闭环。从最开始只能通过kubectl get pods查看Running Pending CrashLoopBackOff到现在故障发生 ↓ Metric 异常 ↓ PrometheusRule ↓ Alert ↓ Grafana 查看 ↓ Loki 定位 ↓ 恢复验证我们已经搭建了一套完整的 Kubernetes 可观测实验环境。下一篇我们将对整个实验室进行一次总结从零搭建一个单节点 K8S 可观测实验室十三总结——这个实验室如何服务工作、学习和开源项目回顾这一路从 Kubernetes 基础环境、CI/CD、镜像仓库到 Metrics、Logs 和 Alert 的完整搭建过程以及这个实验室对于日常学习、技术积累和实际工作的价值。