Cgroup ,ulimit,内核参数
等限制进程、系统级别内存资源我看远山,远山悲悯
持续分享技术干货,感兴趣小伙伴可以关注下 ^_^
今天和小伙伴分享一些Linux 内存限制
相关知识,主要涉及如何配置以及什么情况下需要配置
,我们知道内存属于不可压缩资源
,当没有那么多的物理内存可以映射,进程都无法启动,所以为了公平,亦或是考虑部分进程 Qos 级别,一般情况下会对进程进行内存限制
,即保证机器上的多个进程不会因为业务对基础资源的弹性要求,相互影响
,比如类似FTP进程
的内存泄露
问题影响到核心业务服务触发 OOM
,甚至直接被OOM killer
掉。
简单介绍,关于内存资源限制在 Linux
中,一般按照限制手段
来划分的话,分为
sysctl -w vm.swappiness=10
, 启动引导配置大页参数grubby --update-kernel=ALL --args="hugepagesz=1G hugepages=10"
/sys/fs/cgroup/memory/myapp/memory.limit_in_bytes
,MemoryMax=1G
ulimit -v 2097152
三种方式,按照限制类型
划分,一般分为
sysctl -w vm.overcommit_memory=2
禁止过度分配虚拟内存MemoryMax=1G
echo "john hard as 2097152" >> /etc/security/limits.conf
限制用户 john 的进程最大虚拟内存(地址空间)为 2 GB如果按照具体的内存种类
划分,可以分为:
物理、虚拟
内存限制: 硬限制物理内存大小 memory.limit_in_bytes
, 会话级别虚拟内存限制 ulimit -v
ulimit -d 262144
设置数据段的最大值vm.drop_caches
,网络IO 相关缓存区配置 net.ipv4.tcp_rmem
vm.nr_hugepages
Cgroup(Control Groups)
最早由 google 开发,后来内置到了 Linux 内核中,是Linux kernel(Linux内核)
的一项功能,目前是很多虚拟化容器技术的底层核心技术。
在一个系统中运行的层级制进程组
,Cgroup
可对其进行资源分配(如CPU时间、系统内存、网络带宽或者这些资源的组合)
。
通过使用cgroup
,系统管理员在分配、排序、拒绝、管理和监控系统资源等方面,可以进行精细化控制。硬件资源可以在应用程序和用户间智能分配,从而增加整体效率。
Cgroup
可对进程
进行层级式分组并标记
,并对其可用资源进行限制
。通过将cgroup
层级系统与systemd
单位树捆绑, Linux 可以把资源管理设置从进程级别
移至应用程序
级别。
可以使用systemctl指令,或者通过修改systemd单位文件来管理系统资源。
为了控制重要的内核资源,systemd
会自动挂载/sys/fs/cgroup
目录实现 cgroup
分层架构,Linux 内核的资源管理器,也叫 CGroup 子系统,代表某一种单一资源(如 CPU 时间或内存等
Linux 内核提供了一系列资源管理器,由 systemd
自动挂载。如果需要查看已经挂载的资源管理器列表,可以参考/proc/cgroups
内存子系统位于其中:
memory
: 对 cgroup 中的任务使用内存量进行限制,并且自动生成任务占用内存资源的报告
在安装了 kernel-doc 软件包后,可以在/usr/share/doc/kernel-doc-<version>/Documentation/cgroup
目录下找相关管理器的说明文档,从而配置合适的资源限制
┌──[root@liruilongs.github.io]-[/usr/share/doc/kernel-doc-4.18.0/Documentation/cgroup-v1]
└─$ls
00-INDEX cgroups.txt cpusets.txt freezer-subsystem.txt memcg_test.txt net_cls.txt pids.txt
blkio-controller.txt cpuacct.txt devices.txt hugetlb.txt memory.txt net_prio.txt rdma.txt
┌──[root@liruilongs.github.io]-[/usr/share/doc/kernel-doc-4.18.0/Documentation/cgroup-v1]
└─$ll
total 184
。。。。。。。。。。。。。。。。
-r--r--r--. 1 root root 8480 Mar 27 2020 memcg_test.txt
-r--r--r--. 1 root root 37743 Mar 27 2020 memory.txt
................
简单的信息可以通过索引文件的了解
┌──[root@liruilongs.github.io]-[/usr/share/doc/kernel-doc-4.18.0/Documentation/cgroup-v1]
└─$cat 00-INDEX
。。。。。。。
memcg_test.txt
- Memory Resource Controller; implementation details.
memory.txt
- Memory Resource Controller; design, accounting, interface, testing.
。。。。。。。。。。。。。。。。。。。。。
┌──[root@liruilongs.github.io]-[/usr/share/doc/kernel-doc-4.18.0/Documentation/cgroup-v1]
└─$
Cgroup 限制内存资源常见的有两种,一种是 通过 systemd,一种是直接通过 cgroup 文件系统进行配置,这里我们先介绍通过 systemd
的方式配置,因为这种方式比较简单,而且可以做到进程级别
的配置,而通过 cgroup
的方式,可以做到系统级别
的配置,前提是当前Linux 机器使用 systemd,并且所有启动进程纳管到了 cgroup 子树,那么可以通过限制顶层树的资源限制,来实现整个系统的资源限制。
在 systemd
的 drop-in
文件文件[Service]
段里面定义 MemoryLimit
值就可以限制你的程序所使用的内存,单位可以是K,M,G或T。
这里看一个以临时服务的方式运行 /bin/bash
命令的Demo ,对 内存和CPU 进行限制, 并将其标准输入、标准输出、标准错误连接到当前的 TTY 设备上:
┌──[root@liruilongs.github.io]-[~]
└─$ systemd-run -p MemoryLimit=5M -p CPUShares=100 --unit=bash-limit --slice=bash-test -t /bin/bash
Running as unit bash-limit.service.
Press ^] three times within 1s to disconnect TTY.
在生成的 bash Service
中我们可以运行交互命令,查看当前 Service 的单元文件,MemoryLimit=5242880
,即限制内存使用量 5M
┌──[root@liruilongs.github.io]-[/]
└─$ systemctl cat bash-limit.service
# /run/systemd/system/bash-limit.service
# Transient stub
# /run/systemd/system/bash-limit.service.d/50-CPUShares.conf
[Service]
CPUShares=100
# /run/systemd/system/bash-limit.service.d/50-Description.conf
[Unit]
Description=/bin/bash
# /run/systemd/system/bash-limit.service.d/50-Environment.conf
[Service]
Environment="TERM=xterm-256color"
# /run/systemd/system/bash-limit.service.d/50-ExecStart.conf
[Service]
ExecStart=
ExecStart=@/bin/bash "/bin/bash"
# /run/systemd/system/bash-limit.service.d/50-MemoryLimit.conf
[Service]
MemoryLimit=5242880
# /run/systemd/system/bash-limit.service.d/50-Slice.conf
。。。。。。。。。。。。。。。。。。。。。。。。
通过 systemctl status bash-limit.service
我们可以看到cgroup
的相关信息
┌──[root@liruilongs.github.io]-[/]
└─$ systemctl status bash-limit.service
● bash-limit.service - /bin/bash
Loaded: loaded (/run/systemd/system/bash-limit.service; static; vendor preset: disabled)
Drop-In: /run/systemd/system/bash-limit.service.d
└─50-CPUShares.conf, 50-Description.conf, 50-Environment.conf, 50-ExecStart.conf, 50-MemoryLimit.conf, 50-Slice.conf, 50-StandardError.conf, 50-StandardInput.conf, 50-StandardOutput.conf, 50-TTYPath.conf
Active: active (running) since 六 2022-10-29 13:40:19 CST; 31s ago
Main PID: 136529 (bash)
Memory: 1.7M (limit: 5.0M)
CGroup: /bash.slice/bash-test.slice/bash-limit.service
├─136529 /bin/bash
└─136607 systemctl status bash-limit.service
10月 29 13:40:19 liruilongs.github.io systemd[1]: Started /bin/bash.
┌──[root@liruilongs.github.io]-[/]
└─$ bash
┌──[root@liruilongs.github.io]-[/]
└─$ bash
bash-limit.service 这个 service 的上级子树为 bash.slice 这个分组。
Memory: 1.7M (limit: 5.0M)
CGroup: /bash.slice/bash-test.slice/bash-limit.service
├─136529 /bin/bash
└─136607 systemctl status bash-limit.service
当然上面的配置方式实际上是基于 Cgroup
来实现的,Cgroup V1 版本和 V2 版本有些区别,当前机器环境的问题,我们只看一下 V1 的版本,MemoryLimit 参数可以控制Cgroup 内存控制器的 memory.limit_in_bytes Cgroup参数
。
对于运行中的 service 可以直接通过set-property 的方式来修改
# 如需使用命令列来限定 httpd.service 的 CPU 和内存占用量,请输入:
systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M
下面为 system.slice
这个 Cgroup
分组下面 tuned Cgroup
内存相关资源限制,可以看到默认的情况下没有限制(memory.limit_in_bytes
),使用的最大值,这里的内存限制是物理内存,不是虚拟内存,
tuned 小伙伴们应该不陌生,一个开源的系统性能优化的服务,用于一些内核参数限制
┌──[root@liruilongs.github.io]-[/sys/fs/cgroup/memory/system.slice]
└─$cat tuned.service/memory.
memory.events memory.kmem.tcp.failcnt memory.memsw.failcnt memory.qos_level
memory.events.local memory.kmem.tcp.limit_in_bytes memory.memsw.limit_in_bytes memory.soft_limit_in_bytes
memory.failcnt memory.kmem.tcp.max_usage_in_bytes memory.memsw.max_usage_in_bytes memory.stat
memory.force_empty memory.kmem.tcp.usage_in_bytes memory.memsw.usage_in_bytes memory.swappiness
memory.high memory.kmem.usage_in_bytes memory.min memory.usage_in_bytes
memory.kmem.failcnt memory.limit_in_bytes memory.move_charge_at_immigrate memory.use_hierarchy
memory.kmem.limit_in_bytes memory.low memory.numa_stat
memory.kmem.max_usage_in_bytes memory.max_usage_in_bytes memory.oom_control
memory.kmem.slabinfo memory.memfs_files_info memory.pressure_level
默认情况下,没有限制会显示最大值
┌──[root@liruilongs.github.io]-[/sys/fs/cgroup/memory/system.slice]
└─$cat tuned.service/memory.limit_in_bytes
9223372036854771712
配置方式我们可以通过上面的方式配置,通过 service unit 文件进行限制
限定最大可用内存为 1GB,添加 MemoryLimit 设定
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$vim tuned.service
确认配置,加载配置文件,重启
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl cat tuned.service
# /usr/lib/systemd/system/tuned.service
[Unit]
Description=Dynamic System Tuning Daemon
After=systemd-sysctl.service network.target dbus.service
Requires=dbus.service polkit.service
Conflicts=cpupower.service auto-cpufreq.service tlp.service power-profiles-daemon.service
Documentation=man:tuned(8) man:tuned.conf(5) man:tuned-adm(8)
[Service]
Type=dbus
MemoryLimit=1G
PIDFile=/run/tuned/tuned.pid
BusName=com.redhat.tuned
ExecStart=/usr/sbin/tuned -l -P
Restart=on-failure
[Install]
WantedBy=multi-user.target
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl daemon-reload
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl restart tuned.service
再次查看 Cgroup 内存相关限制参数
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$cat /sys/fs/cgroup/memory/system.slice/tuned.service/memory.limit_in_bytes
1073741824
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$
生产环境,更多的是通过 drop-in
的方式定义文件
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$vim tuned.service.d/50-MemoryLimit.conf
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl daemon-reload
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl restart tuned.service
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$systemctl cat tuned.service
# /usr/lib/systemd/system/tuned.service
[Unit]
Description=Dynamic System Tuning Daemon
After=systemd-sysctl.service network.target dbus.service
Requires=dbus.service polkit.service
Conflicts=cpupower.service auto-cpufreq.service tlp.service power-profiles-daemon.service
Documentation=man:tuned(8) man:tuned.conf(5) man:tuned-adm(8)
[Service]
Type=dbus
PIDFile=/run/tuned/tuned.pid
BusName=com.redhat.tuned
ExecStart=/usr/sbin/tuned -l -P
Restart=on-failure
[Install]
WantedBy=multi-user.target
# /usr/lib/systemd/system/tuned.service.d/50-MemoryLimit.conf
[Service]
MemoryLimit=1G
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]
└─$
这里我们简单看一下,其他的 Cgroup
参数限制,部分参数在 Cgroup V2 中作了调整,感兴趣小伙伴可以看看去
核心内存限制
参数 | 作用 |
---|---|
memory.limit_in_bytes | 物理内存硬限制(单位:字节),超出会触发 OOM Killer。 |
memory.memsw.limit_in_bytes | 物理内存 + swap 总限制(需内核启用 swapaccount=1)。 |
memory.soft_limit_in_bytes | 内存软限制,系统优先回收超过此值的内存,但不会强制杀死进程。 |
内核内存控制
参数 | 作用 |
---|---|
memory.kmem.limit_in_bytes | 内核内存(如 slab、dentry 缓存)的硬限制。 |
memory.kmem.tcp.limit_in_bytes | TCP 缓冲区内存的硬限制(如 TCP socket 发送/接收缓冲区)。 |
内存回收与行为控制
参数 | 作用 |
---|---|
memory.force_empty | 强制释放内存缓存(写入 0 触发)。 |
memory.swappiness | 调整内存回收策略(值越高,系统越积极使用 swap)。 |
memory.oom_control | 控制 OOM Killer 行为(0 表示启用 OOM Killer,1 表示禁用)。 |
memory.move_charge_at_immigrate | 进程迁移时是否转移内存占用(1 表示转移)。 |
高级功能
参数 | 作用 |
---|---|
memory.high | 内存使用软限制(v1 中较少使用,v2 中更常见)。 |
memory.low | 内存保护阈值,系统尽量避免回收低于此值的内存。 |
memory.pressure_level | 内存压力事件通知(需配合 cgroup.event_control 使用)。 |
对于这部分参数的配置,可以直接找到对应的 Cgroup
文件进行修改
# 限制 TCP 缓冲区为 100MB
echo "100M" > memory.kmem.tcp.limit_in_bytes
对于多用户
的系统不限制资源
本身可能就是一种不公平
, 限制系统资源比较老的方式是使用 ulimit
,由 PAM
模块在登录
和会话启动时
强制实施,ulimit
命令是bash
内置命令,主要限制了 shell
及其子进程
可用的资源
在/etc/pam.d/system-auth
文件中调用了 pam_limits
模块,此模块读取 /etc/security/limits.conf
和/etc/security/limits.d/
,按配置文件设置资源限制。 查看模块帮助文档 man pam limits
/etc/pam.d/system-auth
是什么?
/etc/pam.d/system-auth
是一个 PAM(Pluggable Authentication Modules)
配置文件。在 Linux 系统中,PAM 提供了一种灵活的方式来配置用户认证、授权和会话管理
该文件是一个包含 PAM
配置行的文本文件,用于定义不同的认证、授权和会话模块及其参数。PAM 模块
负责处理用户登录、密码验证、权限检查
等操作。
查看文件中资源限制相关的模块,有时候我们做一些基线整改,可能需要修改该文件的相关配置
┌──[root@liruilongs.github.io]-[~]
└─$cat /etc/pam.d/system-auth | grep pam_limits
session required pam_limits.so
┌──[root@liruilongs.github.io]-[~]
└─$
在PAM
配置中,pam_limits.so
模块被要求进行会话限制
PAM(Pluggable Authentication Modules)
是一个用于对用户进行认证的系统级框架。pam_limits.so
模块是 PAM 框架的一部分,它用于设置会话级别的资源限制
,例如进程可打开的文件数、进程可使用的内存
等。
ulimit
命令是用于限制用户级别资源
的工具,它通常用于控制 shell 进程
及其子进程
的资源使用。修改 ulimit 值只会对当前 shell 会话有效,对其他用户或系统进程不会产生影响(不一定)
通过 ulimit 是限制系统资源的一种途径,ulimit 支持 hard
和 soft
限制
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open file descriptors
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
普通用户可以设置自己的软限制
,但不能高于硬限制
。可以使用 ulimit -a
查看资源限制列表
软限制 (soft maxlogins)
:软限制是一个警告阈值,当达到或超过该限制时,系统会发出警告信息,但不会阻止用户登录。硬限制 (hard maxlogins)
:硬限制是一个严格的限制,当达到或超过该限制时,系统将阻止用户登录。
┌──[root@liruilongs.github.io]-[~]
└─$ulimit -Hn #限制数
262144
┌──[root@liruilongs.github.io]-[~]
└─$ulimit -Sn #限制数
1024
┌──[root@liruilongs.github.io]-[~]
└─$
当指定限制数
时限制,不指定时输出当前设置
通过配置文件的方式对登录次数进行限制,配置 kiosk
组 在多个终端中只能同时登录 2 次
┌──[root@liruilongs.github.io]-[~]
└─$cat /etc/security/limits.conf | grep -v ^# | grep -v ^$
@kiosk soft maxlogins 2
@kiosk hard maxlogins 2
┌──[root@liruilongs.github.io]-[~]
└─$
涉及到内存相关的资源限制
memlock
:最大锁定内存地址空间限制(以 KB 为单位)rss
:最大常驻集大小限制(以 KB 为单位)物理内存stack
:最大堆栈大小限制(以 KB 为单位)as
:地址空间限制(以 KB 为单位)虚拟内存msgqueue
:POSIX 消息队列使用的最大内存限制(以字节为单位)配置虚拟内存限制可以通过 ulimit
进行会话基本的虚拟内存设置,下面是一个 Demo,仅对 当前 Shell 及其子进程 生效 as 虚拟地址空间限制
,以 KB 为单位
┌──[root@liruilongs.github.io]-[~]
└─$ulimit -v 8186 # 配置 当前 ulimit 大小为 8MB
┌──[root@liruilongs.github.io]-[~]
└─$ls
ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object
修改 as 的大小之后,提示 ls
命令无法加载共享库 libc.so.6,并且无法从共享对象映射段
永久配置(全局或用户级)需要修改 /etc/security/limits.conf
, 感兴趣小伙伴可以看看我之前的博文,生效条件:用户重新登录后生效。
# 格式:<domain> <type> <item> <value>
liruilong hard as 819200 # Hard Limit 800MB
liruilong soft as 409600 # Soft Limit 400MB
其他的一些限制项,也可以通过上面的方式进行,比如内存锁定,最大栈,数据段等内存相关的限制
通过内核参数
对内存的限制主要是一些缓存区的内存占用限制,以及部分 OOM 和 内存使用策略的修改,内存页分配限制策略等
这里关于怎么修改内核参数以及内核参数的加载方式,可以参考我之前的博文,这里就不再赘述了
缓存区内存限制
下面为通过关键字过滤部分的内核参数
[root@developer ~]# sysctl -a | grep mem
kernel.bind_memcg_blkcg_enable = 1
net.core.optmem_max = 81920
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
net.ipv4.fib_sync_mem = 524288
net.ipv4.igmp_max_memberships = 20
net.ipv4.tcp_mem = 78777105039157554
net.ipv4.tcp_rmem = 40961310726291456
net.ipv4.tcp_wmem = 4096163844194304
net.ipv4.udp_mem = 157557210078315114
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
vm.hugepage_pmem_allocall = 0
vm.hugetlb_optimize_vmemmap = 0
vm.lowmem_reserve_ratio = 256256320
vm.memcg_qos_enable = 0
vm.memcg_swap_qos_enable = 0
vm.memory_failure_early_kill = 0
vm.memory_failure_recovery = 1
vm.nr_hugepages_mempolicy = 0
vm.overcommit_memory = 0
[root@developer ~]#
缓存区的话,一般用的比较多的是网络方面的,比如 TCP,UDP,Stock 等。这部分参数没有固定的值,一般根据机器使用场景动态设置
在上面的输出中,前部位为 socket
级别的网络缓存区限制,socket接受和发送数据的缓存的最大值,这里的配置往往结合 BDP
进行配置,感兴趣小伙伴可以看看我之前网络调优的博文。
net.core.optmem_max = 81920
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
后部分为 TCP/UDP 级别的网络缓存区限制,TCP 缓冲区的大小应根据系统和网络的需求进行调整。较大的缓冲区可以提高网络性能,特别是在高负载或高延迟的网络环境中。但是,过大的缓冲区可能会导致内存占用增加或延迟问题。
net.ipv4.tcp_rmem 和 net.ipv4.tcp_wmem
用于配置 TCP 套接字的接收缓冲区和发送缓冲区的大小。
net.ipv4.tcp_rmem = 40961310726291456
net.ipv4.tcp_wmem = 4096163844194304
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
下面的两个为 系统级别内存限制,单位是Page 内存页,4K,分别代表了TCP和UDP的系统层面内存限制的值,即网络连接的内存分配,包括三列:min,pressure,max
.
net.ipv4.tcp_mem = 78777 105039 157554
net.ipv4.udp_mem = 157557 210078 315114
这里格式有点问题,我们换一个方式查看
[root@developer ~]# cat /proc/sys/net/ipv4/tcp_mem
78777 105039 157554
[root@developer ~]#
内存超售限制
下面这组内核参数用于限制内存的超售问题
,内存的分配和使用是两个阶段,在分配的时候是虚拟内存,而且实际使用才会分配物理内存,对于虚拟内存的分配,可以是一个很大的值,但是物理内存的分配,是有限制的,如果分配的虚拟内存大于物理内存,那么就会导致内存超售,那么这个时候,就需要限制内存的超售问题,避免内存超售导致系统崩溃。
[root@developer ~]# sysctl -a | grep overcomm
vm.nr_overcommit_hugepages = 0
vm.overcommit_kbytes = 0
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
vm.overcommit_memory = 0
:控制内核的内存超分配策略,决定是否允许进程申请超过物理内存 + Swap 的空间。
vm.overcommit_ratio = 50
: 当 overcommit_memory=2
时,定义物理内存的可超配比例(默认值 50%)。 计算公式: CommitLimit = (物理内存 × overcommit_ratio / 100) + Swap
vm.overcommit_kbytes = 0
:与 overcommit_ratio 互斥,直接指定超配的字节级上限(优先级高于 ratio)。
vm.nr_overcommit_hugepages = 0
:控制标准大页(HugePages)的超配数量
,允许临时分配超出 vm.nr_hugepages 预设值的大页。
上面讲到了大页,这里我们顺便看看内存页相关的内存限制
内存页限制
hugepages 用于限制分配的大页数量,这里的大页指的是标准大页
,即 2MB 的大页,
sysctl -w vm.nr_hugepages=1024 # 分配1024个大页(默认2MB/页)
如果需要自定义大页的大小,比如 1GB 的大页,需要通过 hugepagesz
来进行限制,一般启动时通过GRUB配置
hugepagesz=1G hugepages=4 default_hugepagesz=1G # 分配4个1GB大页
关于内存页,内核相关的参数中还有透明大页
的配置,比如透明大页的开启,khugepaged
进程的扫描频率等等,感兴趣的小伙伴可以看看我之前关于大页的博文
下面为脏页/换页/内存回收
与保留相关参数的内存限制
脏页指内存中已被修改但未写入磁盘的数据页。内核通过以下参数控制其回写行为:
[root@developer ~]# sysctl -a | grep dirty
vm.dirty_background_bytes = 0 # 触发后台异步刷盘的脏页绝对字节阈值(优先级高于ratio)。0表示未启用,使用dirty_background_ratio控制
vm.dirty_background_ratio = 10 # 触发后台异步刷盘的脏页内存占比阈值(默认10%)。脏页超限时内核启动后台线程异步刷盘,不阻塞应用
vm.dirty_bytes = 0 # 触发同步阻塞刷盘的脏页绝对字节阈值(优先级高于ratio)。0表示未启用,使用dirty_ratio控制
vm.dirty_expire_centisecs = 3000 # 脏页在内存中的最长存活时间(默认3000=30秒)。超时后强制刷盘,减少数据丢失风险
vm.dirty_ratio = 30 # 触发同步阻塞刷盘的脏页内存占比阈值(默认30%)。超限时应用写入被阻塞,直至脏页落盘
vm.dirty_writeback_centisecs = 500 # 内核刷盘线程的唤醒间隔(默认500=5秒)。值越小刷盘越频繁,过高可能导致I/O堆积
vm.dirtytime_expire_seconds = 43200 # 仅修改时间(atime/mtime)的脏元数据超时时间(默认43200=12小时)。通常无需调整
下面为交换分区使用限制
vm.memcg_swap_qos_enable = 0 # 内存控制组(memcg)的Swap服务质量(QoS)功能开关
vm.swap_extension = 0 # 扩展Swap空间的机制(通常用于特殊场景,如内存压缩)
vm.swappiness = 30 # 控制内核使用Swap的倾向性(范围0-100)
还有两个特殊的参数需要单独说明一下:
vm.min_free_kbytes
:系统保留的最小空闲内存(单位 KB),用于应对突发需求vm.watermark_scale_factor
:调整内存回收敏感度(默认 10,范围 1-1000)。[root@developer ~]# sysctl -a | grep min_free_kbytes
vm.min_free_kbytes = 45056
[root@developer ~]# sysctl -a | grep watermark_scale_factor
vm.watermark_scale_factor = 10
[root@developer ~]#
OOM 相关内存限制
下面为OOM
相关,的内存限制,关于 OOM 是什么,什么原理不是本文重点,小伙伴可以看看我之前的博文
[root@developer ~]# sysctl -a | grep oom
vm.enable_oom_killer = 1 # 启用OOM Killer机制(默认值)。当系统内存耗尽时,内核自动终止进程释放内存
vm.oom_dump_tasks = 1 # OOM触发时记录所有进程的内存状态到日志(/var/log/messages),便于事后分析
vm.oom_kill_allocating_task = 0 # 禁用“直接杀死触发OOM的进程”。内核会扫描所有进程,选择badness分数最高的进程终止
vm.panic_on_oom = 0 # OOM时禁止内核崩溃(panic)。0表示调用OOM Killer而非重启系统(生产环境推荐
[root@developer ~]#
NUMA内存限制
[root@developer ~]# sysctl -a | grep zone_reclaim_mode
vm.zone_reclaim_mode = 0 # 关闭本地NUMA节点内存强制回收。允许从其他节点分配内存,避免因本地回收降低性能
[root@developer ~]# sysctl -a | grep min_unmapped_ratio
vm.min_unmapped_ratio = 1 # 每个NUMA节点保留1%的未映射内存(用于临时内存分配)
[root@developer ~]#
对于内存资源的限制内核参数还有很多,这里只是列举了部分。关于Linux 内存资源限制就和小伙伴分享到这里 ^_^
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 :)
《性能之巅 系统、企业与云可观测性(第2版)》
© 2018-至今 liruilonger@gmail.com, 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)