zoukankan      html  css  js  c++  java
  • linux(centos8):使用cgroups做资源限制

    一,什么是cgroups? 

    1,cgroups是资源的控制组,它提供了一套机制用于控制一组特定进程对资源的使用。
        cgroups绑定一个进程集合到一个或多个限制资源使用的子系统上。
    2, cgroups是容器的实现基础之一:

       其中:Namespace主要用于隔离资源

             Cgroups用来提供对一组进程以及将来子进程的资源限制

     

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

     

    二,cgroups的用途:

     主要有4个:
     Resource limitation: 限制资源使用,例:内存使用上限/cpu的使用限制
     Prioritization: 优先级控制,例:CPU利用/磁盘IO吞吐
     Accounting: 一些审计或一些统计
     Control: 挂起进程/恢复执行进程
     

    三,cgroups相关的操作命令:

    1,查看当前kernel中cgroup是否开启:
    [root@blog ~]$ more /boot/config-`uname -r` | grep -i cgroup
    CONFIG_CGROUPS=y
    CONFIG_BLK_CGROUP=y
    # CONFIG_DEBUG_BLK_CGROUP is not set
    CONFIG_CGROUP_WRITEBACK=y
    CONFIG_CGROUP_SCHED=y
    CONFIG_CGROUP_PIDS=y
    ... 
    说明:CONFIG_CGROUPS=y
    表示已开启cgroup
     
    2,cgroup目前存在v1/v2 两个版本,
       v2 版本与v1相比,在目录组织上更清晰,管理更方便,
    如何检查当前内核版本是否支持cgroup v2?
    方法是:查看文件系统是否支持cgroup2
    [root@node1 ~]# grep cgroup /proc/filesystems
    nodev   cgroup
    nodev   cgroup2
    如果看到cgroup2,表示支持cgroup v2
      
    3,列出所有挂载的cgroup挂载点
    [root@blog ~]$ mount | grep cgroup
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
    cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
    cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
    cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
    cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
    cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
    cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
    cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
    cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
    cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
    cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
    cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
    cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
    注意:/sys/fs/cgroup的挂载方式是ro,表示readonly
    因为/sys/fs/cgroup 目录由 systemd 在系统启动的过程中挂载,
    它把目录挂载为只读的类型,这个目录下不能再手动创建目录
     
    2,列出cgroup支持的子系统?
    [root@blog ~]# ll /sys/fs/cgroup/
    total 0
    dr-xr-xr-x 4 root root  0 Jan 10 18:03 blkio
    lrwxrwxrwx 1 root root 11 Jan 10 18:03 cpu -> cpu,cpuacct
    lrwxrwxrwx 1 root root 11 Jan 10 18:03 cpuacct -> cpu,cpuacct
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 cpu,cpuacct
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 cpuset
    dr-xr-xr-x 4 root root  0 Jan 10 18:03 devices
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 freezer
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 hugetlb
    dr-xr-xr-x 4 root root  0 Jan 10 18:03 memory
    lrwxrwxrwx 1 root root 16 Jan 10 18:03 net_cls -> net_cls,net_prio
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 net_cls,net_prio
    lrwxrwxrwx 1 root root 16 Jan 10 18:03 net_prio -> net_cls,net_prio
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 perf_event
    dr-xr-xr-x 4 root root  0 Jan 10 18:03 pids
    dr-xr-xr-x 2 root root  0 Jan 10 18:03 rdma
    dr-xr-xr-x 5 root root  0 Jan 10 18:03 systemd
    也可以通过/proc/cgroups来查看
    [root@blog ~]# more /proc/cgroups
    #subsys_name    hierarchy       num_cgroups     enabled
    cpuset  8       1       1
    cpu     2       1       1
    cpuacct 2       1       1
    blkio   4       29      1
    memory  7       1703    1
    devices 3       60      1
    freezer 9       1       1
    net_cls 5       1       1
    perf_event      10      1       1
    net_prio        5       1       1
    hugetlb 11      1       1
    pids    12      67      1
    rdma    6       1       1 
    各个子系统的说明:
     
    cpuset:把任务绑定到特定的cpu
    cpu:    限定cpu的时间份额
    cpuacct: 统计一组task占用cpu资源的报告
    blkio:限制控制对块设备的读写
    memory:  限制内存使用
    devices: 限制设备文件的创建限制对设备文件的读写
    freezer: 暂停/恢复cgroup中的task
    net_cls: 用classid标记该cgroup内的task产生的报文
    perf_event: 允许perf监控cgroup的task数据
    net_prio: 设置网络流量的优先级
    hugetlb:  限制huge page 内存页数量
    pids:   限制cgroup中可以创建的进程数
    rdma:  限制RDMA资源(Remote Direct Memory Access,远程直接数据存取)
     

    四,查看一个进程上的cgroup限制:

    以nginx的进程为例

    [root@blog ~]# ps auxfww | grep nginx:
    root   491  0.0  0.0  71028  3368 ?  Ss   May18   0:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx
    nginx  492  0.0  0.0 102496  7036 ?  S    May18   0:00  \_ nginx: worker process
    nginx  493  0.0  0.0 102764  7496 ?  S    May18   0:00  \_ nginx: worker process
    nginx  494  0.0  0.0 102496  5856 ?  S    May18   0:00  \_ 
    ...
    我们取上面的492这个进程:
    查看492这个进程的cgroup限制
    [root@blog ~]# more /proc/492/cgroup
    12:pids:/system.slice/openresty.service
    11:hugetlb:/
    10:perf_event:/
    9:freezer:/
    8:cpuset:/
    7:memory:/system.slice/openresty.service
    6:rdma:/
    5:net_cls,net_prio:/
    4:blkio:/system.slice/openresty.service
    3:devices:/system.slice/openresty.service
    2:cpu,cpuacct:/
    1:name=systemd:/system.slice/openresty.service
    内容说明:
    第一列:cgroupid,和/proc/cgroups中的id是一致的,
    第二列:cgroup的子系统
    第三列:进程在 cgroup 树中的路径  
    例:
    [root@blog ~]# ls /sys/fs/cgroup/systemd/system.slice/openresty.service/
    cgroup.clone_children  cgroup.procs  notify_on_release  tasks

    五,使用libcgroup-tools做进程的限制

    libcgroup-tools包含了多个cg相关的命令,方便进行cgroups的测试
    说明:从centos7开始,已经默认不再使用libcgroup套件,
    所以大家把它作为演示使用即可
    1,安装
    [root@blog ~]# dnf install libcgroup-tools
     
    2,安装/测试运行stress
    [root@node1 stress]# pwd
    /usr/local/source/stress
    [root@node1 stress]# wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/s/stress-1.0.4-16.el7.x86_64.rpm
    [root@node1 stress]# rpm -ivh stress-1.0.4-16.el7.x86_64.rpm
    运行stress
    启动1个消耗内存的进程,每个进程占用50M内存
    #--vm-keep  一直占用内存,(默认是不断释放并重新分配内存)
    [root@node1 memory]# stress -m 1 --vm-bytes 50M --vm-keep
    stress: info: [14327] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd 
    用pidstat查看效果
    [root@node1 ~]# pidstat -r | grep stress
    14时57分13秒     0     46088      0.01      0.00    7948     972   0.03  stress
    14时57分13秒     0     46089      0.07      0.00   59152   51496   1.34  stress  
    3,在cgroup中添加一个内存限制:再次用stress测试:
    [root@node1 memory]# pwd
    /sys/fs/cgroup/memory
    [root@node1 memory]# mkdir lhd_stress_memory
    注意:
    cgroups 文件系统会在创建文件目录的时候自动创建相应的配置文件
    [root@node1 memory]# ls lhd_stress_memory/
    cgroup.clone_children  memory.kmem.limit_in_bytes          memory.kmem.tcp.usage_in_bytes  memory.memsw.max_usage_in_bytes  memory.soft_limit_in_bytes  tasks
    cgroup.event_control   memory.kmem.max_usage_in_bytes      memory.kmem.usage_in_bytes      memory.memsw.usage_in_bytes      memory.stat
    cgroup.procs           memory.kmem.slabinfo                memory.limit_in_bytes           memory.move_charge_at_immigrate  memory.swappiness
    memory.failcnt         memory.kmem.tcp.failcnt             memory.max_usage_in_bytes       memory.numa_stat                 memory.usage_in_bytes
    memory.force_empty     memory.kmem.tcp.limit_in_bytes      memory.memsw.failcnt            memory.oom_control               memory.use_hierarchy
    memory.kmem.failcnt    memory.kmem.tcp.max_usage_in_bytes  memory.memsw.limit_in_bytes     memory.pressure_level            notify_on_release
    可以看到新建目录下面已建好了配置文件
    设置这个cgroup内存限制的最大使用内存:
    [root@node1 memory]# expr 1024 * 1024 * 10
    10485760

    设置内存的限制

    [root@node1 memory]# echo 10485760 > lhd_stress_memory/memory.limit_in_bytes

    用stress测试内存限制

    [root@node1 memory]# cgexec -g memory:lhd_stress_memory  stress -m 1 --vm-bytes 100M --vm-keep --verbose
    stress: info: [35293] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
    stress: dbug: [35293] using backoff sleep of 3000us
    stress: dbug: [35293] --> hogvm worker 1 [35294] forked
    stress: dbug: [35294] allocating 104857600 bytes ...
    stress: dbug: [35294] touching bytes in strides of 4096 bytes ...
    stress: FAIL: [35293] (415) <-- worker 35294 got signal 9
    stress: WARN: [35293] (417) now reaping child worker processes
    stress: FAIL: [35293] (451) failed run completed in 0s 
    因为有内存10M的限制,导致stress在申请100M内存时收到了 SIGKILL(signal 9) 信号
    测试改为10M范围内
    [root@node1 memory]# cgexec -g memory:lhd_stress_memory  stress -m 1 --vm-bytes 9M --vm-keep --verbose   

    此时可以正常运行

    用pidstat查看效果
    [root@node1 ~]# pidstat -r | grep stress
    14时34分21秒     0     41767      0.05      0.00    7948    1148   0.03  stress
    14时34分21秒     0     41768      0.07      0.00   17164    9328   0.24  stress

    六,与systemd相关的cgroup操作:

    1,systemd-cgtop:显示 cgoups 的实时资源消耗情况
    [root@node1 ~]# systemd-cgtop            
    Control Group                                              Tasks   %CPU   Memory  Input/s Output/s
    /                                                            211    4.0     1.0G        -        -
    /system.slice                                                 84    1.5   831.7M        -        -
    /user.slice                                                    9    0.9    64.3M        -        -
    /system.slice/kubelet.service                                 15    0.6    31.3M        - 
     
    2,systemd-cgls :查看 cgroups 的层级结构
    [root@node1 ~]# systemd-cgls
    Control group /:
    -.slice
    ├─user.slice
    │ └─user-0.slice
    │   ├─session-3.scope
    │   │ ├─14349 sshd: root [priv]
    …
     
    各slice的说明:
    -.slice: 根slice
    user.slice:   下面是所有的用户会话
    system.slice:  下面是所有系统service
    machine.slice: 下面是所有虚拟机和容器
     
    什么是slice:一组进程:由service或会话/容器/虚拟机组成
     
    3,为systemd启动的服务添加cgroup限制
    查看有哪些cgroup配置项可用
    [root@node1 ~]# man systemd.resource-control
    例子:
    查看nginx的内存限制:
    [root@node1 ~]# more /sys/fs/cgroup/memory/system.slice/nginx.service/memory.limit_in_bytes
    9223372036854771712
    上面是没有手动设置时的默认值
    设置内存限制
    [root@node1 ~]# systemctl set-property nginx.service MemoryLimit=512M
    再次查看
    [root@node1 ~]# more /sys/fs/cgroup/memory/system.slice/nginx.service/memory.limit_in_bytes
    536870912
    注意:即使服务重启,这个cgroup限制仍然会起作用,
    因为systemctl已经把它写到了service文件中,
    [root@node1 ~]# systemctl cat nginx
    # /usr/lib/systemd/system/nginx.service
    [Unit]
    Description=The nginx HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
     
    [Service]
    Type=forking
    PIDFile=/run/nginx.pid
    # Nginx will fail to start if /run/nginx.pid already exists but has the wrong
    # SELinux context. This might happen when running `nginx -t` from the cmdline.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1268621
    ExecStartPre=/usr/bin/rm -f /run/nginx.pid
    ExecStartPre=/usr/sbin/nginx -t
    ExecStart=/usr/sbin/nginx
    ExecReload=/bin/kill -s HUP $MAINPID
    KillSignal=SIGQUIT
    TimeoutStopSec=5
    KillMode=mixed
    PrivateTmp=true
     
    [Install]
    WantedBy=multi-user.target
     
    # /etc/systemd/system.control/nginx.service.d/50-MemoryLimit.conf
    # This is a drop-in unit file extension, created via "systemctl set-property"
    # or an equivalent operation. Do not edit.
    [Service]
    MemoryLimit=536870912
    4,其他常用命令:
    设置cpu使用率最高不超过单颗cpu的80%
    [root@node1 ~]# systemctl set-property nginx.service CPUQuota=80%
     

    七,查看linux的版本:

    [root@node1 ~]# more /etc/redhat-release
    CentOS Linux release 8.1.1911 (Core)
    [root@node1 ~]# uname -r
    4.18.0-147.el8.x86_64 
  • 相关阅读:
    Tarjan之求LCA
    最近公共祖先(LCA)
    『Tarjan』Tarjan求强连通分量模板
    「LCA + 树上差分」[USACO15DEC]最大流Max Flow
    『主席树』可持久化线段树模板
    「树状数组」[SDOI2009]HH的项链
    「LCA」仓鼠找sugar
    「线段树」[JSOI2008]最大数
    「LCA + 最小生成树」货车运输
    『最小生成树』最小生成树模板
  • 原文地址:https://www.cnblogs.com/architectforest/p/13126905.html
Copyright © 2011-2022 走看看