Cgroups v2:为什么内存限制设了,宿主机数据库还是被 OOM
Cgroups v2ï¼ä¸ºä»ä¹å åéå¶è®¾äºï¼å®¿ä¸»æºæ°æ®åºè¿æ¯è¢« OOM
ltl 2026-08-20 8 é 读12åéåæåå¸äº quant67.comï¼è½¬è½½è¯·ä¿çåºå¤ã
ä½ ç»å®¹å¨è®¾äº 512MB å
åéå¶ãdocker run --memory=512m postgresãç¶åæå¤©åæ¨ä¸ç¹ï¼çæ§æ¥è¦ï¼å®¿ä¸»æºä¸çæ°æ®åºè¢« OOM-killer å¹²æäºã䏿¯å®¹å¨éç â æ¯å®¿ä¸»æºä¸çã
æä¹åäºï¼ä½ çå åéå¶å¢ï¼
çæ¡å¯è½æ¯ï¼ä½ ç¨çæ¯ cgroups v1ï¼ä½ 设ç memory.limit_in_bytes ä¸å
å«å
æ ¸å
åï¼kmemï¼ï¼æè
ä½ ç容å¨ç»è¿äº buffered IO éå¶å¨ç¯çåç£çï¼page cache æå®¿ä¸»æºå
ååå
äºãä¹å¯è½åªæ¯ä½ ç cgroup é
ç½®æ ¹æ¬æ²¡çæ â v1 ç hierarchy 太乱äºï¼æ§å¶å¨ä¹é´äºç¸è¸©èã
ä¸ä¸ç¯æä»¬ç¨ namespace é离äºè¿ç¨ç"è§é"ãä½é离ä¸çäºéå¶ â ä¸ä¸ªè¢«é离çè¿ç¨ç §æ ·å¯ä»¥åææ´å°æºå¨ç CPUãå ååç£ç IOãNamespace ç®¡çæ¯"è½çè§ä»ä¹"ï¼Cgroups ç®¡çæ¯"è½ç¨å¤å°"ã
æ¬ç¯æä»¬æ·±å
¥ cgroups v2ï¼ä»æä»¶ç³»ç»æ¥å£å¼å§ï¼æå¨å建 cgroupã设éå¶ãåæµãçç»è®¡æ°æ®ãææä»£ç å¨ examples/containers/04-cgroups/ ç®å½ï¼make å³å¯ç¼è¯ã
ä¸ æä½ç³»ç»ç¾ç§ · cgroup v2 çåå·¥ï¼æ¬ç¯å±ãä»é¶é 容å¨ãå®æçº¿ââ
mkdir+ å cgroup æä»¶ãC åæµãOOM/CPU throttle æéï¼ç¾ç§ç¯è®² unified hierarchy å ¨æ¯ãPSIãsystemdslice/scopeãdelegation ä¸è¯æå§¿å¿ãéè¦ææè¿è¡æ¶çæ¬ç¯ï¼éè¦çè§£æ¥å¸¸systemctl/ kubelet èååå ¥äºåªäº knobï¼ä¸¤ç¯å¯¹ç §è¯»ãæµè¯ç¯å¢ï¼Linux 6.x, x86_64ï¼cgroups v2 unified hierarchyã
ä¸ãCgroups v1 vs v2ï¼ä¸ä¸ªåå²é误çä¿®æ£
Cgroupsï¼Control Groupsï¼å¨ 2008 å¹´è¿å ¥ Linux å æ ¸ï¼2.6.24ï¼ãåå§è®¾è®¡ â ç°å¨å« v1 â æ¯è¿æ ·çï¼
æ¯ä¸ªæ§å¶å¨ç¬ç«æè½½ä¸æ£µæ ã
/sys/fs/cgroup/
âââ cpu/ â cpu æ§å¶å¨èªå·±ä¸æ£µæ
â âââ docker/
â â âââ container_abc/
â â âââ cpu.cfs_quota_us
â â âââ tasks
â âââ ...
âââ memory/ â memory æ§å¶å¨èªå·±ä¸æ£µæ
â âââ docker/
â â âââ container_abc/
â â âââ memory.limit_in_bytes
â â âââ tasks
â âââ ...
âââ blkio/ â blkio æ§å¶å¨èªå·±ä¸æ£µæ
â âââ ...
âââ cpuset/ â cpuset æ§å¶å¨èªå·±ä¸æ£µæ
âââ ...
çå°é®é¢äºåï¼
-
åä¸ä¸ªè¿ç¨å¨ä¸åæ éçä½ç½®å¯ä»¥ä¸ä¸è´ã container_abc å¨ cpu æ ééäº 50%ï¼å¨ memory æ ééäº 512MBï¼ä½å¨ blkio æ éå¯è½æ ¹æ¬æ²¡é ç½®ãæ¯ä¸ªæ§å¶å¨ç¬ç«ç®¡çï¼æ²¡æç»ä¸ç"è¿ä¸ªå®¹å¨çææéå¶"çæ¦å¿µã
-
ç«äºæ¡ä»¶ã æä¸ä¸ªè¿ç¨å å ¥ cgroup éè¦åå«åæ¯æ£µæ ç
tasksæä»¶ãå¨å¤çº¿ç¨åºæ¯ä¸ï¼è¿ç¨ç线ç¨å¯è½å¨ä¸åæ§å¶å¨æ éå¤äºä¸åç cgroup â è¿ä¸æ¯ bugï¼è¿æ¯ v1 ç"ç¹æ§"ã -
å æ ¸å¤æåº¦çç¸ã æ¯ä¸ªæ§å¶å¨å¯ä»¥æèªå·±çå±çº§ç»æï¼å æ ¸è¦ç»´æ¤ N 棵ç¬ç«çæ ã代ç è·¯å¾äº¤åï¼bug é¾ä»¥å¤ç°ã
-
buffered IO ç婿¢¦ã v1 ç blkio æ§å¶å¨åªå¯¹ direct IO çæãåºç¨ç¨åºç buffered write èµ°çæ¯ page cacheï¼è page cache çååï¼writebackï¼åçå¨å æ ¸çº¿ç¨éï¼ä¸å±äºä»»ä½å®¹å¨ç blkio cgroupãç»æå°±æ¯ï¼ä½ è®¾äº IO éå¶ï¼ä½ buffered IO å®å ¨æ è§å®ã
Tejun Heoï¼cgroup åç³»ç»çç»´æ¤è ï¼å¨ 2012 å¹´å ¬å¼è¯´ v1 ç设计æ¯ä¸ªé误ãç¶åè±äºåå¹´æ¶é´è®¾è®¡å¹¶å®ç°äº cgroups v2ã
Cgroups v2 çæ ¸å¿æ¹åï¼unified hierarchy â 䏿£µæ 管ææã
/sys/fs/cgroup/ â å¯ä¸çæ ¹
âââ cgroup.controllers â å¯ç¨çæ§å¶å¨å表
âââ cgroup.subtree_control â åæ å¯ç¨äºåªäºæ§å¶å¨
âââ mycontainer/ â ä½ å建ç cgroupï¼å°±æ¯ä¸ªç®å½ï¼
â âââ cgroup.procs â é颿åªäºè¿ç¨
â âââ cgroup.controllers
â âââ cgroup.subtree_control
â âââ cpu.max â CPU éå¶
â âââ cpu.weight â CPU æé
â âââ cpu.stat â CPU ç»è®¡
â âââ memory.max â å
å硬éå¶
â âââ memory.high â å
å软éå¶
â âââ memory.current â å½åå
å使ç¨
â âââ memory.stat â å
åç»è®¡
â âââ io.max â IO éå¶
â âââ io.weight â IO æé
â âââ io.stat â IO ç»è®¡
âââ system.slice/ â systemd å建ç cgroup
âââ ...
ä¸ä¸ªè¿ç¨å¨æ éåªæä¸ä¸ªä½ç½®ãæææ§å¶å¨å ±äº«å䏿£µå±çº§ç»æã没æç«äºæ¡ä»¶ã没æä¸ä¸è´ã
ï¼ç¤ºæå¾è§åæï¼Cgroups v2 ç»ä¸å±çº§ç»æï¼
ä» Linux 5.x å¼å§ï¼ææä¸»æµåè¡çé»è®¤ä½¿ç¨ cgroups v2ãå¦æä½ è¿å¨ç¨ v1ï¼è¯·è®¤çèèè¿ç§»ã
äºãæä»¶ç³»ç»æ¥å£ï¼mkdir å°±æ¯å建 cgroup
Cgroups v2 çæ¥å£å°±æ¯æä»¶ç³»ç»ã没æç¹æ®çç³»ç»è°ç¨ï¼æ²¡æ ioctlï¼å°±æ¯è¯»åæä»¶ã
å建 cgroup
# å°±æ¯å建ä¸ä¸ªç®å½
$ sudo mkdir /sys/fs/cgroup/mycontainer
$ ls /sys/fs/cgroup/mycontainer/
cgroup.controllers cgroup.events cgroup.procs cgroup.stat
cgroup.subtree_control cgroup.type cpu.stat io.stat memory.current
memory.stat ...
å建ç®å½çç¬é´ï¼å
æ ¸èªå¨çæäºæææ§å¶æä»¶ãè¿ä¸æ¯æ®éæä»¶ç³»ç» â è¿æ¯ cgroup2fsï¼æ¯ä¸ªæä»¶è忝å
æ ¸ç cgroup åç³»ç»ã
æ¥çå¯ç¨æ§å¶å¨
$ cat /sys/fs/cgroup/cgroup.controllers
cpuset cpu io memory hugetlb pids rdma misc
å¯ç¨åæ æ§å¶å¨
å
³é®æ¦å¿µï¼æ§å¶å¨å¿
é¡»å¨ç¶ cgroup ç cgroup.subtree_control ä¸å¯ç¨ï¼æè½å¨å cgroup ä¸ä½¿ç¨ã
# 卿 ¹ cgroup å¯ç¨ cpuãmemoryãio æ§å¶å¨
$ echo "+cpu +memory +io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
æè¿ç¨å å ¥ cgroup
# æ PID åè¿ cgroup.procs
$ echo $$ | sudo tee /sys/fs/cgroup/mycontainer/cgroup.procs
# éªè¯
$ cat /proc/self/cgroup
0::/mycontainer
å°±è¿æ ·ã没æéæ³ APIãmkdir + echo å°±æ¯å
¨é¨æ¥å£ã
å é¤ cgroup
# å
ç¡®ä¿æ²¡æè¿ç¨å¨éé¢
$ cat /sys/fs/cgroup/mycontainer/cgroup.procs
# (åºè¯¥ä¸ºç©º)
# ç¶å rmdir
$ sudo rmdir /sys/fs/cgroup/mycontainer
æ³¨ææ¯ rmdirï¼ä¸æ¯ rm -rfãä½ ä¸è½å é¤å
å«è¿ç¨ç cgroupï¼ä¹ä¸è½å 餿å cgroup ç cgroupãå¿
é¡»èªåºå䏿¸
çã
ä¸ãCPU æ§å¶ï¼ä¸æ¯"éå¶"é£ä¹ç®å
cpu.max â 硬ä¸é
cpu.max çæ ¼å¼æ¯ "quota period"ï¼å使¯å¾®ç§ï¼
# æ¯ 100ms éåªè½ç¨ 50ms CPU = 50% çä¸ä¸ªæ ¸
$ echo "50000 100000" | sudo tee /sys/fs/cgroup/mycontainer/cpu.max
# ä¸éå¶
$ echo "max 100000" | sudo tee /sys/fs/cgroup/mycontainer/cpu.max
è¿æ¯ CFSï¼Completely Fair Schedulerï¼ç带宽æ§å¶ãå
æ ¸å¨æ¯ä¸ª period å¼å§æ¶ç» cgroup åé
quota å¾®ç§ç CPU æ¶é´ãç¨å®äºå°±çä¸ä¸ª periodã
夿 ¸åºæ¯ï¼quota å¯ä»¥è¶
è¿ periodã"200000 100000" è¡¨ç¤ºæ¯ 100ms å¯ä»¥ç¨ 200ms CPU æ¶é´ï¼å³ä¸¤ä¸ªæ ¸çç®åã
cpu.weight â ç¸å¯¹æé
å½ CPU ç«äºæ¶ï¼cpu.weight å³å®åé
æ¯ä¾ï¼
# èå´ 1-10000ï¼é»è®¤ 100
$ echo 200 | sudo tee /sys/fs/cgroup/mycontainer/cpu.weight
妿 cgroup A ç weight æ¯ 200ï¼cgroup B æ¯ 100ï¼CPU ç´§å¼ æ¶ A æ¿å° 2/3ï¼B æ¿å° 1/3ãCPU ç©ºé²æ¶ä¸¤è é½è½ç¨æ»¡ã
weight å max çåºå«ï¼weight æ¯"ç«äºæ¶çå ¬å¹³æ§"ï¼max æ¯"ç»å¯¹ä¸è½è¶ è¿"ãç产ç¯å¢ä¸¤ä¸ªé½è¦è®¾ã
CFS å¸¦å®½èæµçéè代价
è¿éæä¸ªåãCFS 带宽æ§å¶æä¸ªä¼æå¨ç¥ç尾延è¿é®é¢ã
åè®¾ä½ è®¾äº "50000 100000"ï¼50% CPUï¼ãä½ çç¨åºå¨ä¸ä¸ª period çå 50ms éæ quota ç¨å®äºãç¶åå®å°±è¢« throttle äºï¼å³ä½¿ CPU å®å
¨ç©ºé²ï¼å®ä¹è¦çå°ä¸ä¸ª periodï¼è¿æ 50msï¼æè½è¿è¡ã
å¦æä½ çç¨åºæ¯ä¸ª web æå¡å¨ï¼è¿ 50ms ççå¾ ç´æ¥å å°äºè¯·æ±å»¶è¿ä¸ãP99 å»¶è¿æ´æ¶¨ã
æä¹åç°é®é¢ï¼ç cpu.statï¼
$ cat /sys/fs/cgroup/mycontainer/cpu.stat
usage_usec 23456789
user_usec 20000000
system_usec 3456789
nr_periods 1200
nr_throttled 342
throttled_usec 17100000
nr_throttled æ¯æéè¦çææ ã 妿è¿ä¸ªæ°åå¨å¿«éå¢é¿ï¼è¯´æä½ ç CPU éå¶å¤ªç´§äºï¼è¿ç¨å¨é¢ç¹è¢«èæµãå¾å¤çäº§äºæ
çæ ¹å 齿¯ï¼å®¹å¨ CPU limit è®¾å¤ªä½ â é¢ç¹ throttle â å»¶è¿é£å â è¶
æ¶ â éªå´©ã
Kubernetes ç¤¾åºæä¸ªé¿æäºè®ºï¼å°åºè¯¥ä¸è¯¥è®¾ CPU limitãå对æ¹çæ ¸å¿è®ºç¹å°±æ¯ CFS å¸¦å®½èæµç尾延è¿é®é¢ãä½ å¯ä»¥åªè®¾ cpu.weightï¼å¯¹åº K8s ç requestsï¼ä¸è®¾ cpu.maxï¼å¯¹åº K8s ç limitsï¼â è¿æ · CPU ç«äºæ¶æå
¬å¹³æ§ä¿éï¼ä½ä¸ä¼åºç°"CPU 空é²å´è¢« throttle"çèè°¬åºæ¯ã
åãå åæ§å¶ï¼soft limit æ¯ hard limit æ´éè¦
memory.max â 硬éå¶
# 64MB 硬éå¶
$ echo 67108864 | sudo tee /sys/fs/cgroup/mycontainer/memory.max
è¶ è¿è¿ä¸ªå¼ï¼å æ ¸è§¦å OOM killerãç®åç²æ´ã
memory.high â 软éå¶ï¼æ´æç¨ï¼
# 56MB 软éå¶
$ echo 58720256 | sudo tee /sys/fs/cgroup/mycontainer/memory.high
memory.high æ¯æ´æ¸©åçæ¹å¼ï¼è¶
è¿è¿ä¸ªå¼æ¶ï¼å
æ ¸ä¼ç§¯æåæ¶è¿ä¸ª cgroup çå
åï¼æ page cache å·å°ç£çãå缩å¿å页çï¼ï¼å¹¶æ
æåæ
¢å
ååé
é度ãå
·ä½æ¥è¯´ï¼ç¨æ·çº¿ç¨ä¼å¨åé
è·¯å¾ä¸è¢«è¿«è¿å
¥ direct reclaim / compactionï¼èªå·±æ¿å
æ ¸"è¿åº"ãè¿ç¨ä¼åæ
¢ï¼ä½ä¸ä¼è¢«æã
memory.highãmemory.maxãmemory.low ä¸è çå ³ç³» â å³çæåï¼
æå®ä»¬æ³æä¸éé²çº¿ï¼
| æ¥å£ | è§è² | 触ååæ | ç±»æ¯ |
|---|---|---|---|
memory.low | ä¿æ¤çº¿ | å æ ¸å¨åæ¶å åæ¶å°½éä¸å¨è¿ä¸ª cgroupï¼é¤éå ¨å±åå太大 | "æä½çæ´»ä¿é" |
memory.high | 软éå¶ / èæµçº¿ | è¶ è¿åå æ ¸ç§¯æåæ¶ + æ æåæ ¢å ååé ï¼è¿ç¨åæ ¢ä½ä¸ä¼è¢«æ | "é»ç¯ï¼åé" |
memory.max | 硬éå¶ / çæ»çº¿ | è¶ è¿ä¸åæ¶å¤±è´¥ â OOM kill | "红ç¯ï¼æäºå°±æ»" |
æä½³å®è·µï¼æ memory.high è®¾å¨ memory.max ç 85â90% å·¦å³ãæ¯å¦ä½ ç硬éå¶æ¯ 512MBï¼é£å°±æ memory.high è®¾å° ~435â460MBãè¿æ ·å½å
åä½¿ç¨æ¥è¿ä¸éæ¶ï¼è¿ç¨ä¼å
è¢«èæµåéï¼ç»ä½ åç°é®é¢çæ¶é´çªå£ï¼ï¼è䏿¯ç´æ¥è¢« OOM ä¸ååãmemory.low åç¨æ¥ä¿æ¤å
³é®æå¡ â æ¯å¦ä½ çæ°æ®åº cgroup 设ä¸ä¸ª memory.lowï¼å¨æ´æºå
åç´§å¼ æ¶å
æ ¸ä¼ä¼å
åæ¶å
¶ä» cgroup çå
åã
ç®åè®°ï¼low ä¿åºï¼high é¢è¦ï¼max å åºãä¸éé²çº¿ï¼å±å±éè¿ã
memory.low â æä½ä¿é
$ echo 33554432 | sudo tee /sys/fs/cgroup/mycontainer/memory.low
memory.low æ¯"å°½åä¿æ¤"ï¼å
æ ¸å¨åæ¶å
åæ¶ä¼å°½éé¿å
å¨è¿ä¸ª cgroup çå
åï¼é¤éç³»ç»æ´ä½å
ååå太大ãç¨æ¥ä¿æ¤å
³é®æå¡ä¸è¢«é¥¿æ»ã
OOM è¡ä¸ºï¼memory.oom.group
é»è®¤æ åµä¸ï¼OOM killer æé cgroup é"æè"çè¿ç¨ææãä½å®¹å¨åºæ¯ä¸ï¼ä½ éå¸¸å¸ææææ´ä¸ª cgroupï¼
# å¯ç¨ç»æ
$ echo 1 | sudo tee /sys/fs/cgroup/mycontainer/memory.oom.group
å¯ç¨åï¼ä¸æ¦è§¦å OOMï¼cgroup å çææè¿ç¨ä¸èµ·è¢«æãè¿æ´ç¬¦å容å¨è¯ä¹ â 容å¨è¦ä¹æ´»çï¼è¦ä¹æ´ä¸ªæ»æï¼ä¸è¦æ"æäºä¸ä¸ªè¿ç¨å©ä¸çå¸¦çæ®ç¼ºç¶æç»§ç»è·"ã
memory.stat â çè§£å åå»äºåªé
$ cat /sys/fs/cgroup/mycontainer/memory.stat
anon 12345678
file 8765432
kernel 2345678
shmem 123456
...
pgfault 98765
pgmajfault 12
...
å ³é®å段ï¼
| åæ®µ | å«ä¹ |
|---|---|
anon | å¿å页ï¼å ãæ ãmmap ç MAP_ANONYMOUSï¼ |
file | page cacheï¼è¯»åæä»¶äº§ççç¼åï¼ |
kernel | å æ ¸ä¸ºè¿ä¸ª cgroup åé çå åï¼slabã页表çï¼ |
shmem | å ±äº«å åå tmpfs |
pgfault | minor page fault æ¬¡æ° |
pgmajfault | major page faultï¼éè¦ä»ç£çè¯»ï¼æ¬¡æ° |
memory.current æ¯æ»æ°ï¼memory.stat åè¯ä½ ç»åãå½ä½ è°æ¥"å
åå»äºåªé"çæ¶åï¼memory.stat æ¯ç¬¬ä¸ä¸ªççå°æ¹ã
å¦æä½ ç¨ jemalloc æ tcmalloc è¿æ ·çå
ååé
å¨ï¼å®ä»¬ç arena å线ç¨ç¼åå¯è½å¯¼è´ memory.current è¿é«äºç¨åºå®é
çå·¥ä½éãè¯¦è§ å
ååé
å¨ï¼arena ä¸ç¢çã
äºãIO æ§å¶ï¼æ¾ç»åäºå¾å¤å¹´
io.max â 硬éå¶
IO éå¶æè®¾å¤è®¾ç½®ï¼éè¦å ç¥é设å¤ç major:minor å·ï¼
# æ¥ç设å¤å·
$ lsblk -o NAME,MAJ:MIN
NAME MAJ:MIN
sda 8:0
ââsda1 8:1
ââsda2 8:2
# éå¶ sda ç读å带宽å IOPS
$ echo "8:0 rbps=10485760 wbps=10485760 riops=1000 wiops=1000" | \
sudo tee /sys/fs/cgroup/mycontainer/io.max
åä¸ªåæ°ï¼
rbps/wbpsï¼è¯»/ååè带宽ï¼bytes/secï¼riops/wiopsï¼è¯»/å IOPS
io.weight â æ¯ä¾æé
# èå´ 1-10000ï¼é»è®¤ 100
$ echo "default 200" | sudo tee /sys/fs/cgroup/mycontainer/io.weight
为ä»ä¹ IO æ§å¶åäºå¾å¤å¹´
v1 ç blkio æ§å¶å¨æä¸ªè´å½ç¼ºé·ï¼å®åªå¯¹ direct IO çæã
Linux ç IO è·¯å¾æ¯è¿æ ·çï¼
- åºç¨ç¨åºè°ç¨
write()â æ°æ®åå ¥ page cacheï¼å åï¼ï¼ç«å»è¿å - å æ ¸ç writeback 线ç¨å¨åå°æ page cache å·å°ç£ç
é®é¢å¨äºï¼writeback çº¿ç¨æ¯å æ ¸çº¿ç¨ï¼ä¸å±äºä»»ä½å®¹å¨ç cgroupãv1 ç blkio æ§å¶å¨å¨ IO è°åº¦å¨å±åéå¶ï¼ä½ buffered write å°è¾¾ IO è°åº¦å¨æ¶ï¼å·²ç»ä¸ç¥é宿¥èªåªä¸ª cgroup äºã
ç»æå°±æ¯ï¼ä½ è®¾äº blkio.throttle.write_bps_deviceï¼ä½ çç¨åºç¨ buffered write ç
§æ ·å¯ä»¥ç¬é´æ page cache 塿»¡ï¼ç¶å writeback ååææ´å°æºå¨ç IO ææ»¡ãä½ ç IO éå¶å½¢åè设ã
Cgroups v2 éè¿ writeback æç¥ï¼writeback-aware IO controllerï¼è§£å³äºè¿ä¸ªé®é¢ã å¨ v2 ä¸ï¼page cache ä¼è®°ä½å®å±äºåªä¸ª cgroupï¼writeback æ¶ä¼æ£ç¡®è®¡å ¥å¯¹åº cgroup ç IO é é¢ãä½éè¦å æ ¸åæä»¶ç³»ç»é½æ¯æï¼ext4 å btrfs æ¯æï¼XFS å¨è¾æ°å æ ¸ä¸æ¯æï¼ã
è¿æ¯ä» v1 è¿ç§»å° v2 æéè¦ççç±ä¹ä¸ã
å ã宿´ç¤ºä¾ï¼ä»å建å°åæµ
ä¸é¢ç C ç¨åºæ¼ç¤ºäºå®æ´æµç¨ï¼å建 cgroupã设éå¶ãfork åè¿ç¨è¿å»ãè·åæµãçæ§ç»è®¡æ°æ®ã
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define CGROUP_ROOT "/sys/fs/cgroup"
#define CGROUP_NAME "demo_container"
#define CGROUP_PATH CGROUP_ROOT "/" CGROUP_NAME
// å cgroup æ§å¶æä»¶åå
¥å符串
static int cg_write(const char *path, const char *value) {
int fd = open(path, O_WRONLY);
if (fd < 0) { perror(path); return -1; }
int ret = write(fd, value, strlen(value));
close(fd);
return ret < 0 ? -1 : 0;
}
// 读å cgroup æ§å¶æä»¶
static int cg_read(const char *path, char *buf, size_t len) {
int fd = open(path, O_RDONLY);
if (fd < 0) { perror(path); return -1; }
ssize_t n = read(fd, buf, len - 1);
close(fd);
if (n < 0) return -1;
buf[n] = '\0';
return 0;
}
// åè¿ç¨åæµï¼å CPU åå
å
static void stress_workload(void) {
printf("[child %d] å¼å§åæµ... ", getpid());
// CPU åæµï¼å¿å¾ªç¯
volatile unsigned long counter = 0;
// å
ååæµï¼åé
32MB
size_t alloc_size = 32 * 1024 * 1024;
char *mem = malloc(alloc_size);
if (mem) {
memset(mem, 0xAA, alloc_size);
printf("[child] å·²åé
å¹¶å¡«å
%zu MB ", alloc_size / (1024 * 1024));
}
for (int i = 0; i < 5; i++) {
for (long j = 0; j < 100000000L; j++)
counter++;
printf("[child] CPU å¾ªç¯ %d/5 宿, counter=%lu ", i + 1, counter);
}
free(mem);
printf("[child] åæµç»æ ");
}
int main(void) {
char buf[4096];
// 1. ç¡®ä¿åæ§å¶å¨å·²å¯ç¨
printf("=== å¯ç¨ cpu å memory æ§å¶å¨ === ");
cg_write(CGROUP_ROOT "/cgroup.subtree_control", "+cpu +memory");
// 2. å建 cgroup
printf("=== å建 cgroup: %s === ", CGROUP_PATH);
if (mkdir(CGROUP_PATH, 0755) && errno != EEXIST) {
perror("mkdir cgroup");
return 1;
}
// 3. 设置éå¶
printf("=== 设置 CPU éå¶: 50%% === ");
cg_write(CGROUP_PATH "/cpu.max", "50000 100000");
printf("=== 设置å
åéå¶: 64MB === ");
cg_write(CGROUP_PATH "/memory.max", "67108864");
cg_write(CGROUP_PATH "/memory.high", "58720256");
// 4. Fork åè¿ç¨
pid_t pid = fork();
if (pid < 0) { perror("fork"); return 1; }
if (pid == 0) {
// åè¿ç¨ï¼æèªå·±å å
¥ cgroup
char pid_str[32];
snprintf(pid_str, sizeof(pid_str), "%d", getpid());
cg_write(CGROUP_PATH "/cgroup.procs", pid_str);
printf("[child %s] å·²å å
¥ cgroup ", pid_str);
stress_workload();
_exit(0);
}
// 5. ç¶è¿ç¨ï¼çæ§ cgroup ç»è®¡æ°æ®
printf(" === ç¶è¿ç¨çæ§ä¸ (æ¯ç§ä¸æ¬¡) === ");
for (int i = 0; i < 8; i++) {
sleep(1);
printf(" --- 第 %d ç§ --- ", i + 1);
if (cg_read(CGROUP_PATH "/memory.current", buf, sizeof(buf)) == 0)
printf("memory.current: %s", buf);
if (cg_read(CGROUP_PATH "/cpu.stat", buf, sizeof(buf)) == 0) {
// åªæå°å
³é®è¡
char *line = strtok(buf, " ");
while (line) {
if (strstr(line, "throttled") || strstr(line, "usage"))
printf("cpu.stat: %s ", line);
line = strtok(NULL, " ");
}
}
}
// 6. çå¾
åè¿ç¨
int status;
waitpid(pid, &status, 0);
printf(" åè¿ç¨éåº, status=%d ", WEXITSTATUS(status));
// 7. æ¸
ç
printf("=== æ¸
ç cgroup === ");
rmdir(CGROUP_PATH);
return 0;
}
ç¼è¯è¿è¡ï¼éè¦ rootï¼ï¼
$ make
$ sudo ./cgroup_demo
=== å¯ç¨ cpu å memory æ§å¶å¨ ===
=== å建 cgroup: /sys/fs/cgroup/demo_container ===
=== 设置 CPU éå¶: 50% ===
=== 设置å
åéå¶: 64MB ===
[child 12345] å·²å å
¥ cgroup
[child 12345] å¼å§åæµ...
[child] å·²åé
å¹¶å¡«å
32 MB
=== ç¶è¿ç¨çæ§ä¸ (æ¯ç§ä¸æ¬¡) ===
--- 第 1 ç§ ---
memory.current: 33816576
cpu.stat: usage_usec 498213
cpu.stat: nr_throttled 3
cpu.stat: throttled_usec 1502345
--- 第 2 ç§ ---
memory.current: 33816576
cpu.stat: usage_usec 997856
cpu.stat: nr_throttled 8
cpu.stat: throttled_usec 4012345
...
注æ nr_throttled å¨å¢é¿ â å 为æä»¬è®¾äº 50% CPU éå¶ï¼è¿ç¨çå¿å¾ªç¯ä¸æè¢«èæµã
宿´ä»£ç å OOM æ¼ç¤ºè§ examples/containers/04-cgroups/ã
ä¸ãOOM 宿ï¼è®© cgroup ä¸èµ·å»æ»
OOM killer æ¯ Linux éæè®©äººå¤´ç¼çæºå¶ä¹ä¸ãæä»¬æ¥æ æè§¦åå®ï¼
#define CGROUP_PATH "/sys/fs/cgroup/oom_test"
int main(void) {
// å建 cgroupï¼è®¾ 8MB å
åéå¶
mkdir(CGROUP_PATH, 0755);
cg_write(CGROUP_PATH "/memory.max", "8388608");
// å¯ç¨ç»æ â OOM æ¶æææ´ä¸ª cgroup
cg_write(CGROUP_PATH "/memory.oom.group", "1");
pid_t pid = fork();
if (pid == 0) {
// å å
¥ cgroup
char s[32]; snprintf(s, sizeof(s), "%d", getpid());
cg_write(CGROUP_PATH "/cgroup.procs", s);
// ç¯çåé
å
åç´å°è¢«æ
size_t total = 0;
while (1) {
char *p = malloc(1024 * 1024);
if (!p) break;
memset(p, 0xFF, 1024 * 1024);
total += 1024 * 1024;
printf("å·²åé
%zu MB ", total / (1024*1024));
}
_exit(0);
}
int status;
waitpid(pid, &status, 0);
if (WIFSIGNALED(status))
printf("åè¿ç¨è¢«ä¿¡å· %d ææ» (SIGKILL=%d) ",
WTERMSIG(status), SIGKILL);
// æ¥ç OOM äºä»¶
char buf[256];
cg_read(CGROUP_PATH "/memory.events", buf, sizeof(buf));
printf("memory.events: %s ", buf);
rmdir(CGROUP_PATH);
return 0;
}
è¿è¡è¾åºï¼
$ sudo ./oom_demo
å·²åé
1 MB
å·²åé
2 MB
å·²åé
3 MB
å·²åé
4 MB
å·²åé
5 MB
å·²åé
6 MB
åè¿ç¨è¢«ä¿¡å· 9 ææ» (SIGKILL=9)
memory.events:
low 0
high 0
max 12
oom 1
oom_kill 1
oom_group_kill 1
memory.events éç oom_kill å oom_group_kill 计æ°å¨æ¸
æ¥å°è®°å½äº OOM äºä»¶ãè¿æ¯çº¿ä¸ææ¥ OOM çå
³é®æä»¶ â ä¸è¦å»ç¿» dmesg äºã
宿´æºç è§ examples/containers/04-cgroups/oom_demo.cã
å «ãç»ä»£ç å éå¶æ¶çå 个å
å 1ï¼subtree_control ç"no internal processes"è§å
Cgroups v2 æä¸ªéè¦éå¶ï¼å¦æä¸ä¸ª cgroup å¯ç¨äº subtree_controlï¼å®èªèº«ä¸è½å å«è¿ç¨ï¼leaf cgroup é¤å¤ï¼ã
# è¿æ ·å伿¥é
$ echo "+cpu" > /sys/fs/cgroup/mygroup/cgroup.subtree_control
$ echo $$ > /sys/fs/cgroup/mygroup/cgroup.procs
# Error: Device or resource busy
è¿ç¨åªè½æ¾å¨å¶å cgroup éãè¿æ¯ä¸ºäºé¿å "ç¶ cgroup çèµæºéå¶åå cgroup çèµæºéå¶äºç¸çç¾"çé®é¢ã
å 2ï¼memory.max ç OOM æ¯å¼æ¥ç
è®¾äº memory.max åï¼è¿ç¨åé
å
åå°è¾¾ä¸éæ¶ä¸ä¼ç«å»æ¶å° SIGKILLãå
æ ¸ä¼å
å°è¯åæ¶ï¼reclaimï¼ï¼å¦æåæ¶å¤±è´¥æè§¦å OOM killerãè¿ä¸é´å¯è½æå 忝«ç§å°å ç§çå»¶è¿ï¼è¿ç¨å¤äºåæ»ä¸æ´»ç reclaim ç¶æã
æä»¥å¨å®é
使ç¨ä¸ï¼memory.high æ¯ memory.max æ´æç¨ â å®å¨å°è¾¾éå¶åå°±å¼å§åéï¼é¿å
çªç¶æ»äº¡ã
å 3ï¼CPU ç»è®¡çæ¶é´åºå
cpu.stat éç usage_usec æ¯ CPU æ¶é´ï¼ä¸æ¯å¢éæ¶é´ãå¦æä½ çç¨åºè·å¨ 4 ä¸ªæ ¸ä¸ï¼1 ç§å¢éæ¶é´å¯¹åº 4 ç§ CPU æ¶é´ï¼4,000,000 usecï¼ãè®¡ç® CPU 使ç¨çæ¶å«å¿äºé¤ä»¥æ ¸æ°ã
ä¹ãCgroups ä¸å®¹å¨è¿è¡æ¶çå ³ç³»
ç°å¨è®©æä»¬æè§éæé«ãå½ Docker æ containerd å建ä¸ä¸ªå®¹å¨æ¶ï¼å¨ cgroups å±é¢åçäºä»ä¹ï¼
/sys/fs/cgroup/
âââ system.slice/ â systemd å建ç
âââ docker-<container_id>.scope/ â Docker å建ç
âââ cpu.max = "100000 100000" â --cpus=1
âââ memory.max = "536870912" â --memory=512m
âââ memory.high = "429496729" â (Docker å¯è½èªå¨è®¾)
âââ pids.max = "1024" â --pids-limit=1024
âââ cgroup.procs = "12345 12346 " â 容å¨éçè¿ç¨
Docker åçäºæ åæä»¬ä¸é¢ç C 代ç 䏿¨¡ä¸æ ·ï¼mkdirãåæä»¶ãæè¿ç¨ PID echo è¿å»ã没æéæ³ã
Kubernetes æ´å¤æä¸äº â å®éè¿ kubelet 管ç cgroup hierarchyï¼æ¯æ Pod 级å«ï¼QoS classï¼å容å¨çº§å«çéå¶ï¼
/sys/fs/cgroup/
âââ kubepods.slice/
âââ kubepods-burstable.slice/ â Burstable QoS
â âââ kubepods-burstable-pod<id>.slice/
â âââ cri-containerd-<id>.scope/
â âââ cpu.max
â âââ memory.max
âââ kubepods-besteffort.slice/ â BestEffort QoS
âââ ...
systemd ä¸ Kubernetes èµæºæ¨¡åå¦ä½è½å° cgroup
æ¥å¸¸å¾å°ç´æ¥ echo å /sys/fs/cgroup/ââsystemd ç®¡åæºæå¡ï¼kubelet 管 Pod 容å¨ãäºè
æç»ä»æ¯ååä¸å¥ v2 æä»¶ï¼ææ¸
æ å°ï¼æéæ¶æç¥éãYAML éé£ä¸ª limit å°åºå¡å¨åªãã
systemdï¼systemd.resource-control(5)ï¼A çº§ï¼æ unit 屿§ç¿»è¯ä¸º cgroup è·¯å¾ä¸çåå
¥ï¼
systemd 屿§ï¼systemctl set-propertyï¼ | cgroup v2 æä»¶ | è¯ä¹ |
|---|---|---|
CPUWeight= | cpu.weight | ç«äºæ¶ç¸å¯¹ä»½é¢ï¼1â10000ï¼ |
CPUQuota= / CPUQuotaPeriodSec= | cpu.max | CFS 带宽硬ä¸éï¼quota period å¾®ç§ï¼ |
MemoryMin= | memory.min | åæ¶æ¶å°½éä¿ççä¸é |
MemoryLow= | memory.low | è½¯ä¿æ¤ï¼å¼±äº memory.minï¼ |
MemoryHigh= | memory.high | è¶ çº¿å主å¨åæ¶ + åé åé |
MemoryMax= | memory.max | 硬ä¸éï¼è§¦å cgroup OOM |
MemorySwapMax= | memory.swap.max | swap é é¢ |
IOReadBandwidthMax= ç | io.max | æ major:minor é带宽/IOPS |
TasksMax= | pids.max | è¿ç¨/çº¿ç¨æ°ä¸é |
示ä¾ï¼systemctl set-property nginx.service CPUQuota=200% çä»·äºå¨è¯¥ service å¯¹åº cgroup å cpu.maxï¼è¡¨ç¤ºæ¯ period æå¤ç¨ 2 ä¸ªæ ¸ç CPU æ¶é´ï¼ä¸ç¬¬ä¸è cpu.max æ ¼å¼ä¸è´ï¼ã
Kubernetesï¼kubelet + cgroup v2ï¼1.25+ é»è®¤ v2ï¼è¡ä¸ºä»¥é群 cgroupDriver=systemd ä¸ release ææ¡£ä¸ºåï¼æ Pod/å®¹å¨ spec æ å°å° kubepods.slice/ åæ ï¼
| K8s åæ®µ | cgroup v2ï¼å®¹å¨ scopeï¼ | 说æ |
|---|---|---|
resources.limits.cpu | cpu.max | éé¢ â CFS quotaï¼ç©ºé² CPU ä¹ä¸ååºï¼æè§¦å nr_throttledï¼è§ç¬¬ä¸èï¼ |
resources.requests.cpu | cpu.weight | kubelet æ request æ¯ä¾åé weightï¼ä¸è®¾ limit æ¶ä» weight çæ |
resources.limits.memory | memory.max | 容å¨ç¡¬é¡¶ï¼OOM æ cgroup å è¿ç¨ |
resources.requests.memory | memory.min | å°½åä¿è¯çåæ¶ä¿æ¤çº¿ï¼éãå·²åé å³å ç¨ãï¼ |
| ï¼æ ç´æ¥ YAML åæ®µï¼ | memory.high | é¨ååè¡ç/è¿è¡æ¶å¯é设ï¼K8s 䏿 request æ å°å° memory.high |
QoS ä¸å±çº§ï¼kubepods-guaranteed / burstable / besteffort sliceï¼å³å® Pod cgroup åµå¨åªæ¡åæ¯ï¼Guaranteedï¼request = limitï¼å¨å
åç´§å¼ æ¶ æå被驱éï¼BestEffort æå
ââè¿æ¯è°åº¦ä¸ eviction çç¥ï¼åºå±ä»é ä¸è¿°æä»¶çæã
常è§è¯¯åºï¼ä¸ç¬¬ä¸èã第åä¸èæéè¡æ¥ï¼ï¼
- åªè®¾ CPU request ä¸è®¾ limitï¼åªæ
cpu.weightï¼ä¸ä¼è¢« CFS throttleï¼ä½ç«äºæ¶ä»½é¢åºå®ã - CPU limit 设è¿ä½ï¼
cpu.maxææ»¡å³ throttleï¼P99 æ¯åºèå¹³å CPUãçèµ·æ¥ä¸é«ãââæ¥cpu.statçnr_throttledã - æ memory request 彿已ç¨å
åï¼request â
memory.minæ¯ ä¿æ¤çº¿ï¼ä¸çäºå®¹å¨å½å RSSï¼å®é ç¨éçmemory.currentã - Pod limit ä¸èç¹ allocatableï¼èç¹ cgroup è¿æ
kubepodsç¶çº§ï¼å容卿ªè¶ éä»å¯è½å èç¹ memory.pressure 触å evictionï¼è§ ç¾ç§ç¯ PSIï¼ã
åãä¸å¼ 表æ»ç» Cgroups v2 æ¥å£
| æä»¶ | ç¨é | 示ä¾å¼ |
|---|---|---|
cgroup.procs | å å ¥/æ¥çè¿ç¨ | echo 1234 > cgroup.procs |
cgroup.controllers | å¯ç¨æ§å¶å¨ | cpu memory io pids |
cgroup.subtree_control | åæ å¯ç¨çæ§å¶å¨ | echo "+cpu +memory" > ... |
cpu.max | CPU 硬éå¶ (quota period) | "50000 100000" = 50% |
cpu.weight | CPU ç¸å¯¹æé | 1-10000ï¼é»è®¤ 100 |
cpu.stat | CPU ç»è®¡ | nr_throttled, throttled_usec |
memory.max | å å硬éå¶ | 67108864 (64MB) |
memory.high | å å软éå¶ï¼èæµï¼ | 58720256 (56MB) |
memory.low | å åä¿æ¤ | 33554432 (32MB) |
memory.current | å½åå åä½¿ç¨ | åªè¯» |
memory.stat | å åç»åç»è®¡ | anon, file, kernel |
memory.oom.group | OOM æ¶ç»æ | 0 æ 1 |
memory.events | OOM äºä»¶è®¡æ° | oom, oom_kill |
io.max | IO éå¶ | "8:0 rbps=10485760 wbps=10485760" |
io.weight | IO ç¸å¯¹æé | "default 100" |
pids.max | è¿ç¨æ°éå¶ | 1024 æ max |
pids.events | PID éå¶è§¦åè®¡æ° | max 42 |
/proc/pressure/{cpu,memory,io} | PSI ååææ | some avg10=0.50 ... |
pids.max æ¯é² fork bomb çæåä¸éé¸é¨ãWeb æå¡ãCI worker è¿ç±»ä¼çæ¶é´æèµ·å¤§éåè¿ç¨ç容å¨ï¼å»ºè®®æ pids.events ä¸èµ·ç¯ä¸ãPSIï¼Pressure Stall Informationï¼è¡¥çæ¯å¦ä¸ä¸ªè§è§ï¼èµæºä¹è®¸è¿æ²¡ææ»¡ï¼ä½çº¿ç¨å·²ç»å¼å§å 为 reclaimãthrottleãIO çå¾
èåé¡¿äºãåªç usageï¼ä¸ç pressureï¼å¾å®¹æéè¿å°¾å»¶è¿æ¶åçåå
ã
åä¸ãæéæåï¼Cgroup é ç½®ä¸çææä¹å
çº¿ä¸æè®©äººå´©æºçäºï¼ä½ ææè®¾äºéå¶ï¼ä½è¿ç¨å°±æ¯ä¸åæ§ãä¸é¢æ¯ä¸å¥å®ç¨çææ¥æ¸ åã
1. è¿ç¨å°åºå¨åªä¸ª cgroup éï¼
ç¬¬ä¸æ¥æ°¸è¿æ¯ç¡®è®¤è¿ç¨ççå¨ä½ ææç cgroup ä¸ï¼
$ cat /proc/<PID>/cgroup
0::/system.slice/docker-abc123.scope
妿è¾åºçè·¯å¾ä¸æ¯ä½ 设çé£ä¸ª cgroupï¼é£éå¶å½ç¶ä¸çæã常è§åå ï¼è¿ç¨è¢« systemd æå®¹å¨è¿è¡æ¶ç§»å°äºå«ç cgroupï¼æè
ä½ å cgroup.procs æ¶ç¨äºé误ç PIDã
2. æ§å¶å¨å¯ç¨äºåï¼
å
å建 cgroup ç®å½ä¸å¤ï¼æ§å¶å¨å¿
é¡»å¨ç¶ cgroup ç subtree_control 䏿¾å¼å¯ç¨ï¼
# æ¥çå½å cgroup å¯ç¨çæ§å¶å¨
$ cat /sys/fs/cgroup/mygroup/cgroup.controllers
cpu memory io
# æ¥çç¶ cgroup å¯ç¨äºåªäºæ§å¶å¨ç»åæ
$ cat /sys/fs/cgroup/cgroup.subtree_control
cpu memory
å¦æä½ æ³å¨ mygroup éç¨ io æ§å¶å¨ï¼ä½ç¶çº§ç cgroup.subtree_control éæ²¡æ ioï¼å io.max ä¼ç´æ¥æ¥éæè
æä»¶æ ¹æ¬ä¸åå¨ãä¿®å¤æ¹æ³ï¼
$ echo "+io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
3. "no internal processes" 踩å
Cgroups v2 çè§åï¼å¦æä¸ä¸ª cgroup ç subtree_control å¯ç¨äºä»»ä½æ§å¶å¨ï¼é£è¿ä¸ª cgroup æ¬èº«ä¸è½æè¿ç¨ã è¿ç¨åªè½å¾
å¨å¶åèç¹ã
å
¸åçç¶ï¼ä½ å¾ä¸ä¸ªæå cgroup çç®å½å cgroup.procsï¼å¾å° Device or resource busy é误ã
# é误示è
$ echo "+cpu" | sudo tee /sys/fs/cgroup/mygroup/cgroup.subtree_control
$ echo $$ | sudo tee /sys/fs/cgroup/mygroup/cgroup.procs
# echo: write error: Device or resource busy
è§£å³æ¹æ³ï¼æè¿ç¨æ¾å°å¶å cgroup éï¼è䏿¯æ¾å°å¯ç¨äº subtree_control çä¸é´èç¹ã
4. è°è¢« OOM æäºï¼æä¹æ¥ï¼
è¿ç¨çªç¶æ¶å¤±äºï¼æçæ¯ OOMï¼ä¸æ¥ç¡®è®¤ï¼
# ç¬¬ä¸æ¥ï¼æ¥ç cgroup ç OOM äºä»¶è®¡æ°
$ cat /sys/fs/cgroup/mygroup/memory.events
low 0
high 234
max 12
oom 3
oom_kill 3
oom_group_kill 1
# ç¬¬äºæ¥ï¼å
æ ¸æ¥å¿
$ dmesg | grep -i oom
[12345.678] memory cgroup out of memory: Killed process 9876 (myapp)
# ç¬¬ä¸æ¥ï¼systemd journalï¼å¦æç¨ systemd 管çï¼
$ journalctl -k | grep -i oom
memory.events æ¯æç²¾ç¡®ç â å®åªç»è®¡è¿ä¸ª cgroup ç OOM äºä»¶ï¼ä¸ä¼è¢«å
¶ä» cgroup çåªé³å¹²æ°ãoom_kill æ¯å®é
ææè¿ç¨ç次æ°ï¼oom æ¯è§¦å OOM æµç¨ç次æ°ï¼å¯è½åæ¶æåæ²¡æççæï¼ã
5. CPU è¢«èæµäºï¼æä¹ç¡®è®¤ï¼
åºç¨å»¶è¿é£åä½ CPU 使ç¨ç"çèµ·æ¥ä¸é«"ï¼å¾å¯è½æ¯ CFS å¸¦å®½èæµãæ¥ cpu.statï¼
$ cat /sys/fs/cgroup/mygroup/cpu.stat
usage_usec 23456789
user_usec 20000000
system_usec 3456789
nr_periods 12000
nr_throttled 3420
throttled_usec 171000000
å ³é®ç两个æ°åï¼
nr_throttledï¼è¢«èæµç卿æ°ã妿è¿ä¸ªæ°å卿ç»å¢é¿ï¼è¯´æcpu.maxç quota 设å¾å¤ªç´§ãthrottled_usecï¼ç´¯è®¡è¢«èæµçæ»æ¶é´ãthrottled_usec / nr_throttledå°±æ¯å¹³åæ¯æ¬¡è¢«èæµå¤ä¹ ã
妿 nr_throttled / nr_periods çæ¯ä¾è¶
è¿ 5â10%ï¼å°±è¯¥èèæ¾å®½ CPU éå¶äºï¼æè
å¹²èåªç¨ cpu.weight ä¸è®¾ cpu.maxï¼ã
6. systemd åä½ çè¿è¡æ¶ææ¶
è¿æ¯ä¸ªå¸¸è§ä½å®¹æè¢«å¿½ç¥çé®é¢ãsystemd ä¼ä¸»å¨ç®¡ç cgroup æ â 宿èªå·±å½æ cgroup å±çº§ç"管çå"ãå¦æä½ åæ¶ç¨ systemd åå¦ä¸ä¸ªè¿è¡æ¶ï¼æ¯å¦ç´æ¥ç¨ runcãæè èªå·±åçç¨åºï¼æä½å䏿£µ cgroup åæ ï¼å°±ä¼åºç°å²çªï¼
- systemd å¯è½æä½ æå¨å建ç cgroup 彿"ä¸è®¤è¯çåå¾"ç»æ¸ çæ
- ä½ çè¿è¡æ¶åäº
subtree_controlï¼systemd ä¹åäºï¼äºç¸è¦ç - systemd ç scope/slice æºå¶ä¼æè¿ç¨ç§»å°å®è®¤ä¸º"æ£ç¡®"çä½ç½®
è§£å³æè·¯ï¼
- å¦æä½ ç¨ Docker/containerd/CRI-Oï¼è®©å®ä»¬å systemd ååï¼ä¸è¦æå¨æä½å®ä»¬ç®¡çç cgroup åæ ã
- å¦æä½ èªå·±ç®¡ç cgroupï¼å¨ systemd 管çèå´ä¹å¤åå»ºä½ çåæ ï¼æè
ç¨
systemd-run --scope让 systemd ç¥éä½ ç cgroup çåå¨ã - ææ¥æ¹å¼ï¼
systemctl statusåsystemd-cglså¯ä»¥çå° systemd è§è§ä¸ç cgroup æ ï¼å¯¹æ¯cat /proc/<PID>/cgroupçå®é ä½ç½®ã
åäºã弿¾é®é¢
- K8s æ¯å¦åºé»è®¤è®¾ CPU limitï¼CFS å¸¦å®½èæµå¨ CPU ç©ºé²æ¶ä»çå¾
ä¸ä¸ periodï¼ç¬¬ä¸èï¼ââ社åºé¿æäºè®ºãrequest-only vs request+limitãï¼æ åä¸è®ºæç»è®ºï¼ç产éç¨
cpu.statä¸å»¶è¿ SLO èªè¯ã memory.highä¸å®¹å¨ç¼æï¼systemd åçæ¯æMemoryHigh=ï¼è K8s æ å spec æªæ´é²çä»·åæ®µï¼è½¯èæµè½å¦ç± CRI/runtime ç»ä¸æ³¨å ¥ï¼ä»éçæ¬ä¸åè¡çååã
Aitishiku.com