Cgroup和Namespace在测试中的使用(上)

Cgroup和Namespace在测试中的使用(上)

很多时候需要测试程序在资源受限情况下的表现,普通的做法可能是不断对系统加压使能够分配给目标程序的资源变少,换另一个思路思考,可以尝试限制分配给目标程序的资源总数,使得机器状态健康的情况下让程序资源使用达到饱和。

作为一个正在做着容器项目的人,知道容器技术是依靠Cgroup和Namespace来实现的。在容器中,cpu和内存资源是使用Cgroup来控制,PID、IPC、网络等资源是通过Namespace来划分。在程序没有部署在容器的情况下,我们仍可以利用Cgoup和Namespace来构造场景完成一些异常测试,如利用Cgroup的资源控制功能做资源满载的测试;利用Namespace的资源隔离特性做一些网络异常测试而不影响其他程序的运行。

Cgroup介绍

Cgroup是进行分组化管理的Linux内核功能,具体的资源管理是通过子系统来完成的。可以理解为子系统就是资源控制器,每种子系统就是一个资源的分配器,比如cpu子系统是控制cpu时间分配的,使用方式如下

安装(ubuntu)

#apt-get install cgroup-bin

基本命令

cgclassify -- cgclassify命令是用来将运行的任务移动到一个或者多个cgroup。

cgclear -- cgclear 命令是用来删除层级中的所有cgroup。

cgconfig.conf -- 在cgconfig.conf文件中定义cgroup。

cgconfigparser -- cgconfigparser命令解析cgconfig.conf文件和并挂载层级。

cgcreate -- cgcreate在层级中创建新cgroup。

cgdelete -- cgdelete命令删除指定的cgroup。

cgexec -- cgexec命令在指定的cgroup中运行任务。

cgget -- cgget命令显示cgroup参数。

cgred.conf -- cgred.conf是cgred服务的配置文件。

cgrules.conf -- cgrules.conf 包含用来决定何时任务术语某些 cgroup的规则。

cgrulesengd -- cgrulesengd 在 cgroup 中发布任务。

cgset -- cgset 命令为 cgroup 设定参数。

lscgroup -- lscgroup 命令列出层级中的 cgroup。

lssubsys -- lssubsys 命令列出包含指定子系统的层级

子系统说明

可以使用lssubsys -a来列出系统支持多少种子系统,和:比如cpu是控制cpu时间片的,memory是控制内存使用的

#lssubsys -a

cpuset

cpu,cpuacct

memory

devices

freezer

net_cls,net_prio

blkio

perf_event

hugetlb

主要的几种子系统说明如下:

blkio 这个子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。

cpu 这个子系统使用调度程序为cgroup任务提供cpu的访问。

cpuacct 产生cgroup任务的cpu资源报告。

cpuset 如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。

devices 允许或拒绝cgroup任务对设备的访问。

freezer 暂停和恢复cgroup任务。

memory 设置每个cgroup的内存限制以及产生内存资源报告。

net_cls 标记每个网络包以供cgroup方便使用。

ns 名称空间子系统

perf_event: 增加了对每group的监测跟踪的能力,即可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程

要为Cgroup分配限制的资源,首先要挂载子系统,然后才有控制组,比如想要对目标程序进行内存限制,那就需要挂载memory子系统

使用lssubsys -am来显示已经挂载的子系统

#lssubsys -am

cpuset /sys/fs/cgroup/cpuset

cpu,cpuacct /sys/fs/cgroup/cpu,cpuacct

memory /sys/fs/cgroup/memory

devices /sys/fs/cgroup/devices

freezer /sys/fs/cgroup/freezer

net_cls,net_prio /sys/fs/cgroup/net_cls,net_prio

blkio /sys/fs/cgroup/blkio

perf_event /sys/fs/cgroup/perf_event

hugetlb /sys/fs/cgroup/hugetlb

可以手动挂载或者卸载子系统,如执行umount /sys/fs/cgroup/memory,memory子系统就被卸载了,这时候手动执行# mount -t cgroup -o memory memory /sys/fs/cgroup/memory就又挂载上了。
要确保需要的子系统都挂上了,不然创建控制组的时候会报错 is not mounted

#cgcreate -g memory,cpu:/hzmali_test

cgcreate: can‘t create cgroup /hzmali_test: Cgroup one of the needed subsystems is not mounted

如何创建control group(即需要资源管理的组)呢, 这里用cgcreate命令,当然也有其他方法, 如cgconfig.conf等

#cgcreate -g memory,cpu:/hzmali_test

这里有个重要特性:一个组可以同时做多个资源的限制,如这里我同时限制了memory和cpu,然后memory和cpu子系统目录下会自动生成这个组的目录和些文件,如memory

#/sys/fs/cgroup/memory/hzmali_test$ ls -lrt

-rw-r--r-- 1 root root 0 Jul 26 20:56 tasks

-rw-r--r-- 1 root root 0 Jul 26 20:56 notify_on_release

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.use_hierarchy

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.usage_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.swappiness

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.stat

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.soft_limit_in_bytes

---------- 1 root root 0 Jul 26 20:56 memory.pressure_level

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.oom_control

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.numa_stat

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.move_charge_at_immigrate

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.max_usage_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.limit_in_bytes

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.usage_in_bytes

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.tcp.usage_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.tcp.max_usage_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.tcp.limit_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.tcp.failcnt

-r--r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.slabinfo

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.max_usage_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.limit_in_bytes

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.kmem.failcnt

--w------- 1 root root 0 Jul 26 20:56 memory.force_empty

-rw-r--r-- 1 root root 0 Jul 26 20:56 memory.failcnt

-rw-r--r-- 1 root root 0 Jul 26 20:56 cgroup.procs

--w--w--w- 1 root root 0 Jul 26 20:56 cgroup.event_control

-rw-r--r-- 1 root root 0 Jul 26 20:56 cgroup.clone_children

文件很多,选几个重要的讲下:

  • tasks 可以将想要限制资源的进程都加到这个文件中
  • memory.max_usage_in_bytes内存的最大使用量,用来限制资源
    -memory.soft_limit_in_bytes 和 memory.limit_in_bytes 的差异是,这个限制并不会阻止进程使用超过限额的内存,只是在系统内存不足时,会优先回收超过限额的进程占用的内存,使之向限定值靠拢。
  • memory.oom_control
    包含一个标志(0或1)来开启或者关闭cgroup的OOM killer。如果开启(1),任务如果尝试申请内存超过允许,就会被系统OOM killer终止。OOM killer在每个使用cgroup内存子系统中都是默认开启的。如果需要关闭,则可以向memory.oom_control文件写入1:

# echo 1 > /sys/fs/cgroup/memory.oom_control
如果OOM killer关闭,那么进程尝试申请的内存超过允许,那么它就会被暂停,直到额外的内存被释放

  • memory.mem.usage_in_bytes 当前进程内存用量,因为现在还没有进程加到组里,就是0了
  • memory.mem.failcnt显示内存达到限制值的次数

Cgroup文档

Cgroup的使用细节,子系统和参数设置都可以可以在https://www.kernel.org/doc/Documentation/cgroups/中找到,继承等特性由于篇幅所限,可以看下文档

Cgroup实战

内存限制测试

用控制组限制目标程序内存使用为1000000 byte,当然,需要root执行
echo "1000000" >memory.limit_in_bytes

一般更推荐用cgset来设置数值

cgset -r memory.limit_in_bytes=1000000 hzmali_test

然后构造一个吃内存的程序,每运行一次内存使用就大幅增加

#vim memtest.sh

x="hahaha"

while [ True ];do

x=$x$x$x$x$x$x$x$x$x$x

sleep 1

done;

然后运行程序,并将进程pid写入mem下面控制组的tasks中

#./memtest.sh &

[1] 17638

# echo 17638 > /sys/fs/cgroup/memory/hzmali_test/tasks

使用cgclassify 可以将运行中的进程加到task中,如果控制组有多个资源的控制,使用命令会比echo方便很多

cgclassify -g mem:hzmali_test 17638

然后这货就在不断占内存,由于没有设置disable oom killing,所以最后会oom被kill掉

# cat /sys/fs/cgroup/memory/hzmali_test/memory.usage_in_bytes

966656

# cat /sys/fs/cgroup/memory/hzmali_test/memory.usage_in_bytes

978944

# cat /sys/fs/cgroup/memory/hzmali_test/memory.usage_in_bytes

995328

#

[1]+ Killed ./memtest.sh

CPU限制测试

我的机器上有2个核

%Cpu0 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

写个死循环脚本cpu_test.sh跑一下

x=a

while [ True ];do

x=$x

done;

如果我不想把机器跑死,这里想要限制组里的进程的CPU使用,有2种做法
1.在cpu子系统中控制cpu调度的配额
先看下当前cpu分配情况

cat /sys/fs/cgroup/cpu/hzmali_test/cpu.cfs_quota_us

-1

cat /sys/fs/cgroup/cpu/hzmali_test/cpu.cfs_period_us

100000

-1表示无限制,这里改为50000,即相对于cpu.cfs_period_us 来说为50000/100000约占1个核50%的cpu时间

#./cpu_test.sh &

[1] 17709

# echo 17709 >/sys/fs/cgroup/cpu/hzmali_test/tasks

或者直接使用命令cgexec执行

cgexec -g cpu:hzmali_test ./cpu_test.sh

top了下基本上就是在50%的cpu占用

%Cpu0 : 50.5 us, 0.0 sy, 0.0 ni, 49.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

%Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 17709 root 20 0 25368 2020 1764 R 50.2 0.1 1:14.74 bash

2.在cpuset控制物理cpu的分配
当前使用了上面的方法后,我们发现进程的CPU使用都在Cpu0上,这次希望只用Cpu1来跑这个小程序
所以把控制组也加到cpuset

# cgcreate -g cpuset:/hzmali_test

看一下现在使用的cpu的设置

# cat /sys/fs/cgroup/cpuset/hzmali_test/cpuset.cpus

0-1

改为只用Cpu1,输入以下命令

# echo 1 > /sys/fs/cgroup/cpuset/hzmali_test/cpuset.cpus

# echo 17709 > /sys/fs/cgroup/cpuset/hzmali_test/tasks

或用命令

# cgset -r cpuset.cpus=‘1‘ hzmali_test

# cgclassify -g cpu,cpuset:hzmali_test 17709

top一下,内存的使用从CPU0到CPU1了

%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st

%Cpu1 : 50.3 us, 0.0 sy, 0.0 ni, 49.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

17709 root 20 0 25368 2108 2076 R 50.1 0.1 8:56.78 bash

IO限制测试

用dd对硬盘进行写操作

# dd if=/dev/sda of=/dev/null &

打开iotop看下IO速度

Total DISK READ : 100.37 M/s | Total DISK WRITE : 0.00 B/s

Actual DISK READ: 100.37 M/s | Actual DISK WRITE: 0.00 B/s

TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND

18081 be/4 root 100.37 M/s 0.00 B/s 0.00 % 1.34 % dd if=/dev/sda of=/dev/null

为了控制IO速度,在blkio上创建控制组

# cgcreate -g blkio:/hzmali_test

查看下硬盘号

# ls -l /dev/sda

brw-rw---- 1 root disk 8, 0 Jul 25 22:46 /dev/sda

设置硬盘号和对应的读取速度限制,然后执行同样的命令

# cgset -r blkio.throttle.read_bps_device="8:0 1000000" hzmali_test

# cgexec -g blkio:hzmali_test "dd if=/dev/sda of=/dev/null"

用iotop查看下,速度果然就降到1M以下

Total DISK READ : 996.55 K/s | Total DISK WRITE : 0.00 B/s

Actual DISK READ: 996.55 K/s | Actual DISK WRITE: 0.00 B/s

TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND

18188 be/4 root 996.55 K/s 0.00 B/s 0.00 % 99.99 % dd if=/dev/sda of=/dev/null

时间: 2024-10-26 13:52:23

Cgroup和Namespace在测试中的使用(上)的相关文章

Cgroup和Namespace在测试中的使用(下)

Cgroup和Namespace在测试中的使用(下) Namespace介绍 使用Namespace又叫做命名空间,可以让每个进程组具有独立的PID.IPC和网络空间等,也就是说这些系统资源不再是全局性的,而是属于特定的Namespace,每个Namespace里面的资源对其他Namespace都是透明的,从而达到资源的隔离效果. 目前namespace的种类如下 分类 系统调用参数 Mount namespaces CLONE_NEWNS UTS namespaces CLONE_NEWUTS

详述MySQL服务在渗透测试中的利用

本文作者:i春秋签约作家--Binghe 致力于书写ichunqiu社区历史上最长篇最细致最真实的技术复现文章. 文章目录: MySQL之UDF提权 MySQL之MOF提权 MySQL之常规写启动项提权 导出木马到启动项提权 反弹端口提权 MySQL提权综合姿势 part1 mysql之UDF提权 首先什么是UDF? UDF为`User Defined Function`-用户自定义函数,也就是支持用户自定义函数的功能.看这个名字应该就理解了一半了. MySQL是最流行的开放源码SQL数据库管理

Cgroup blkio简介和测试(使用fio测试)

Cgroup blkio简介和测试(使用fio测试) 因需要对docker镜像内的进程对磁盘读写的速度进行限制,研究了下Cgroup blkio,并使用fio对其iops/bps限速进行测试. Cgroup blkio简介 Linux Cgroup(Control Groups)是Linux内核提供的用于限制.记录.隔离进程组可以使用的资源(cpu.memory.IO等)的一种机制. 在/boot下面的对应config文件里查看Cgroup内核选项: CONFIG_BLK_CGROUP=y CO

游戏测试中的sql语句

基本的内容在这里就不写了. 游戏测试中经常使用到1个复合条件的 游戏内一般要查下用户剩余多少钱.例如有个字段为energy代表体力 表名为db_role 关键字段 id,name(唯一) 要查询条件为 energy在1500一档,然后二档是500~1000之间的 语句为 select id,name,energy from db_name where energy=1500 OR(energy >=500 and energy<1000) 喜欢as的话 可以再要看的列之前加as  select

【转】移动App测试中的最佳做法

一说起软件测试,测试员想到肯定是去检查文件,功能,API,性能并确定软件是否安全,以及关于软件特定部分的其他事项.但是对于移动测试,测试员不得不基于用户移动使用模式考虑移动相关的功能. 本文是基于我的工作经验而写的.作为一名敏捷软件开发团队的软件质量保证经理,我一心投入iPhone,Android,WindowsPhone7的移动apps和移动webapps.在XING移动团队的日常工作以及与其他移动测试专家交流的过程中,我深刻了解了移动测试工作的困难.渐渐地,我明确了什么是帮助改进同事们和我的

LoadRunner之Paramater在负载测试中的数据生成规则

LoadRunner之Paramater在负载测试中的数据生成规则 前段时间在做性能测试的时候,基于业务的需求,使用到了Unique Number的参数类型. 脚本的业务是注册以alien开头,后面接数字的用户帐号,填写相关帐号信息.提交企业信息进行审核. 其中用户帐号是alien开头拼接一个唯一数字的参数,如图: 下面对Unique Number进行相关解释,先引用官方资料:(相信大家也理解这段话的意思) Unique Number: Assigns a range of numbers to

压力测试中需要掌握的几个基本概念

1:吞吐率(Requests per second) 服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数下单位时间内处理的请求数.某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率. 记住:吞吐率是基于并发用户数的.这句话代表了两个含义,1:吞吐率和并发用户数相关:2:不同的并发用户数下,吞吐率一般是不同的. 计算公式:总请求数 / 处理完成这些请求数所花费的时间,即 Request per second = Complete requests / Time ta

移动App测试中的最佳做法

每项开发的新功能都需要进行测试.移动app测试中功能测试是一个重要方面,移动测试员应该要进行手动测试和自动化测试.刚开始测试时,测试员必须把移动app 当做"黑盒"一样进行手动测试,看看提供的功能是否正确并如设计的一样正常运作.除了经典软件测试,像点击按钮看看会发生什么,测试员还必须执行更多功能的移动设备专门的测试. 如今,现代移动设备都有触摸屏,要求多点触控动作来与它们互动.设备可以是纵向或横向显示屏.它们提供动作,倾斜和螺旋传感器.它们有不同的接口可以连接其他设备或服务,比如GPS

[转]移动App测试中的最佳做法

Daniel Knott 用过各种不同编程语言和软件质量保证工具.他在软件开发和测试方面干了七年,自2010年起,他一直在德国汉堡的XING AG公司就职,几个项目里,比如XING调查和XING建议,他负责测试管理,测试自动化和测试执行.Daniel现在是XING移动和XING API团队的质量保证团队负责人.在XING移动团队中,他还负责XING安卓和iPhone Apps的测试管理和测试自动化.Daniel在包括像Robotium, KIF (Keep It Functional), Sel