本文目录导读:

在Shell脚本中配置容器资源超卖,主要涉及调整CPU和内存的限制参数,不同容器运行时(Docker、Podman、containerd)和底层资源管理的实现方式不同。
核心思路是:设置高于实际物理资源总量的 limits(上限),或设置较低的 requests(预留)+ 较高的 limits,让调度器认为有更多资源可用。
以下是针对常见场景的Shell脚本配置方法:
Docker 运行时(最常见)
Docker 通过 --cpu-shares(相对权重)、--cpus(绝对限制)和 --memory、--memory-swap 参数实现超卖。
场景:物理机 4核CPU,8GB内存,想跑 8个容器
Shell脚本示例(超卖 CPU 和 内存):
#!/bin/bash
# 容器配置
CONTAINER_IMAGE="nginx:alpine"
CONTAINER_COUNT=8
NETWORK_NAME="my_overlay"
# 每个容器申请的资源(超卖配置)
# CPU:使用 shares(权重),让 8 个容器在 4 核上竞争
# 内存:设置硬限制,但 swap 开高,实际可超卖
CPU_SHARES="1024" # 默认1024,8个容器总和=8192 > 4核理论值
MEMORY_LIMIT="1g" # 每个容器最大1GB
MEMORY_SWAP="2g" # 允许使用swap,变相超卖内存
MEMORY_RESERVATION="512m" # 软限制,保证基础
# 创建网络(如果不存在)
docker network inspect $NETWORK_NAME >/dev/null 2>&1 || docker network create $NETWORK_NAME
# 启动容器实现超卖
for i in $(seq 1 $CONTAINER_COUNT); do
echo "Starting container web-$i with oversubscription..."
docker run -d \
--name "web-$i" \
--network $NETWORK_NAME \
--cpus "0.5" \ # 每个容器限制0.5核,8个总共4核(物理100%)
--cpu-shares $CPU_SHARES \ # 相对权重,所有容器均等
--memory $MEMORY_LIMIT \ # 硬限制1GB
--memory-swap $MEMORY_SWAP \ # swap空间,允许内存超卖
--memory-reservation $MEMORY_RESERVATION \ # 软限制512MB
$CONTAINER_IMAGE
done
echo "8 containers started with CPU oversubscription (8 * 0.5 = 4 cores) and memory oversubscription (8 * 1GB = 8GB total, swap enabled)."
关键参数说明:
--cpus:限制容器使用的 CPU 核心数(可以是非整数,如5)。
超卖技巧:--cpus总和可超过物理核心数,如 4 核机器,--cpus 0.5 * 10 = 5 核。--cpu-shares:默认 1024,所有容器按权重分配 CPU 时间。
超卖技巧: 设置较低值(如 512)让容器被视为“低优先级”,但允许大量容器共存。--memory:硬限制容器内存使用上限。--memory-swap:等于memory + swap总量,设为-1则不限 swap。
超卖技巧:--memory-swap>--memory允许使用 swap,从而运行超过物理内存的容器。--memory-reservation:软限制,只在内存紧张时生效。
Kubernetes 场景(通过 Shell 调度 Pod)
在 Kubernetes 中,超卖通过 ResourceQuota 和 LimitRange 实现,Shell 脚本通常用于创建这些对象。
场景:在 4核16GB 的 Node 上部署大量测试 Pod
Shell脚本示例(创建超卖策略):
#!/bin/bash
NAMESPACE="oversubscription-demo"
# 1. 创建命名空间
kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -
# 2. 创建 LimitRange(默认限制,让没设置的Pod自动拥有超卖配置)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: LimitRange
metadata:
name: oversubscription-limit
namespace: $NAMESPACE
spec:
limits:
- default:
cpu: "1" # 默认 limits CPU = 1核
memory: "512Mi" # 默认 limits 内存 = 512MB
defaultRequest:
cpu: "0.1" # 默认 requests CPU = 0.1核(超卖关键!)
memory: "128Mi" # 默认 requests 内存 = 128MB
type: Container
EOF
# 3. 批量创建 Deployment(每个 Pod 将继承 LimitRange 的超卖配置)
for i in {1..20}; do
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-$i
namespace: $NAMESPACE
spec:
replicas: 1
selector:
matchLabels:
app: app-$i
template:
metadata:
labels:
app: app-$i
spec:
containers:
- name: app
image: nginx:alpine
# 注意:没有显式设置 resources,将使用 LimitRange 默认值
EOF
done
echo "Created 20 pods with oversubscription: each requests 0.1 CPU, limits 1 CPU (10x oversubscription)."
关键点:
requestsvslimits:requests低(0.1核)→ 调度器认为可用资源多。limits高(1核)→ 容器运行时可在空闲时使用更多CPU。
超卖比例:limits / requests = 10:1(10倍超卖)。
LimitRange确保所有 Pod 自动获得超卖配置,无需修改 YAML。
容器运行时底层(cgroups v2 直接操作)
如果使用 containerd 或直接管理 cgroups(如系统容器),Shell 脚本可以直接写入 cgroup 文件。
Shell示例(cgroups v2 直接超卖):
#!/bin/bash # 假设容器 PID 为 $PID,cgroup 路径为 /sys/fs/cgroup/system.slice/containerd-xxx.scope CGROUP_PATH="/sys/fs/cgroup/system.slice/docker-xxxxxxxx.scope" # CPU 超卖:设置 cpu.weight(类似 cpu-shares) # 所有容器权重之和 > 10000 即超卖 echo "2048" > $CGROUP_PATH/cpu.weight # 每个容器给 2048 # 内存超卖:设置 memory.max(硬限制) echo "1G" > $CGROUP_PATH/memory.max # 硬限制 1GB echo "2G" > $CGROUP_PATH/memory.swap.max # 允许 2GB swap # 禁用 OOM killer(内存超卖时避免被杀) echo "0" > $CGROUP_PATH/memory.oom.group # 0 = 禁用组 OOM
关键注意事项
-
物理资源限制:
CPU 超卖通常安全(等待调度),但内存超卖可能导致 OOM Killer 或 Swap 风暴,建议用swappiness=0避免系统卡死:echo "0" > /proc/sys/vm/swappiness
-
监控与驱逐:
超卖环境中必须配置监控,避免资源耗尽,Docker Compose 可加deploy.resources.limits;K8s 需配置 Vertical Pod Autoscaler 或第三方程控。 -
负载类型:
- CPU密集型:超卖比例不超过 2:1(否则响应变慢)。
- 内存空闲型:可 5:1 或更高(适合静态文件服务)。
-
测试脚本:
使用stress工具模拟负载,验证超卖效果:docker run --rm --cpus 0.5 --memory 256m progrium/stress --cpu 2 --vm 1 --vm-bytes 128M
| 运行时 | 超卖方法 | Shell 关键参数 |
|---|---|---|
| Docker | --cpu-shares / --cpus + --memory-swap |
--cpus 0.5 --cpu-shares 1024 --memory 1g --memory-swap 2g |
| K8s | 设置低 requests + 高 limits |
通过 LimitRange 或直接在 YAML 中设置 resources.requests |
| 直接 cgroups | 写入 cpu.weight、memory.max、memory.swap.max |
直接修改 /sys/fs/cgroup/... 文件 |
最佳实践:
- 生产环境不建议过度超卖(CPU < 3x,内存 < 1.5x)。
- 测试环境可大胆超卖(CPU 10x,内存 3x)。
- 始终给核心服务(数据库、K8s 控制面)保留专用资源,不参与超卖。