ooouuuooouuu 2018-11-14
Namespace是用來實現進程之間的隔離,但是并没有限制其空间的大小。如果想要限制一个进程可以使用的空间,保证各个进程之间不会互相争抢就要用到 Cgroups。
Linux Cgroups(Linux Control Groups)提供了对一组进程及将来子进程的资源限制、控制、统计的能力。这些资源包括cpu、内存、存储、网络 等。通过Cgroups,可以方便的控制某个进程占用的资源,并可以实施监控和统计信息。
cgroup 是对进程分组管理的一种机制,一个cgroup包含一组进程,并可以在这个cgroup上增加Linux subsystem的各种参数配置,将一组进程和一 组subsystem的系统参数关联起来。
subsystem 是一组资源控制的模块。包含以下几项。
每个subsystem会关联到定义的cgroup,并对这个cgroup中的进程做限制和控制。这些subsystem是逐步合并到内核中的,可以安装apt-get install cgroup-bin 然后通过 lssubsys -a 查看
前面说道Cgroups中的hierarchy是一种树状结构,Kernel为了对Cgroups的配置更直观,也会显示为树状结构。下面进行实例,了解如何操作Cgroups。
首先创建并挂在一个hierarchy(cgroup树),如下.
leon@leon:~$ mkdir cgroup-test这些文件就是这个hierarchy中cgroup根节点的配置项,上面这些文件含义如下。
然后创建刚才建立的hierarchy上cgroup根节点中扩展出的两个子cgroup。
可以看到创建子文件夹的同时,Kernel会标记这个cgroup的子cgroup,他们会继承父cgroup的属性。
可以看到当前进程已经被添加到cgroup-1中了。**第一行**
通过subsystem限制cgroup进程的资源 上面的hierarchy没有关系任何的subsystem,所以没有限制cgroup占用的系统资源。本质系统默认为subsystem创建了hierarchy,比如memory的hierarchy。
可以看到/sys/fs/cgroup/memory目录挂载在memory subsystem的hierarchy上。下面进入到memory目录下创建cgroup。限制内存。
这样就创建成功,并添加了内存使用的限制。
可以看到9752 使用内存最大为100M
Docker是通过Cgroups实现容器资源的限制和监控。
可以看到最大限制是134217728 使用的是1970176.这些都是我们在/sys/fs/cgroup/memory中找到的。由此可见docker本质上也是这样做的。
在Namespace的基础之上增加Cgroup的限制,使其具有限制内存的功能。
package main
import (
"os"
"os/exec"
"log"
"syscall"
"path"
"fmt"
"io/ioutil"
"strconv"
)
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" ,"strees --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.Start(); err !=nil{
fmt.Println("error", err)
os.Exit(1)
}else {
//获取fork的进程pid
fmt.Printf("%v" ,cmd.Process.Pid)
// 在系统中默认创建挂在了memory subsystem的hierarchy上创建Cgroup
os.Mkdir(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit"),0755)
// 将容器加入到这个Cgroup中
ioutil.WriteFile(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit","tasks"),[]byte(strconv.Itoa(cmd.Process.Pid)),0644)
//限制cgroup的使用
ioutil.WriteFile(path.Join(cgroupMemoryHierarchyMount,"testmemorylimit","memory.limit_in_bytes"),[]byte("100m"),0644)
}
cmd.Process.Wait()
}
通过top就可以查看。