容器在宿主机上共享同一个 Linux 内核,因此宿主机的内核参数、文件系统、安全模块和网络配置会直接影响所有容器的稳定性、性能和安全边界。以下优化项均来自生产环境检验,简单明了,可直接参考。
1. 内核参数调优(sysctl)
容器本质上是一组进程,高强度运行时容易触发内核的网络连接跟踪、文件监视和内存回收瓶颈。在 /etc/sysctl.conf 或 /etc/sysctl.d/99-container.conf 中集中调整以下参数,然后执行 sysctl -p 使其生效。
- 网络篇
# 扩大连接跟踪表,避免高并发时丢包
net.netfilter.nf_conntrack_max = 2097152
# 缩短 TIME_WAIT 连接回收和重用,加快端口释放
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
# 增加监听队列长度,应对突发连接
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 8192
# 允许将 TIME_WAIT 连接用于新请求(与 tw_reuse 配合)
net.ipv4.tcp_tw_recycle = 0 # 容器环境应关闭 recycle,避免 NAT 问题
# 扩大本地端口范围,防止端口耗尽
net.ipv4.ip_local_port_range = 10240 65535
- 文件监视与存储
# 增加 inotify 用户实例数和监视数,容器内程序(如 webpack、nodemon)常用
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 524288
- 内存与交换
# 降低使用 swap 的倾向,容器场景希望尽量用内存
vm.swappiness = 1
# 避免过度使用透明大页,可能造成内存碎片(建议关闭或设为 madvise)
vm.zone_reclaim_mode = 0
# 透明大页若造成延迟,可通过 /sys/kernel/mm/transparent_hugepage/enabled 设为 never 或 madvise
2. 存储驱动与文件系统
- 存储驱动选择
推荐使用 overlay2,它性能好、内存消耗低、内核原生支持。在 Docker 的 /etc/docker/daemon.json 中明确指定:
{
"storage-driver": "overlay2"
}
- 文件系统
宿主机承载容器镜像和卷的磁盘应使用支持 d_type 的文件系统,如 ext4 或 xfs。挂载数据分区时建议添加 noatime 减少写入:
/dev/sdb1 /var/lib/docker ext4 defaults,noatime 0 2
3. 资源限制与 cgroup
容器不是虚拟机,必须通过 cgroup 严格限制资源,避免单个容器耗尽宿主机资源。
- 使用 cgroup v2
主流发行版(Ubuntu 22.04+、Debian 11+、RHEL 9+)默认启用 cgroup v2,提供更佳的隔离和内存管理。确认:
stat -fc %T /sys/fs/cgroup/
# 输出 cgroup2fs 即为 v2
- 容器运行时级限制
以 Docker 为例,启动容器时始终指定 --memory 和 --cpus 参数,否则容器可无限抢占资源。
docker run -d --memory="512m" --cpus="1.5" --name app myimage
在容器编排平台(Kubernetes)中,Pod 的 resources.limits 必须填写。
- 全局 ulimit 调整
容器内进程能打开的文件数过小会引发 “Too many open files” 错误。启动容器时提升:
docker run --ulimit nofile=65536:65536 ...
或在 Docker Engine 配置中设置默认值:
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65536,
"Soft": 65536
}
}
}
4. 安全与内核模块
- 必须的内核模块
容器网络和存储强依赖几个内核模块,确认已加载:
modprobe overlay # overlay2 存储驱动需要
modprobe br_netfilter # 跨主机容器通信需要
lsmod | grep -E 'overlay|br_netfilter'
可在 /etc/modules-load.d/docker.conf 中写入模块名使其开机加载。
- AppArmor / SELinux
不要关闭 SELinux 或 AppArmor,保持 enforcing 模式,并利用容器运行时的安全策略(如 Docker 的 seccomp profile、AppArmor 配置文件)加固容器。
# 查看 SELinux 状态
getenforce
# 查看 AppArmor 状态
aa-status
- 用户命名空间
对于高安全要求的环境,启用 user namespace 映射,避免容器内 root 与宿主机 root 等价。在 Docker daemon 配置中加入:
{
"userns-remap": "default"
}
5. 网络性能优化
- 增大 conntrack 表(已在 sysctl 提及)。
- 避免 iptables 规则膨胀
大量容器启停会生成成千上万条 iptables 规则,拖慢数据包处理。应定期清理不用的规则,或使用 nftables(默认在较新 Docker 中已切换)。检查规则数量:
iptables-save | wc -l
- 启用 IPVS 模式(Kubernetes)
若使用 kube-proxy,用 IPVS 替代 iptables 模式,可显著降低大规模 Service 下的 CPU 开销:
kube-proxy --proxy-mode=ipvs
确保内核加载了 ip_vs、ip_vs_rr 等模块。
6. 日志管理
容器产生的标准输出和标准错误默认为 json-file 驱动写入磁盘,若无限制容易撑爆宿主机。
- 在
/etc/docker/daemon.json中配置日志轮转:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
- 或使用
journald驱动,合并到系统日志,由 journald 统一处理轮转。
7. 内核实时性与高性能场景
对于延迟敏感的容器应用(如金融撮合、5G 核心网),可考虑使用 PREEMPT_RT 实时内核补丁,并将容器绑定到隔离的 CPU 核心上,避免调度抖动。同时将 cpu-manager 策略设为 static(Kubernetes)。
8. 定期清理与审计
- 设置定时任务清理停止的容器、无用镜像和卷,避免 inode 耗尽:
docker system prune -af --volumes --filter "until=72h"
- 监控宿主机 inode 使用率,容器镜像和挂载点会大量消耗 inode:
df -i
以上各项优化不需要全部照搬,可根据实际负载逐项启用。关键原则是:容器化部署后,宿主机的稳定性和性能决定了所有容器的底线,通过可量化的参数把资源隔离开,才能充分发挥容器轻量、高效的优势。