资源限制
在Linux 系统中,有一个非常古老的资源限制功能——limits
在系统中,有一个模块叫做limits.so,这个模块有一个配置文件:
vim /etc/security/limits.conf
这个模块也是PAM 认证模块里面的一个机制。
如果你早期有安装过类似于oracle 这种大型数据库,通常会接触到limits 这个功能,它能帮助你限制一个用户最多打开多少个文件、最多使用多大的磁盘空间、最多打开多少进程、最多使用多少内存...等等,不过这个功能已经属于非常古老的一种资源限制方式了,大概在红帽3、红帽4 的时代就已经实现了,不过在今天进行一些简单的设置依然还是可行有效的。
这里面有介绍到该文件做资源限制的写法。
下面我们来新建一个用户:
useradd user1
然后在配置文件中写入这么一行:
nofile 表示限制的资源类型是打开的文件数,最多只能打开4 个文件。
结果连登录都报错,因为用户登录的时候已经不止要打开4 个文件了。
限制user1 最多打开40 个文件,最多使用10M 的虚拟内存。
同样无法登录,分配不到内存去读取一些必要的文件导致的。
改为限制分配100M 虚拟内存,登录成功了
所以limits.conf 修改完成以后,无需重启什么服务,只需要让用户重新登录一遍,限制就生效了。
那么如果用户登录以后,想要查看系统对它有哪些限制,使用:
ulimit -a
ulimit -n
ulimit -v
那么,软限制与硬限制有什么区别呢?
现在最多能打开30 个文件。
ulimit -n 35
现在设置了最多可以打开35 个文件。
如果你要打开45 个文件,不可以。
所以,超出软限制,用户可以进行微调,但还是不能超过硬限制。
从RHEL 6.2 开始,引入了一个新的功能——cgroup
cgroup 已经成为了现在的主流。
今天很多的虚拟机,容器背后用来资源限制的功能用的就是cgroup
docker 容器其中两个核心技术,一个是namespace(命名空间),用来做资源隔离,另一个就是cgroup,用来做资源限制。
cgroup 从RHEL 6 开始,在RHEL 7 上又经历了迭代,下面来演示当年在RHEL 6 上是怎么做的:
这个包在RHEL 7 上是默认安装的,RHEL 6 可能要手动安装。
那么,像/proc、/sys 这样的目录,系统中也有一个/cgroup 的文件系统
cd /cgroup/blkio
这里面有很多的调优选项。
vim /etc/cgconfig.conf
如果你要做资源限制,那么这一段有相应的配置文件。
假如说在RHEL 6 系统中现在有一个需求:
要求执行读写操作时,限速读写1MB/s,如何做?
你可以:
man cgconfig.conf
模仿示例来写:
vim /etc/cgconfig.conf
这是一个全局配置,第一个名称bigdata 可以自定义, 第二个名称是你要针对什么资源做限制,必须与调优参数对应。
重启一下服务:
/etc/init.d/cgconfig restart
cd /cgroup/blkio/bigdata/
cat blkio.throttle.read_bps_device
接下来将这个全局配置应用到具体某一个用户执行某一个动作上:
vim /etc/cgrules.conf
这表示:任何用户执行cp 这个命令的时候,会受到全局配置bigdata 里面的blkio 规则的限制。
/etc/init.d/cgconfig restart
现在来测试一下是不是这样的:
/etc 目录36M大小,新开一个窗口,观察:
rm -rf /tmp/*
watch -n 1 -x du -sh /tmp
回到原来的窗口,拷贝文件:
cp /etc/ /tmp/
会发现这个文件夹的大小几乎是一兆一兆在增长的,说明限制生效了。
bigmem 是一个专门用来做内存测试的工具,不是系统自带的,先来看一下当前这台机器的内存使用情况:
现在我要申请512M 内存:
申请到了。
现在来做资源限制,限制bigmem 可以申请到的内存最多为256M
cd /cgroup/memory
内存限制应该是操作这个参数。
vim /etc/cgconfig.conf
一个组里面可以有多个选项,也可以单独再写到一个组里面。
vim /etc/cgrules.conf
/etc/init.d/cgconfig restart
/etc/init.d/cgred restart
下面测试一下:
新开一个窗口观察
watch -n 1 -x free -m
内存限制生效了。
在RHEL 5、RHEL 6 时代,系统服务是怎么管理的呢?
比如说重启vsftpd 服务:
这条命令本质上是执行了下面这条命令:
/etc/init.d/vsftpd 这个文件其实是一个脚本。
vim /etc/init.d/vsftpd
在当时,你想要管理一个服务,就需要写一个这样的脚本放在/etc/init.d 目录,用来控制服务的启动、停止、重启等等...
从RHEL 7 开始,服务由systemd 管理,重启一个服务用这样的命令来执行:
当然它也支持使用以前的语法:
实际上还是调用的systemd 服务。
cd /usr/lib/systemd/system
这里面有很多的服务,其中就有一个是叫vsftpd.service,所以当你启服务的时候,会读到这个脚本。
vim vsftpd.service
Description 是对这个服务的描述,After 表示这个服务在network.target 服务启动后运行,type 是这个服务的类型,ExecStart 表示这个服务启动时执行的脚本,其实你启服务的时候,本质上就是在执行下面这条命令:
WanteBy=multi-user.target 表示在多用户模式(级别3)运行。
所以使用systemd 来管理服务相比于RHEL 6及以前的版本,大大简化了服务脚本编写的难度。
下面我们自己来写一个服务:
vim realtime
这个脚本会持续运行。
cd /usr/lib/systemd/system
cp -p vsftpd.service realtime.service
vim realtime.service
systemctl daemon-reload
systemctl enable --now realtime.service
systemctl status realtime.service
ps aux | grep realtime
如果我想限制一些吃内存的应用,怎么通过systemd 的方式来管理呢?
man -k systemd |grep resource
man 5 systemd.resource-control
可以对CPU、内存、IO 资源做限制。
就CPU 而言,可以对CPUAccounting,权重、配额等等做限制。
我们可以直接写/usr/lib/systemd/system/realtime.service 文件来控制,但是不建议直接改这个文件,推荐下面的做法:
cd /etc/systemd/system/
mkdir realtime.service.d
cd realtime.service.d/
在这个文件夹下新建一个配置文件,名称无所谓,但必须以.conf
结尾:
vim 01-time.conf
但是这个文件里面该写些什么内容呢?可以参照其他服务来写:
systemctl daemon-reload
systemctl restart realtime.service
systemctl status realtime.service
除此以外,怎么验证是否生效呢?
df -h
在RHEL 7 以前,这个目录是在根下的/cgroup,现在是在/sys/fs/cgroup
cd /sys/fs/cgroup
cd memory
cd /system.slice
cd realtime.service
上一级目录里是全局配置,里面一级是单独配置的。
这两个进程会受到单独配置的影响,其他进程则是受全局配置的影响。
cd /sys/cgroup/memory/system.slice/realtime.service
cat memory.limit_in_bytes
这里看到系统把内存的一半容量分配给了/sys/fs/cgroup
cd /sys/fs/cgroup/memory/
cat tasks
这里面显示的都是PID,如果没有单独限制,那么读取的就是全局的配置。
如果没有单独做限制,那么默认的这个全局配置,是7EB,几乎等同于无上限。
持续更新中...