使用cgroup進行系統資源使用限制


環境:Centos 7 64

一、對某個進程限制它使用cpu為50%

1、先寫一個占用cpu較高的腳本

x=0
while [ True ];do
    x=$x+1
done;

2、可以看到運行后cpu使用到了100%

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                              
20369 root      20   0  113452   1664   1196 R  100.0  0.0   0:10.73 sh  

3、創建控制組

mkdir /sys/fs/cgroup/cpu/foo

4、下面用cgroups控制這個進程的cpu資源

echo 50000 > /sys/fs/cgroup/cpu/foo/cpu.cfs_quota_us #將cpu.cfs_quota_us設為50000,相對於cpu.cfs_period_us的100000是50%
echo 20369 >/sys/fs/cgroup/cpu/foo/tasks

5、我們看到大概限制到了50%左右

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                              
20369 root      20   0  113828   1908   1196 R  49.8  0.0   0:33.75 sh

6、cgroup控制組下還有很多對於cpu其他的一些控制

[root@foreman ~]# ls /sys/fs/cgroup/cpu/foo/
cgroup.clone_children  cpuacct.usage          cpu.rt_period_us       notify_on_release
cgroup.event_control   cpuacct.usage_percpu   cpu.rt_runtime_us      tasks
cgroup.procs           cpu.cfs_period_us      cpu.shares             
cpuacct.stat           cpu.cfs_quota_us       cpu.stat 

 

 

 

ls /sys/fs/cgroup/memory/cgtest/*

 cgroup.event_control       #用於eventfd的接口
 memory.usage_in_bytes      #顯示當前已用的內存
 memory.limit_in_bytes      #設置/顯示當前限制的內存額度
 memory.failcnt             #顯示內存使用量達到限制值的次數
 memory.max_usage_in_bytes  #歷史內存最大使用量
 memory.soft_limit_in_bytes #設置/顯示當前限制的內存軟額度
 memory.stat                #顯示當前cgroup的內存使用情況
 memory.use_hierarchy       #設置/顯示是否將子cgroup的內存使用情況統計到當前cgroup里面
 memory.force_empty         #觸發系統立即盡可能的回收當前cgroup中可以回收的內存
 memory.pressure_level      #設置內存壓力的通知事件,配合cgroup.event_control一起使用
 memory.swappiness          #設置和顯示當前的swappiness
 memory.move_charge_at_immigrate #設置當進程移動到其他cgroup中時,它所占用的內存是否也隨着移動過去
 memory.oom_control         #設置/顯示oom controls相關的配置
 memory.numa_stat           #顯示numa相關的內存

 

寫一個內存占用的c程序,每秒申請1MB內存 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MB (1024 * 1024)

int main(int argc, char *argv[])
{
    char *p;
    int i = 0;
    while(1) {
        p = (char *)malloc(MB);
        memset(p, 0, MB);
        printf("%dM memory allocated\n", ++i);
        sleep(1);
    }

    return 0;
}

#gcc mem-allocate.c  -o  mem-allocate

 

 cgroup限制內存使用50M(強制限制 memory.limit_in_bytes)

[root@foreman cgtest]# pwd
/sys/fs/cgroup/memory/cgtest
[root@foreman cgtest]# echo 50M > memory.limit_in_bytes 
[root@foreman cgtest]# echo 0 > memory.oom_control 
[root@foreman cgtest]# pgrep mem-allocate
35190
[root@foreman cgtest]# echo 35190 > tasks  #只對一個線程ID做限制 ,如果需要對一個線程組做限制,需要將PID放到cgroup.procs中。
                          這樣這個PID本身以及所衍生的進程整體會限制在memory.limit_in_bytes中設置的大小內存
                          同時包括這個PID調用所產生的進程也會受到限制。想查看某個進程所屬線程組使用如下命令
                          #cat /proc/<PID>/cgroup 來進行查看

 

限制效果:

[root@foreman ~]# ./mem-allocate 
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
...
...
49M memory allocated
50M memory allocated
51M memory allocated
Killed

 

如果達到限制不想直接kill進程,而是掛起進程需要將oom_kill_disable 設置為1
[root@foreman cgtest]#cat memory.oom_control #默認
oom_kill_disable 0
under_oom 0
[root@foreman cgtest]# echo 1 > memory.oom_control 
[root@foreman cgtest]# cat memory.oom_control 
oom_kill_disable 1
under_oom 0

 

跑一個腳本使其產生多個子線程去瘋狂吃內存(提前將memory.limitxxxxx設置為300MB,oom_kill 設置為0)

[root@foreman ~]# cat cgtest.sh 
sleep 20
x=0
while [ True ];do
    nohup /root/mem-allocate >>/root/mem.log 2>&1 &
    sleep 1
    proc_num=$(pgrep mem-allocate | wc -l)
    if [ $proc_num -eq 50 ];then
        sleep 1000000
    fi
    x=$(($x+1))
done;

跑起來后用systemd-cgtop查看限制情況:

#systemd-cgtop #使用此命令查看cgroup限制的資源情況
/cgtest                                                               25      -   295.8M
通過上面可以清晰的看到tasks 25個 內存限制到了300MB

 

 

概念理解:

就把 5678 進程加入到了 /foo 控制組。那么 tasks 和 cgroups.procs 有什么區別呢?前面說的對“進程”的管理限制其實不夠准確。系統對任務調度的單位是線程。
在這里,tasks 中看到的就是線程 id。而 cgroups.procs 中是線程組 id,也就是一般所說的進程 id 。
將一個一般的 pid 寫入到 tasks 中,只有這個 pid 對應的線程,以及由它產生的其他進程、線程會屬於這個控制組,原有的其他線程則不會。
而寫入 cgroups.procs 會把當前所有的線程都加入進去。如果寫入 cgroups.procs 的不是一個線程組 id,而是一個一般的線程 id,那會自動找到所對應的線程組 id 加入進去。
進程在加入一個控制組后,控制組所對應的限制會即時生效。想知道一個進程屬於哪些控制組,可以通過 cat /proc/<pid>/cgroup 查看。 要把進程移出控制組,把 pid 寫入到根 cgroup 的 tasks 文件即可。因為每個進程都屬於且只屬於一個 cgroup,加入到新的 cgroup 后,原有關系也就解除了。
要刪除一個 cgroup,可以用 rmdir 刪除相應目錄。不過在刪除前,必須先讓其中的進程全部退出,對應子系統的資源都已經釋放,否則是無法刪除的。 前面都是通過文件系統訪問方式來操作 cgroups 的。實際上,也有一組命令行工具。

 

 

 

  沒有英漢互譯結果
   請嘗試網頁搜索

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM