怎样用脚本自动缩容Docker容器?

wen 实用脚本 2

本文目录导读:

怎样用脚本自动缩容Docker容器?

  1. 方案一:使用 Docker Compose + 脚本修改配置并重建(推荐)
  2. 方案二:直接更新正在运行的容器(Docker API / Systemd)
  3. 方案三:基于 CPU 使用率自动缩容(监控脚本)
  4. 方案四:使用 Docker Compose 的 scale 命令(针对多副本服务)
  5. 方案五:定时任务(Cron)实现夜间低负载缩容
  6. 重要注意事项

自动缩容 Docker 容器通常指减少容器资源限制(CPU、内存),而不是减少容器数量,因为容器本身是静态的,运行后无法直接修改其资源,所以需要通过更新容器配置重建容器来实现。

以下是几种常见的自动化脚本方案,适用于不同场景:

使用 Docker Compose + 脚本修改配置并重建(推荐)

适用场景:容器由 Docker Compose 管理,需要按计划(如夜间)降低资源。

脚本思路:读取 docker-compose.yml,修改资源限制,然后执行 docker-compose up -d 重建。

示例脚本 (Bash):

#!/bin/bash
# 定义缩容后的资源限制
NEW_MEMORY="512m"
NEW_CPU="0.5" # 0.5核
# 要缩容的服务名称(在 docker-compose.yml 中定义)
SERVICE_NAME="my-app"
# 进入项目目录
cd /path/to/your/project
echo "正在修改 docker-compose.yml..."
# 使用 sed 替换资源限制(根据你的 YAML 格式调整)
# 注意:如果启用了 deploy.resources,可能需要修改对应部分
sed -i "s/mem_limit: .*/mem_limit: $NEW_MEMORY/" docker-compose.yml
sed -i "s/cpus: .*/cpus: $NEW_CPU/" docker-compose.yml
echo "正在重新创建容器(缩容)..."
docker-compose up -d --force-recreate $SERVICE_NAME
echo "缩容完成!新资源限制:内存 $NEW_MEMORY, CPU $NEW_CPU"

直接更新正在运行的容器(Docker API / Systemd)

适用场景:容器由 docker run 直接创建,且容器进程支持运行时资源热调整(Docker 支持,但需要容器内有 cgroup 挂载)。

原理:使用 docker update 命令。

示例脚本:

#!/bin/bash
# 指定容器名或ID
CONTAINER_NAME="my-container"
# 缩容后的限制
NEW_MEMORY="256m"
NEW_CPU_SHARES="256" # CPU 权重,相对值
echo "正在热更新容器 ${CONTAINER_NAME} 的资源限制..."
docker update --memory=$NEW_MEMORY --cpu-shares=$NEW_CPU_SHARES $CONTAINER_NAME
# 验证
echo "当前限制:"
docker inspect $CONTAINER_NAME | grep -A 2 "Memory\|CpuShares"

基于 CPU 使用率自动缩容(监控脚本)

适用场景:根据容器实际负载自动调整(CPU > 80% 时缩容)。

示例脚本(Python):

#!/usr/bin/env python3
import subprocess
import json
import time
THRESHOLD_CPU = 80.0  # 触发缩容的CPU百分比
SCALE_DOWN_PERCENT = 0.7  # 缩容到当前资源的70%
def get_container_stats(container_id):
    result = subprocess.run(
        ["docker", "stats", "--no-stream", "--format", "{{json .}}", container_id],
        capture_output=True, text=True
    )
    if result.returncode != 0:
        return None
    try:
        stats = json.loads(result.stdout.strip())
        cpu_percent = float(stats["CPUPerc"].replace("%", ""))
        mem_usage = stats["MemUsage"].split("/")[0].strip()
        # 解析内存,"1.2GiB" -> 转换为字节
        if "GiB" in mem_usage:
            mem_bytes = float(mem_usage.replace("GiB", "")) * 1024**3
        elif "MiB" in mem_usage:
            mem_bytes = float(mem_usage.replace("MiB", "")) * 1024**2
        else:
            mem_bytes = float(mem_usage.replace("KiB", "")) * 1024
        return cpu_percent, mem_bytes
    except:
        return None
def auto_scale_down(container_name):
    print(f"监控容器: {container_name}")
    while True:
        stats = get_container_stats(container_name)
        if stats:
            cpu, mem = stats
            print(f"当前 CPU: {cpu:.1f}%,内存: {mem/(1024**2):.1f} MiB")
            if cpu > THRESHOLD_CPU:
                new_mem = int(mem * SCALE_DOWN_PERCENT)
                new_cpu_shares = int(1024 * SCALE_DOWN_PERCENT)  # 1024 为默认
                print(f"CPU 超限 ({cpu}%),正在缩容...")
                subprocess.run([
                    "docker", "update",
                    "--memory", f"{new_mem}",
                    "--cpu-shares", str(new_cpu_shares),
                    container_name
                ])
                print("缩容完成")
        else:
            print("无法获取容器统计信息")
        time.sleep(60)  # 每分钟检查一次
if __name__ == "__main__":
    auto_scale_down("my-container")

使用 Docker Compose 的 scale 命令(针对多副本服务)

注意:这不是严格意义的“缩容”,而是减少容器副本数。

docker-compose up -d --scale my-service=1   # 将 my-service 缩容到 1 个副本

定时任务(Cron)实现夜间低负载缩容

/etc/cron.d/scale-down 中添加:

# 每天凌晨2点缩容
0 2 * * * root /usr/local/bin/scale-down.sh

重要注意事项

  1. 不可逆性:缩容操作需要回滚策略,如果缩容后业务负载回升,需要准备扩容器脚本。
  2. 内存限制docker update 只对内存和 CPU 权重生效,无法热更新 --cpus 参数(需重启容器)。
  3. 容器内进程:如果容器内进程不响应 SIGTERM 信号,直接 --force-recreate 会强杀。
  4. 建议使用编排工具:对于生产环境,更推荐使用 Kubernetes HPA(水平自动伸缩)Docker Swarm 的 service update 进行资源管理。

推荐实践:如果只是简单环境,使用 方案二(docker update) 最快捷;如果需要复杂策略,用 方案三(Python监控) 结合 方案五(Cron)

抱歉,评论功能暂时关闭!