Shell脚本如何配置容器ulimit限制

wen 实用脚本 2

本文目录导读:

Shell脚本如何配置容器ulimit限制

  1. 使用 ulimit 命令配置当前Shell
  2. Docker容器运行时配置
  3. 在Dockerfile中配置
  4. 完整的配置脚本示例
  5. Kubernetes环境配置
  6. 不同容器运行时的注意事项
  7. 常见ulimit参数说明
  8. 验证配置

在Shell脚本中配置容器的ulimit限制,主要有以下几种方法:

使用 ulimit 命令配置当前Shell

#!/bin/bash
# 设置各种限制
ulimit -n 65535        # 最大文件打开数
ulimit -u 65535        # 最大用户进程数
ulimit -s 65536        # 最大栈大小(KB)
ulimit -c 0            # 关闭core文件
ulimit -m unlimited    # 内存限制不限制
# 查看当前限制
ulimit -a

Docker容器运行时配置

通过docker run命令

#!/bin/bash
# 启动容器时设置ulimit
docker run -d \
  --name mycontainer \
  --ulimit nofile=65535:65535 \
  --ulimit nproc=65535:65535 \
  --ulimit stack=67108864:67108864 \
  --ulimit core=0:0 \
  nginx:latest

通过docker-compose配置

version: '3.8'
services:
  myapp:
    image: nginx:latest
    ulimits:
      nofile:
        soft: 65535
        hard: 65535
      nproc:
        soft: 65535
        hard: 65535
      stack:
        soft: 67108864
        hard: 67108864

在Dockerfile中配置

FROM ubuntu:20.04
# 设置默认ulimit(需要容器运行时privileged或调整docker daemon配置)
RUN echo "root soft nofile 65535" >> /etc/security/limits.conf && \
    echo "root hard nofile 65535" >> /etc/security/limits.conf && \
    echo "* soft nofile 65535" >> /etc/security/limits.conf && \
    echo "* hard nofile 65535" >> /etc/security/limits.conf
# 使用entrpoint脚本设置
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh:

#!/bin/bash
# 设置ulimit
ulimit -n 65535
ulimit -n ${MAX_OPEN_FILES:-65535}
# 执行主程序
exec "$@"

完整的配置脚本示例

#!/bin/bash
# 配置容器ulimit的完整脚本
# 适应不同容器运行时
set -e
# 检查是否是容器环境
is_container() {
    [ -f /.dockerenv ] || [ -f /run/.containerenv ] || [ "$container" = "docker" ] || [ "$container" = "podman" ]
}
# 配置ulimit函数
configure_ulimit() {
    local soft_limit=${1:-65535}
    local hard_limit=${2:-65535}
    echo "配置ulimit参数..."
    # 尝试设置各种资源限制
    ulimit -n "$soft_limit" 2>/dev/null || echo "警告: 无法设置文件打开数限制"
    ulimit -u "$soft_limit" 2>/dev/null || echo "警告: 无法设置进程数限制"
    ulimit -s 65536 2>/dev/null || echo "警告: 无法设置栈大小"
    ulimit -c 0 2>/dev/null
    # 显示当前限制
    echo "当前ulimit设置:"
    ulimit -a
}
# 配置系统级限制(需要root权限)
configure_system_limits() {
    if [ "$(id -u)" = "0" ]; then
        echo "配置系统级限制..."
        # 修改limits.conf
        cat >> /etc/security/limits.conf <<EOF
*               soft    nofile          65535
*               hard    nofile          65535
*               soft    nproc           unlimited
*               hard    nproc           unlimited
EOF
        # 配置systemd服务限制
        if command -v systemctl &> /dev/null; then
            mkdir -p /etc/systemd/system/user@.service.d/
            cat > /etc/systemd/system/user@.service.d/limits.conf <<EOF
[Service]
LimitNOFILE=65535
LimitNPROC=65535
LimitSTACK=67108864
EOF
            systemctl daemon-reload 2>/dev/null || true
        fi
        echo "系统限制配置完成"
    else
        echo "非root用户,跳过系统级配置"
    fi
}
# 主函数
main() {
    echo "配置容器ulimit限制..."
    # 识别运行环境
    if is_container; then
        echo "检测到容器环境"
        configure_system_limits
    fi
    # 配置当前shell的ulimit
    configure_ulimit
    echo "ulimit配置完成!"
    # 执行主程序(如果作为entrypoint使用)
    if [ $# -gt 0 ]; then
        exec "$@"
    fi
}
# 执行主函数
main "$@"

Kubernetes环境配置

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: myapp
    image: nginx:latest
    resources:
      limits:
        memory: "512Mi"
        cpu: "500m"
    securityContext:
      capabilities:
        add: ["SYS_RESOURCE"]  # 需要此权限
    # 在容器中设置ulimit由OCI运行时处理

不同容器运行时的注意事项

#!/bin/bash
# Docker配置
echo "Docker默认ulimit:"
docker run --rm alpine ulimit -a
# Podman配置(通常更宽松)
echo "Podman默认ulimit:"
podman run --rm alpine ulimit -a
# Containerd配置(通过nerdctl)
echo "Containerd配置:"
nerdctl run --rm --ulimit nofile=65535:65535 alpine ulimit -n

常见ulimit参数说明

unlimited  # 无限(需要root)
- # 硬件限制
soft # 当前能使用的限制
hard # 最大限制
主要参数:
-n # 最大打开文件描述符数
-u # 最大用户进程数
-s # 栈大小(KB)
-c # core文件大小(KB)
-m # 最大内存大小(KB)
-v # 最大虚拟内存(KB)
-l # 锁住内存的大小

验证配置

#!/bin/bash
# 验证ulimit设置
echo "验证ulimit配置..."
ulimit -n # 查看文件打开数
ulimit -u # 查看进程数
ulimit -a # 查看所有限制
# 测试文件打开限制
test_file_limit() {
    local count=$(( $(ulimit -n) ))
    echo "理论最大文件打开数: $count"
    # 实际测试(谨慎执行)
    # for i in $(seq 1 $count); do
    #     exec {fd}>/dev/null 2>/dev/null || break
    # done
    # echo "实际打开文件数: $((i-1))"
}

配置ulimit时要注意:

  • 有些限制需要特权模式(--privileged)
  • 不同的容器运行时默认值不同
  • 建议在entrypoint脚本中统一配置
  • 考虑安全性和资源限制的平衡

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