Cgroup
linux Cgroup 提供了对一组进程及子进程的资源限制,控制和统计的能力,这些资源包括 CPU,内存,存储,网络等。通过 Cgroup,可以方便的限制某个进程的资源占用,并且可以实时监控进程和统计信息。
Cgroup 完成资源限制主要通过下面三个组件
- cgroup: 是对进程分组管理的一种机制
- subsystem: 是一组资源控制的模块
- hierarchy: 把一组 cgroup 串成一个树状结构 (可让其实现继承)
Cgroup使用
#创建一个用来存放挂载点的文件夹
mkdir cgroup-demo
#挂载 hierarchy
mount -t cgroup -o none,name=cgroup-demo cgroup-demo ./cgroup-demo
一旦我们挂载了 hierarchy,那么就会在这个文件夹中生成一些默认文件
大致解释下这几个文件的作用,主要是这个 task 文件
- cgroup.clone_children:cpuset 的 subsystem 会读取该文件,如果该文件里面的值为 1 的话,那么子 cgroup 将会继承父 cgroup 的 cpuset 配置
- cgroup.procs:记录了树中当前节点 cgroup 中的进程组 ID
- task: 标识该 cgroup 下的进程 ID,如果将某个进程的 ID 写到该文件中,那么便会将该进程加入到当前的 cgroup 中。
只要在挂载了 hierarchy 的文件夹下,新建一个新的文件夹,那么该新的文件夹会被 kernel 自动标记为该 cgroup 的子 group
cd cgroup-demo
mkdir cgroup1
可以看到,我们新建文件夹之后,文件夹里面会自动生成一些默认的文件,这个 cgroup1 就是 cgroup-demo 的子 cgroup,默认情况下,他会继承父cgroup 的配置。
通过 subsystem 限制 cgroup 中进程的资源
上面创建的 hierarchy 并没有关联到任何的 subsystem,所以没办法通过上面的 hierarchy 中的 cgroup 节点来限制进程的资源占用,其实系统默认已经为每个 subsystem 创建了一个默认的 hierarchy,它在 Linux 的 /sys/fs/cgroup 路径下
如果我们想限制某个进程 ID 的内存,那么就在 /sys/fs/cgroup/memory 文件夹下创建一个限制 mermory 的 cgroup,创建方式和上面一样,只要创建一个文件夹即可,kernel 自动把该文件夹标记为一个 cgroup
cd /sys/fs/cgroup/memory
mkdir cgroup-demo-memory
可以看到该文件下,自动给我们创建出来了很多限制资源文件,我们只要将进程ID
写到该文件夹下的 task文件中,然后修改其 meory.limit_in_bytes 的文件,就能达到限制该进程的内存使用。
go语言使用Cgroup
//go语言实现Cgroup
package main
import (
"fmt"
"io/ioutil" //io处理
"os" //操作系统接口
"os/exec" //执行外部命令
"path" //斜杠分隔的路径的实用操作
"strconv" //基本数据类型和其字符串表示的相互转换
"syscall" //包系统调用,底层系统调用
)
const (
// 挂载了 memory subsystem的hierarchy的根目录位置
cgroupMemeoryHierarchMount = "/sys/fs/cgroup/memory"
)
func main() {
if os.Args[0] == "/proc/self/exe" {
//容器进程
fmt.Printf("current pid %d n", syscall.Getegid())
//执行命令
//首先要保证宿主机中有stress命令,快速模拟CPU、内存、磁盘消耗
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 {
panic(err)
}
}
cmd := exec.Command("/proc/self/exe")
//隔离uts,pid,ns
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
//直接运行,不用等待结束
err := cmd.Start()
if err != nil {
panic(err)
}
//得到fork出来进程映射在外部空间的pid
fmt.Printf("%+v", cmd.Process.Pid)
//创建子cgroup,拼接路径
newCgroup := path.Join(cgroupMemeoryHierarchMount, "cgroup-demo-memory")
if err := os.Mkdir(newCgroup, 0755); err != nil {
panic(err)
}
//将容器进程放到子cgroup中
//将进程名通过字节IO写入到task中
if err := ioutil.WriteFile(path.Join(newCgroup, "task"), []byte(strconv.Itoa(cmd.Process.Pid)), 0644); err != nil {
panic(err)
}
//限制cgroup的内存使用
//将内存显示100m写入到memory.limit_in_bytes中
if err := ioutil.WriteFile(path.Join(newCgroup, "memory.limit_in_bytes"), []byte("100m"), 0644); err != nil {
panic(err)
}
//等待进程结束
cmd.Process.Wait()
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net