(2)Cgroups

7771 ワード

Cgroupsについて
前回のnamespaceは主に環境隔離について、このCgroupsは主に隔離環境を制限し、隔離された空間が互いに資源を奪うことを防止すると述べた.
Cgroupsもlinuxのカーネル技術であり、プロセスとそのサブプロセスのセットに対するリソース制限、制御、統計機能を提供しています.これらのリソースには、cpu、メモリ、ストレージ、ネットワークなどが含まれます.
Cgroupsの3つのコンポーネント、cgroup、subsystem、hierarchy.まずcgroupはプロセスパケット管理のメカニズムであり、1つのCgroupにはプロセスのセットが含まれており、このcgroupに対して様々なsubsystemパラメータを追加して、プロセスのセットとsubsystemのセットを関連付けることができます.次にsubsystemは、リソース管理制御のモジュールのセットです.(例えばblkioはブロックデバイスのIO制御を設定することができ、memoryはプロセスのメモリ占有を制御するために使用される...)最後にhierarchyは、Cgroupのセットを木状の構造に直列に接続する機能で、この構造Cgroupsによって継承することができます.
手動でkernelインタフェースを呼び出してCgroupsを感じます
1 hierarchy(Cgroupツリー)を作成してマウント
[root@iZ2zebynirz2ac5eron661Z ~]# mkdir cgroup-test  #    hierarchy   
[root@iZ2zebynirz2ac5eron661Z ~]# mount -t cgroup -o none,name=cgroup-test cgroup-test ./cgroup-test #    hierarchy
[root@iZ2zebynirz2ac5eron661Z ~]# ls ./cgroup-test/ #              
cgroup.event_control  cgroup.procs  notify_on_release  release_agent  tasks

2ルートノードに2つのサブCgroupを拡張
[root@iZ2zebynirz2ac5eron661Z cgroup-test]# mkdir cgroup-1
[root@iZ2zebynirz2ac5eron661Z cgroup-test]# mkdir cgroup-2
[root@iZ2zebynirz2ac5eron661Z cgroup-test]# tree
.
├── cgroup-1
│   ├── cgroup.event_control
│   ├── cgroup.procs
│   ├── notify_on_release
│   └── tasks
├── cgroup-2
│   ├── cgroup.event_control
│   ├── cgroup.procs
│   ├── notify_on_release
│   └── tasks
├── cgroup.event_control
├── cgroup.procs
├── notify_on_release
├── release_agent
└── tasks

Cgroupのディレクトリの下でファイルを作成すると、kernelはこのCgroupのサブCgroupとしてファイルをマークし、Cgroupのプロパティを継承することがわかります.
3 Cgroupに移動プロセスを追加する1つのプロセスCgroupsのhierarchyでは、1つのCgroupノードにのみ存在し、システムのすべてのプロセスはデフォルトでルートノードに存在し、移動したCgroupノードのtasksファイルにプロセスIDを書き込むことでそのCgroupノードに移動できます.
[root@iZ2zebynirz2ac5eron661Z cgroup-1]# echo $$
18091
[root@iZ2zebynirz2ac5eron661Z cgroup-1]# cat /proc/18091/cgroup 
1:name=cgroup-test:/
[root@iZ2zebynirz2ac5eron661Z cgroup-1]#  sh -c "echo $$ >>tasks"
[root@iZ2zebynirz2ac5eron661Z cgroup-1]# cat /proc/18091/cgroup 
1:name=cgroup-test:/cgroup-1
[root@iZ2zebynirz2ac5eron661Z cgroup-1]# 

現在のプロセスがcgroup-1に移動していることがわかります.
4 subsystemでCgroupを制限するプロセスのリソース
PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                      
 7644 bozhon    20   0  211980 205620    748 R 100.0  2.6   1:55.63 stress                                                                                                       
bozhon@bozhon:~$ mkdir test-limit-memory && cd test-limit-memory
bozhon@bozhon:~/test-limit-memory$ cd /sys/fs/cgroup/memory
bozhon@bozhon:/sys/fs/cgroup/memory$ sudo mkdir test-limit-memory && cd test-limit-memory
[sudo] password for bozhon: 
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ sudo sh -c "echo "100m">memory.limit_in_bytes"
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ sudo sh -c "echo $$ >tasks"
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ stress --vm-bytes 200m --vm-keep -m 1
stress: info: [7674] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
   
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ stress --vm-bytes 200m --vm-keep -m 1
stress: info: [7676] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
   
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ stress --vm-bytes 100m --vm-keep -m 1
stress: info: [7678] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
   
bozhon@bozhon:/sys/fs/cgroup/memory/test-limit-memory$ stress --vm-bytes 10m --vm-keep -m 1
stress: info: [7680] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd

制限100 Mを使用すると、100 M以上のプロセスが殺されることがわかります.
Cgroupsのdockerでの運用
02613 ec 46397 ee 46 a 6 a 9 bd 7 e 62 f 78 b 1 bd 89 f 15 f 07 b 898 f 3 c 8553 db 4243 b 5346 fはある容器IDである
bozhon@bozhon:~$ cd /sys/fs/cgroup/memory/docker/02613ec46397ee46a6a9bd7e62f78b1bd89f15f07b898f3c8553db4243b5346f/
bozhon@bozhon:/sys/fs/cgroup/memory/docker/02613ec46397ee46a6a9bd7e62f78b1bd89f15f07b898f3c8553db4243b5346f$ ls
cgroup.clone_children  memory.kmem.failcnt             memory.kmem.tcp.limit_in_bytes      memory.max_usage_in_bytes        memory.soft_limit_in_bytes  notify_on_release
cgroup.event_control   memory.kmem.limit_in_bytes      memory.kmem.tcp.max_usage_in_bytes  memory.move_charge_at_immigrate  memory.stat                 tasks
cgroup.procs           memory.kmem.max_usage_in_bytes  memory.kmem.tcp.usage_in_bytes      memory.numa_stat                 memory.swappiness
memory.failcnt         memory.kmem.slabinfo            memory.kmem.usage_in_bytes          memory.oom_control               memory.usage_in_bytes
memory.force_empty     memory.kmem.tcp.failcnt         memory.limit_in_bytes               memory.pressure_level            memory.use_hierarchy
bozhon@bozhon:/sys/fs/cgroup/memory/docker/02613ec46397ee46a6a9bd7e62f78b1bd89f15f07b898f3c8553db4243b5346f$ cat memory.limit_in_bytes 
9223372036854771712

Cgroupsによるコンテナリソースの制限をgo言語で実現
package main

import (
    "os"
    "fmt"
    "syscall"
    "os/exec"
    "path"
    "io/ioutil"
    "strconv"
)
//   memory subsystem  hierarchy       
const cgroupMemoryHierarchyMount  ="/sys/fs/cgroup/memory"
func main() {
    if os.Args[0] == "/proc/self/exe"{
        //    
        fmt.Printf("current pid %d",syscall.Getpid())
        fmt.Println()
        cmd := exec.Command("sh","-c",`stress --vm-bytes 200m --vm-keep -m  1` )
        cmd.SysProcAttr = &syscall.SysProcAttr{}

        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr

        if err:= cmd.Run(); err!=nil{
            fmt.Println(err)
            os.Exit(1)
        }
    }

    cmd := exec.Command("/proc/self/exe")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS |syscall.CLONE_NEWPID|syscall.CLONE_NEWNS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err:= cmd.Run(); err!=nil{
        fmt.Println(err)
        os.Exit(1)
    }else{
        //  fork              pid
        fmt.Printf("%v",cmd.Process.Pid)
        //          memory subsystem Hierachy   cgroup
        os.Mkdir(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit"),0755)
        //          cgroup 
        ioutil.WriteFile(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit","memory.limit_in_bytes"),
            []byte(strconv.Itoa(cmd.Process.Pid)),0644)
        //  cgroup    
        ioutil.WriteFile(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit","memory.limit_in_bytes"),
            []byte("100m"),0644)
    }
    cmd.Process.Wait()


}


20%のメモリ(1 G*20%=100 M)が消費されていることがわかり、制限が成功したことを示しています.
 34192 maojian+  20   0   41820   3764   3120 R  4.3  0.4   0:00.40 top
     1 root      20   0  119744   5844   4012 S  0.0  0.6   0:02.73 systemd
     2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
     3 root      20   0       0      0      0 S  0.0  0.0   0:01.80 ksoftirqd/0
     5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
     7 root      20   0       0      0      0 S  0.0  0.0   0:00.70 rcu_sched
     8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
     9 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
    10 root      rt   0       0      0      0 S  0.0  0.0   0:00.03 watchdog/0
    11 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs