故障应急响应:K8s集群故障的分级与SRE处置流程
Kubernetes容器编排环境下的故障应急响应,和传统虚拟机运维有本质区别。Pod随时可能被驱逐、重建,节点可能因为资源压力被标记为NotReady。SRE稳定性工程的核心挑战是:在海量短暂实体中快速定位根因,避免在表象层反复打转。
故障等级定义直接决定应急响应的资源配置和升级路径:
- P0:集群控制平面不可用,多Namespace服务全量不可达
- P1:单Namespace核心业务Pod全部CrashLoop,用户面受损
- P2:部分Pod异常,流量降级但未中断
- P3:单Pod间歇性重启,业务无感知
CrashLoopBackOff诊断:从日志到根因的五步排查法
CrashLoopBackOff是K8s最常见的Pod故障状态,表示容器反复启动失败并退避重启。五步排查流程:
第一步:获取Pod事件和状态
kubectl describe pod <pod-name> -n <namespace>
# 关注输出中的:
# - State: Waiting/Running/Terminated
# - Last State: 上一次退出的code和reason
# - Events: 调度、拉取镜像、启动容器的时序记录
Events区域是最有价值的信息源。如果看到Back-off restarting failed container,说明容器启动后立即退出,需要看容器日志。
第二步:查看容器日志
# 当前容器日志
kubectl logs <pod-name> -n <namespace> --tail=200
# 如果Pod已重启,查看上一次容器的日志
kubectl logs <pod-name> -n <namespace> --previous --tail=200
--previous参数是关键,当前容器的日志可能是空的(刚启动就崩了),上一次容器的日志才有报错信息。
第三步:检查容器退出码
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated}'
退出码含义:
Exit Code 1:应用通用错误,检查应用日志Exit Code 137:OOMKilled,内存超限被内核杀掉Exit Code 139:Segfault,段错误,检查依赖库兼容性Exit Code 143:SIGTERM正常终止,可能是readiness探测失败
第四步:验证配置和依赖
# 检查ConfigMap和Secret是否正确挂载
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A5 "envFrom|volumes"
# 检查资源限制
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[0].resources}'
第五步:本地复现
# 用相同镜像和配置在本地运行
kubectl run debug --image=<image> --rm -it --restart=Never -- /bin/sh
监控告警体系:从指标采集到告警分级的完整配置
故障应急的速度取决于监控告警体系的覆盖度和精确度。K8s环境的标准监控栈是Prometheus+Grafana+Alertmanager。
关键告警规则配置:
# prometheus-rules.yaml
groups:
- name: kubernetes-alerts
rules:
- alert: PodCrashLoopBackOff
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: P2
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} 持续重启"
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
for: 3m
labels:
severity: P1
annotations:
summary: "节点 {{ $labels.node }} NotReady 超过3分钟"
- alert: HighMemoryUsage
expr: container_memory_working_set_bytes / container_spec_memory_limit_bytes > 0.9
for: 2m
labels:
severity: P2
annotations:
summary: "容器 {{ $labels.container }} 内存使用超90%"
- alert: PVNearFull
expr: kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
for: 5m
labels:
severity: P2
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} 使用率超85%"
混沌工程:主动注入故障验证恢复能力
SRE团队不能等到真实故障发生才检验应急响应能力。混沌工程通过可控的故障注入,提前暴露系统的薄弱环节。
Chaos Mesh是K8s生态中最成熟的混沌工程工具,支持Pod故障、网络故障、IO故障等多种注入类型。
# 安装Chaos Mesh
kubectl apply -f https://mirrors.chaos-mesh.org/v2.7/chaos-mesh.yaml
# 注入Pod Kill故障:随机杀死default命名空间下50%的Pod
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: pod-kill-test
namespace: chaos-testing
spec:
action: pod-kill
mode: random-max-percent
value: "50"
selector:
namespaces:
- default
labelSelectors:
app: "web-service"
scheduler:
cron: "@every 300s"
混沌实验必须遵循安全原则:先在预发环境执行,确认服务有足够冗余后才逐步扩大影响范围。每次实验前定义明确的止损条件——例如错误率超过5%立即中止注入。
CI/CD流水线集成:故障自愈的自动化闭环
DevOps实践的终极目标是故障自愈:监控发现异常后自动诊断并修复,无需人工介入。K8s提供了基础的自愈能力(Pod重启、节点驱逐),但更复杂的修复逻辑需要CI/CD流水线联动。
# 故障自愈的Argo Workflow示例
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
name: auto-heal-oom
spec:
entrypoint: heal
templates:
- name: heal
steps:
- - name: diagnose
template: diagnose
- - name: fix-memory
template: fix-memory
when: "{{steps.diagnose.outputs.result}} == OOMKilled"
- - name: notify
template: notify
- name: diagnose
script:
image: bitnami/kubectl
command: [bash]
source: |
EXIT_CODE=$(kubectl get pod {{workflow.parameters.pod}} \
-o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}')
if [ "$EXIT_CODE" = "137" ]; then
echo "OOMKilled"
else
echo "Other"
fi
- name: fix-memory
script:
image: bitnami/kubectl
command: [bash]
source: |
kubectl patch deployment {{workflow.parameters.deployment}} -p \
'{"spec":{"template":{"spec":{"containers":[{"name":"app","resources":{"limits":{"memory":"1.3Gi"}}}]}}}}'
日志分析:从海量日志中快速定位故障链路
K8s环境下日志分散在每个Pod容器中,人工kubectl logs逐个查看效率极低。集中化日志分析方案是必须的:
# EFK栈部署:Elasticsearch + Fluentd + Kibana
# Fluentd DaemonSet采集每个节点的容器日志
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
spec:
selector:
matchLabels:
app: fluentd
template:
spec:
serviceAccountName: fluentd
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.16-elasticsearch7
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.logging.svc"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
故障应急时在Kibana中使用KQL查询特定Pod和时间范围的日志:
kubernetes.pod_name: "web-service-*" AND kubernetes.namespace_name: "production" AND @timestamp: [now-30m TO now] AND log_level: "ERROR"
日志分析的核心价值是还原故障链路:哪个Pod先报错、错误如何传播到下游、最终影响面多大。这比单纯看监控指标更能揭示根因。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-gu-zhang-ying-ji-xiang-ying/