自我实现部分回忆
在client中添加cgroup命令
- 在api/client中添加cgroup.go,接受的参数为id和ioweight,命令的形式如下
--
- 首先根据id获取正在运行中的container的完整的config,将之和ioweight一起再次提交给server进行修改
在server中加入关于修改cgroup的post函数
- api/server/server.go中结尾的路由部分添加关于changecgroup的代码
- 实现上述函数,该函数会调用daemon中的相关函数,如下
var hostConfig *runconfig.HostConfig
……
blkioWeight ,err := strconv.ParseInt(r.Form.Get("blkio-weight"),10,64)
if err != nil {
return err
}
hostConfig.BlkioWeight = blkioWeight
if err := s.daemon.ContainerChangeCgroup(vars["name"], hostConfig); err != nil {
return err
}
在daemon中实现相关函数
- 在daemon中增加cgroup.go,在其中实现ContainerChangeCgroup函数
- 该函数会调用daemon/container.go中的函数
if err := container.ChangeCgroup(); err != nil {
return fmt.Errorf("Cannot change container cgroup %s: %s", name, err)
}
在container中实现相关函数
- 在daemon/container.go中增加ChangeCgroup函数
- 这个函数会调用driver中的函数
container.command.Resources.BlkioWeight = container.hostConfig.BlkioWeight
if err := container.daemon.execDriver.Set(container.command)
return err
}
driver的各种修改
- 首先要注意的是,driver的interface本身并没有提供有关修改的函数,所以我们增加了一个函数接口
Set(c *Command) error
,即在daemon/execdriver/driver.go中增加 - 但因为这个是一个interface,所以不管是lxc还是native都需要实现这个函数
- 在daemon/execdriver/lxc/driver.go中,我们实现了一个空函数,暂且不管
- 在daemon/execdriver/native/driver.go中我们实现了一个真正有用的函数
func (d *Driver) Set(c *execdriver.Command) ( error) {
d.Lock()
active := d.activeContainers[c.ID]
d.Unlock()
if active == nil {
return fmt.Errorf("active container for %s does not exist", c.ID)
}
cont, _ := d.factory.Load(c.ID)
config := cont.Config()
config.Cgroups.BlkioWeight = c.Resources.BlkioWeight
return active.Set(config)
}
- 最后的Set调用的是venfor/src/github.com/opencontainers/runc/libcontainer/container.go的Set接口,无论是谁实现的,至少他有用。
libcontainer部分分析
systemd的部分
- 一般上一节最后调用的都是libcontainer/container_linux.go中实现的Set,其调用了libcontainer/cgroup/cgroup.go中Manager中的Set家口
- 因为ubuntu或者其他linux都默认有systemd,所以一般上一节最后调用的都是libcontainer/cgroups/systemd/apply_systemd.go中实现的Set,其代码很简单,是这个样子的
var subsystems = map[string]subsystem{
"devices": &fs.DevicesGroup{},
"memory": &fs.MemoryGroup{},
"cpu": &fs.CpuGroup{},
"cpuset": &fs.CpusetGroup{},
"cpuacct": &fs.CpuacctGroup{},
"blkio": &fs.BlkioGroup{},
"hugetlb": &fs.HugetlbGroup{},
"perf_event": &fs.PerfEventGroup{},
"freezer": &fs.FreezerGroup{},
"net_prio": &fs.NetPrioGroup{},
"net_cls": &fs.NetClsGroup{},
}
func (m *Manager) Set(container *configs.Config) error {
for name, path := range m.Paths {
sys, ok := subsystems[name]
if !ok || !cgroups.PathExists(path) {
continue
}
if err := sys.Set(path, container.Cgroups)
return err
}
}
return nil
}
- 可以看出Set调用了libcontainer/cgroups/fs中的各种函数,比如blkio.go,它将我们需要的blkio-weight写入了相关的配置文件。根据系统的不同,其在系统中的位置各有不用,但是在容器中的位置是/sys/fs/cgroup/blkio/blkio.weight