容器化应用的SLA保障与传统的虚拟机或物理机部署有本质区别。Pod本身是易失的,节点随时可能发生驱逐或宕机,应用实例的IP地址也会频繁变化。如果仍然依赖人工监控和手工重启,响应时间远远达不到分钟级恢复目标。Kubernetes控制平面提供了完整的自愈闭环,但只有正确配置健康检查、资源约束和调度策略,这套机制才会真正生效。下面从指标定义、核心配置、扩缩容和发布策略四个层面展开。

把SLA拆解成可观测的SLO指标
SLA是面向业务方的服务承诺,通常包含可用性百分比、响应时间和错误率。例如一个对外的支付网关可能承诺99.95%的月度可用性,换算下来每月允许故障时间约21.9分钟。这个数字本身对运维没有直接指导意义,必须转换成平台可监控、可告警的SLO指标。在容器化环境中,常用的SLO包括Pod就绪率、请求延迟P99、每分钟5xx错误数量以及节点不可调度时长。
以Pod就绪率为例,可以定义一个Prometheus告警规则,当某个Deployment的就绪副本数低于期望副本数的90%并且持续超过5分钟时触发告警。这个指标能够直接反映滚动更新、节点故障或者镜像拉取失败对服务的影响。另一个关键指标是请求排队时间,容器运行时对CPU和内存的限制会造成节流,导致延迟升高但服务尚未完全不可用,这类“灰色故障”往往比彻底宕机更难以排查。因此SLA保障的第一步不是堆砌工具,而是明确哪些信号真正代表用户可感知的降级。
建议为每个核心服务建立一张SLO对照表,注明指标名称、数据来源、目标值、告警阈值和责任人。同时要区分平台级指标和应用级指标:节点NotReady属于平台级,由集群管理员负责;Pod反复CrashLoopBackOff则更多与应用自身的启动逻辑有关。两者需要的处理流程和升级路径完全不同,混在一起会拖慢故障定位速度。
健康检查与资源配额是可用性底线
就绪探针和存活探针的配置错误是容器化环境中最常见的人为故障源。就绪探针决定Pod是否接收流量,存活探针决定容器是否需要重启。很多团队把两个探针指向同一个HTTP端点,而且设置了非常短的超时时间,导致应用在启动预热阶段被反复杀死。正确做法是根据应用实际启动耗时设置initialDelaySeconds,并为就绪探针配置比存活探针更宽松的失败阈值。
下面是一个较为稳健的探针配置示例,适用于Java或Go这类启动时间可能超过30秒的应用:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 5
资源配额同样直接影响SLA。如果没有设置CPU和内存的request与limit,Pod会被调度到资源紧张节点,发生频繁的OOMKilled或者CPU节流。更严重的是,一个失控的Pod可能耗尽整个节点的内存,导致同节点其他Pod被驱逐,形成连锁故障。每个命名空间应当设置ResourceQuota,限制总资源消耗,每个容器必须声明请求值,避免集群被个别业务挤占。
除了CPU和内存,还要关注临时存储和进程数。从Kubernetes 1.20开始,ephemeral-storage和pids可以被限制,日志写入过大或者进程泄漏同样会拖垮节点。配置资源配额时不能只设上限而不设下限,requests过小会让调度器把过多Pod堆叠到同一节点,一旦该节点故障,受影响副本数会超出预期。
利用调度策略和中断预算控制故障域
默认情况下,Kubernetes调度器会把同一个Deployment的多个副本尽量分散到不同节点,但这只是尽力而为,并不保证严格的反亲和。如果多个副本恰好落在同一台物理机或同一个机架上,一次电源故障或交换机故障就会导致服务全部不可用。使用Pod反亲和规则可以强制副本分布到不同的拓扑域,例如按主机名或区域标签打散。
以下配置强制同一个应用的Pod不能调度到具有相同kubernetes.io/hostname标签的节点上,并且优先跨可用区分布:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- payment-service
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- payment-service
topologyKey: topology.kubernetes.io/zone
PodDisruptionBudget(PDB)是另一个容易被忽略的SLA保障工具。节点维护、集群升级或者资源回收会自动触发Pod驱逐,如果一次性驱逐过多副本,服务会瞬间失去处理能力。PDB可以声明应用在任何时刻必须保持的最小可用副本数或最大不可用副本数。例如一个3副本的服务设置minAvailable: 2,那么驱逐操作会等待至少2个副本就绪后再继续,避免流量全部打到剩余副本上。
PDB并不能阻止所有类型的故障,比如节点物理宕机时,Pod仍然会丢失。但它能有效减少计划内维护造成的可用性损失。同时要注意PDB与HorizontalPodAutoscaler的配合,如果HPA正在缩容,PDB可能会阻塞缩容操作,需要合理设置两者的边界。
自动扩缩容与滚动更新保障持续可用
流量突增是SLA违约的典型场景。HorizontalPodAutoscaler(HPA)可以根据CPU使用率、内存或自定义指标自动调整副本数,但仅靠HPA还不够,因为新Pod启动需要时间,如果流量在几秒内翻倍,HPA的被动响应会造成短暂过载。此时需要配合集群自动扩缩容,提前准备节点资源,或者使用带有预热机制的负载均衡器。
一个实用的HPA配置如下,基于CPU和内存双指标,并设置了快速扩容和缓慢缩容的行为策略:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: payment-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: payment-service
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 30
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 120
滚动更新策略同样深刻影响SLA。默认的maxUnavailable: 25%意味着更新过程中可能损失四分之一副本,对于只有4个副本的服务来说,允许1个不可用,剩余3个可能承压。可以设置maxSurge先创建新Pod再删除旧Pod,或者将maxUnavailable设为0,保证更新期间副本数不低于目标值。但这样需要更多临时资源,集群容量规划时必须预留。
发布过程中的流量切换也需要谨慎。如果新版本启动后立即接收全部流量,而预热未完成,会导致请求延迟飙升。结合Readiness Gate和Ingress控制器的流量权重调整,可以实现渐进式切流。例如使用Argo Rollouts或Flagger进行金丝雀发布,先让5%的流量进入新版本,观察错误率和延迟后再逐步扩大。发布期间一旦指标异常,自动回滚比人工处理快得多。
容器化应用的SLA保障是一个系统性工程,没有单一银弹。从明确SLO指标开始,把探针、配额、反亲和、PDB这些基础配置做扎实,再引入自动扩缩容和灰度发布机制,才能在动态多变的容器环境中维持稳定。很多故障并不是集群本身不可靠,而是配置遗漏或者参数不合理埋下的隐患。定期进行故障演练,例如手动驱逐Pod、切断节点网络,可以提前暴露薄弱环节,远比等到真实故障发生后再补救更有价值。