You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置CPU阈值触发Docker容器故障并自动重建的方法

实现Docker Swarm服务在CPU占用过高时自动重启的方案

针对你遇到的Java进程在Swarm服务中CPU持续满载、需要在95%占用时自动故障重建的需求,这里提供几个可行的实现方案,从简单到复杂按需选择:

方案一:利用Docker健康检查(HEALTHCHECK)触发自动重启

这是最轻量化的方案,无需额外监控工具,通过容器内的健康检查脚本判断CPU使用率,一旦超过阈值就让健康检查失败,Swarm会自动重启容器。

步骤1:编写CPU监控的健康检查脚本

在你的Java应用镜像中添加一个shell脚本(比如cpu-healthcheck.sh),内容如下:

#!/bin/bash
# 获取容器内Java进程的CPU使用率(过滤掉grep自身进程)
JAVA_CPU=$(ps aux | grep java | grep -v grep | awk '{print $3}')
# 转换为整数,避免小数比较问题
CPU_THRESHOLD=95
CPU_USAGE=$(printf "%.0f" "$JAVA_CPU")

if [ "$CPU_USAGE" -ge "$CPU_THRESHOLD" ]; then
  echo "[FAILURE] CPU usage is ${CPU_USAGE}%, exceeding threshold ${CPU_THRESHOLD}%"
  exit 1  # 健康检查失败
else
  echo "[SUCCESS] CPU usage is ${CPU_USAGE}%, within threshold"
  exit 0  # 健康检查正常
fi

步骤2:修改Dockerfile集成健康检查

确保镜像中包含ps、grep、awk这些工具(基础镜像如果是Alpine,需要安装procps;Ubuntu/Debian则默认有),然后添加健康检查指令:

# 以Alpine为例,安装依赖工具
RUN apk add --no-cache procps bash

# 添加健康检查脚本
COPY cpu-healthcheck.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/cpu-healthcheck.sh

# 配置健康检查:每10秒检查一次,超时5秒,启动后30秒开始检查,失败2次标记为不健康
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=2 \
  CMD /usr/local/bin/cpu-healthcheck.sh

步骤3:部署Swarm服务时配置重启策略

创建服务时指定重启条件为on-failure,这样当健康检查失败时Swarm会自动重启容器:

docker service create \
  --name your-java-service \
  --restart-condition on-failure \
  --restart-max-attempts 5 \  # 可选:限制最大重启次数,避免无限循环
  --limit-cpu 1 \
  your-java-image:latest

方案二:用外部监控栈(Prometheus + Alertmanager)触发重启

如果你的集群已经有监控体系,这个方案更灵活,适合多服务统一管理:

  1. 采集Swarm容器指标:配置Prometheus采集Docker Daemon的metrics(通过部署prom/node-exporter或直接启用Docker内置的metrics端点)。
  2. 配置告警规则:在Prometheus中添加规则,当基于container_cpu_usage_seconds_total计算出的CPU使用率持续5分钟超过95%时触发告警。
  3. 配置Alertmanager Webhook:编写一个简单的web服务,接收Alertmanager的告警请求后,调用Docker API执行docker service update --force your-java-service(或直接删除异常容器),触发Swarm重建服务。

方案三:自定义Swarm监控服务

编写一个独立的监控脚本,部署成Swarm服务,定期检查目标服务的容器CPU使用率,超过阈值就主动删除容器让Swarm重建:

示例监控脚本(shell版)

#!/bin/bash
TARGET_SERVICE="your-java-service"
CPU_THRESHOLD=95
CHECK_INTERVAL=10

while true; do
  # 获取目标服务下所有运行中的任务ID
  docker service ps -q --filter desired-state=running "$TARGET_SERVICE" | while read TASK_ID; do
    # 获取任务对应的容器ID
    CONTAINER_ID=$(docker inspect -f '{{.Status.ContainerStatus.ContainerID}}' "$TASK_ID")
    if [ -n "$CONTAINER_ID" ]; then
      # 获取容器CPU使用率(去掉%符号并转为整数)
      CPU_USAGE=$(docker stats --no-stream --format "{{.CPUPerc}}" "$CONTAINER_ID" | sed 's/%//')
      CPU_USAGE_INT=$(printf "%.0f" "$CPU_USAGE")
      
      if [ "$CPU_USAGE_INT" -ge "$CPU_THRESHOLD" ]; then
        echo "$(date): Container $CONTAINER_ID CPU usage ${CPU_USAGE_INT}%, restarting..."
        docker container rm -f "$CONTAINER_ID"
      fi
    fi
  done
  sleep "$CHECK_INTERVAL"
done

部署监控服务

将脚本打包成镜像,挂载Docker套接字以获取权限:

docker service create \
  --name cpu-monitor \
  --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
  your-monitor-image:latest

额外建议

虽然自动重启能临时解决问题,但Java进程持续高CPU通常是代码死循环、内存泄漏、线程阻塞等根源问题导致的。建议结合jstack、jmap等工具分析线程栈和内存快照,从代码层面解决问题,避免频繁重启影响业务稳定性。

内容的提问来源于stack exchange,提问作者Rajesh Rajendran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:28:54