【mydocker】实现简单的容器demo--容器隔离与资源控制[ 2 ]

一)、简单实现run、init命令

1.主要使用urfave/cli来实现命令行工具

main.go:创建cli实例、设置cli名字与用途、定义cli应用命令列表,将命令行输入的参数带入运行文件。

main_command.go文件:设置initCommand、runCommand为cli.Command类型:

其中属性Flags设置了命令的可选参数数组;

Action则为具体执行函数:

  • ti命令作用是将os/exec包的cmd对象的输入输出连接到终端,方便与命令交互
  • runcommand:通过执行、/proc/self/exe调用当前文件创建出新的进程,第一个参数为init,exec.cmd.start会执行资源更新。
  • initcommand:容器执行的第一个进程,使用mount去挂载proc文件系统,便于以后查看文件;syscall.exec执行了内核的execve调用,作用是执行当前的filename对应的程序,覆盖当前进程的镜像、数据、堆栈信息,使得PID为1的进程是用户命令。

效果如下:
    效果如下:

bug:在第二次进入容器时出现panic:

原因:代码中会讲容器进程的proc信息挂载为proc文件系统,在mydocker init进行,但是退出后容器进程消失,对应进程不存在,但是linux中mount namespace 是share by default 所以说宿主机上的proc目录被影响,执行/proc/self/exe出错,每次执行都会破坏/proc

执行:
sudo mount -t proc proc /proc

或者修改代码:在挂载之前,将所有mount事件显示的指定为private即可避免外泄。

syscall.Mount("","/","",system.MS_PRIVATE|syscall.MS_REC,"")

2.优化参数传递方式-匿名管道

介绍:匿名管道是一种特殊的文件描述符,用父进程与子进程之间创建通信通道

特点:数据是单向的、管道缓冲区固定,一般是4kb,管道被写满时写进程阻塞,管道为空时读进程阻塞。

使用:readPipe,writePipe,err := os.Pipe()

父进程把数据写入到writePipe,子进程从readPipe数据读。

应用

1.在创建子进程之前将readPipe带入。

cmd.ExtraFiles = []*os.File{readPipe}

2.子进程创建并启动后,将命令参数都写入写管道。

3.子进程读取管道数据:

读取进程的第四个文件描述符:readPipe第一步携带的。

pipe := os.NewFile(uintptr(3),"pipe")

message,err := io.ReadAll(pipe)

此时的run流程:创建exec.cmd实例、执行程序本身+init资源初始化、子进程携带管道返回、启动,发送数据

init流程:读取管道的命令数据,mount挂载proc,调用execve覆盖当前进程信息。

3.基于cgroups实现资源限制

1.给run命令的flag加mem、cpu、cpuset,从命令行中解析参数并传给subsystem以配置cgroup

2.各个subsystem实现对cgroup的某资源控制

3.cgroupManger来管理每一个subsystem

1.	给对应路径的cgroup创建cgroupManager

2.根据资源配置信息循环运行subsystem对该cgroup的限制

3.在子进程创建后创建cgroup ls

bug:命令行设置了mem标签来限制内存大小,但是不起作用?

原因:我的内核使用的cgroup版本v2没有memory.limit_in_bytes文件
解决
通过修改文件并重启,可以切换为cgoup v1版本

sudo nano /etc/default/grub

//修改值:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=0 systemd.unified_cgroup_hierarchy=0"
sudo uodate-grub

重启即可

//再次编译运行程序:
 sudo ./myDocker run -it -mem 3m /bin/sh

发现内存限制仍然没有被应用,但是cgroup的memory.limit_in_bytes文件值已经修改为我们键入的值。
原因:程序进程使用了swap空间,memory.swappiness文件值为0-100数值越高,使用swap空间的权重越高。

解决:

sudo nano memory.swappiness 
修改值为0即可

重新编译运行即可
效果如下:
在这里插入图片描述

4.基于cgroup的v2版本实现资源控制

(1).怎么查看自己系统内核的cgroup?
stat -fc %T /sys/fs/cgroup/
结果为tmpfs内核的cgoup版本为v1,为cgroup2fs的内核的cgroup版本为v2
(2.).怎么切换内核的cgoup版本?
修改/etc/default/grub文件,将值修改为下方的任一版本即可。
//v1:
GRUB_CMDLINE_LINUX=“cgroup_enable=memory swapaccount=0 systemd.unified_cgroup_hierarchy=0”
//v2
GRUB_CMDLINE_LINUX=“”
sudo uodate-grub
重启即可
(3).cgroup v2的修改subsystem配置信息的文件
在这里插入图片描述

以 cpu 为例,只需要在 cpu.max 中添加具体限制即可,就像这样:

echo 5000 10000 > cpu.max

含义是在10000的CPU时间周期内,有5000是分配给本cgroup的,也就是本cgroup管理的进程在单核CPU上的使用率不会超过50%
(4).v1与v2的对比:
v1:cgroup的cgroup subsystem的各个信息收录在单独的文件目录中,每个目录就代表了一个 cgroup subsystem,比如要限制 cpu 则需要到 cpu 目录下创建子目录(树),用户空间最后管理着多个非常类似的 hierarchy,
v2:cgroup将统一/sys/fs/cgroup/GROUPNAME中的树,当进程加入cgroup是会被配置所有的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值