增加Docker cgroup命令

自我实现部分回忆

在client中添加cgroup命令

  1. api/client中添加cgroup.go,接受的参数为id和ioweight,命令的形式如下
docker cgroup 123 --ioweight 300
  1. 首先根据id获取正在运行中的container的完整的config,将之和ioweight一起再次提交给server进行修改

在server中加入关于修改cgroup的post函数

  1. api/server/server.go中结尾的路由部分添加关于changecgroup的代码
  2. 实现上述函数,该函数会调用daemon中的相关函数,如下
var hostConfig *runconfig.HostConfig
……//获取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中实现相关函数

  1. daemon中增加cgroup.go,在其中实现ContainerChangeCgroup函数
  2. 该函数会调用daemon/container.go中的函数
//在此之前已经将hostconfig更新至container中
if err := container.ChangeCgroup(); err != nil {
    return fmt.Errorf("Cannot change container cgroup %s: %s", name, err)
}

在container中实现相关函数

  1. daemon/container.go中增加ChangeCgroup函数
  2. 这个函数会调用driver中的函数
container.command.Resources.BlkioWeight = container.hostConfig.BlkioWeight
if err := container.daemon.execDriver.Set(container.command); err != nil {
    return err
}

driver的各种修改

  1. 首先要注意的是,driver的interface本身并没有提供有关修改的函数,所以我们增加了一个函数接口Set(c *Command) error,即在daemon/execdriver/driver.go中增加
  2. 但因为这个是一个interface,所以不管是lxc还是native都需要实现这个函数
  3. daemon/execdriver/lxc/driver.go中,我们实现了一个空函数,暂且不管
  4. 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)
}
  1. 最后的Set调用的是venfor/src/github.com/opencontainers/runc/libcontainer/container.go的Set接口,无论是谁实现的,至少他有用。

libcontainer部分分析

systemd的部分

  1. 一般上一节最后调用的都是libcontainer/container_linux.go中实现的Set,其调用了libcontainer/cgroup/cgroup.go中Manager中的Set家口
  2. 因为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); err != nil {
            return err
        }
    }
    return nil
}
  1. 可以看出Set调用了libcontainer/cgroups/fs中的各种函数,比如blkio.go,它将我们需要的blkio-weight写入了相关的配置文件。根据系统的不同,其在系统中的位置各有不用,但是在容器中的位置是/sys/fs/cgroup/blkio/blkio.weight

你可能感兴趣的:(coding)