mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Add --cpus support for docker update
				
					
				
			This fix tries to address the issue raised in 31032 where it was not possible to specify `--cpus` for `docker update`. This fix adds `--cpus` support for `docker update`. In case both `--cpus` and `--cpu-period/--cpu-quota` have been specified, an error will be returned. Related docs has been updated. Integration tests have been added. This fix fixes 31032. This fix is related to 27921, 27958. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
		
							parent
							
								
									30cdabd13f
								
							
						
					
					
						commit
						6102243692
					
				
					 6 changed files with 74 additions and 4 deletions
				
			
		| 
						 | 
					@ -28,6 +28,7 @@ type updateOptions struct {
 | 
				
			||||||
	memorySwap         opts.MemSwapBytes
 | 
						memorySwap         opts.MemSwapBytes
 | 
				
			||||||
	kernelMemory       opts.MemBytes
 | 
						kernelMemory       opts.MemBytes
 | 
				
			||||||
	restartPolicy      string
 | 
						restartPolicy      string
 | 
				
			||||||
 | 
						cpus               opts.NanoCPUs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nFlag int
 | 
						nFlag int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +67,9 @@ func NewUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
				
			||||||
	flags.Var(&opts.kernelMemory, "kernel-memory", "Kernel memory limit")
 | 
						flags.Var(&opts.kernelMemory, "kernel-memory", "Kernel memory limit")
 | 
				
			||||||
	flags.StringVar(&opts.restartPolicy, "restart", "", "Restart policy to apply when a container exits")
 | 
						flags.StringVar(&opts.restartPolicy, "restart", "", "Restart policy to apply when a container exits")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags.Var(&opts.cpus, "cpus", "Number of CPUs")
 | 
				
			||||||
 | 
						flags.SetAnnotation("cpus", "version", []string{"1.29"})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +101,7 @@ func runUpdate(dockerCli *command.DockerCli, opts *updateOptions) error {
 | 
				
			||||||
		CPUQuota:           opts.cpuQuota,
 | 
							CPUQuota:           opts.cpuQuota,
 | 
				
			||||||
		CPURealtimePeriod:  opts.cpuRealtimePeriod,
 | 
							CPURealtimePeriod:  opts.cpuRealtimePeriod,
 | 
				
			||||||
		CPURealtimeRuntime: opts.cpuRealtimeRuntime,
 | 
							CPURealtimeRuntime: opts.cpuRealtimeRuntime,
 | 
				
			||||||
 | 
							NanoCPUs:           opts.cpus.Value(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	updateConfig := containertypes.UpdateConfig{
 | 
						updateConfig := containertypes.UpdateConfig{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,12 +286,33 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
 | 
				
			||||||
	// update resources of container
 | 
						// update resources of container
 | 
				
			||||||
	resources := hostConfig.Resources
 | 
						resources := hostConfig.Resources
 | 
				
			||||||
	cResources := &container.HostConfig.Resources
 | 
						cResources := &container.HostConfig.Resources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate NanoCPUs, CPUPeriod, and CPUQuota
 | 
				
			||||||
 | 
						// Becuase NanoCPU effectively updates CPUPeriod/CPUQuota,
 | 
				
			||||||
 | 
						// once NanoCPU is already set, updating CPUPeriod/CPUQuota will be blocked, and vice versa.
 | 
				
			||||||
 | 
						// In the following we make sure the intended update (resources) does not conflict with the existing (cResource).
 | 
				
			||||||
 | 
						if resources.NanoCPUs > 0 && cResources.CPUPeriod > 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Conflicting options: Nano CPUs cannot be updated as CPU Period has already been set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if resources.NanoCPUs > 0 && cResources.CPUQuota > 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Conflicting options: Nano CPUs cannot be updated as CPU Quota has already been set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if resources.CPUPeriod > 0 && cResources.NanoCPUs > 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Conflicting options: CPU Period cannot be updated as NanoCPUs has already been set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if resources.CPUQuota > 0 && cResources.NanoCPUs > 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if resources.BlkioWeight != 0 {
 | 
						if resources.BlkioWeight != 0 {
 | 
				
			||||||
		cResources.BlkioWeight = resources.BlkioWeight
 | 
							cResources.BlkioWeight = resources.BlkioWeight
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if resources.CPUShares != 0 {
 | 
						if resources.CPUShares != 0 {
 | 
				
			||||||
		cResources.CPUShares = resources.CPUShares
 | 
							cResources.CPUShares = resources.CPUShares
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if resources.NanoCPUs != 0 {
 | 
				
			||||||
 | 
							cResources.NanoCPUs = resources.NanoCPUs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if resources.CPUPeriod != 0 {
 | 
						if resources.CPUPeriod != 0 {
 | 
				
			||||||
		cResources.CPUPeriod = resources.CPUPeriod
 | 
							cResources.CPUPeriod = resources.CPUPeriod
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,8 @@
 | 
				
			||||||
package daemon
 | 
					package daemon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/docker/docker/api/types/container"
 | 
						"github.com/docker/docker/api/types/container"
 | 
				
			||||||
	"github.com/docker/docker/libcontainerd"
 | 
						"github.com/docker/docker/libcontainerd"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -11,8 +13,13 @@ func toContainerdResources(resources container.Resources) libcontainerd.Resource
 | 
				
			||||||
	var r libcontainerd.Resources
 | 
						var r libcontainerd.Resources
 | 
				
			||||||
	r.BlkioWeight = uint64(resources.BlkioWeight)
 | 
						r.BlkioWeight = uint64(resources.BlkioWeight)
 | 
				
			||||||
	r.CpuShares = uint64(resources.CPUShares)
 | 
						r.CpuShares = uint64(resources.CPUShares)
 | 
				
			||||||
	r.CpuPeriod = uint64(resources.CPUPeriod)
 | 
						if resources.NanoCPUs != 0 {
 | 
				
			||||||
	r.CpuQuota = uint64(resources.CPUQuota)
 | 
							r.CpuPeriod = uint64(100 * time.Millisecond / time.Microsecond)
 | 
				
			||||||
 | 
							r.CpuQuota = uint64(resources.NanoCPUs) * r.CpuPeriod / 1e9
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							r.CpuPeriod = uint64(resources.CPUPeriod)
 | 
				
			||||||
 | 
							r.CpuQuota = uint64(resources.CPUQuota)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	r.CpusetCpus = resources.CpusetCpus
 | 
						r.CpusetCpus = resources.CpusetCpus
 | 
				
			||||||
	r.CpusetMems = resources.CpusetMems
 | 
						r.CpusetMems = resources.CpusetMems
 | 
				
			||||||
	r.MemoryLimit = uint64(resources.Memory)
 | 
						r.MemoryLimit = uint64(resources.Memory)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ keywords: "API, Docker, rcli, REST, documentation"
 | 
				
			||||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept a `rollback` value for `FailureAction`.
 | 
					* `POST /services/create` and `POST /services/(id or name)/update` now accept a `rollback` value for `FailureAction`.
 | 
				
			||||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept an optional `RollbackConfig` object which specifies rollback options.
 | 
					* `POST /services/create` and `POST /services/(id or name)/update` now accept an optional `RollbackConfig` object which specifies rollback options.
 | 
				
			||||||
* `GET /services` now supports a `mode` filter to filter services based on the service mode (either `global` or `replicated`).
 | 
					* `GET /services` now supports a `mode` filter to filter services based on the service mode (either `global` or `replicated`).
 | 
				
			||||||
 | 
					* `POST /containers/(name)/update` now supports updating `NanoCPUs` that represents CPU quota in units of 10<sup>-9</sup> CPUs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## v1.27 API changes
 | 
					## v1.27 API changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,12 +21,13 @@ Usage:  docker update [OPTIONS] CONTAINER [CONTAINER...]
 | 
				
			||||||
Update configuration of one or more containers
 | 
					Update configuration of one or more containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Options:
 | 
					Options:
 | 
				
			||||||
      --blkio-weight value          Block IO (relative weight), between 10 and 1000
 | 
					      --blkio-weight uint16         Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
 | 
				
			||||||
      --cpu-period int              Limit CPU CFS (Completely Fair Scheduler) period
 | 
					      --cpu-period int              Limit CPU CFS (Completely Fair Scheduler) period
 | 
				
			||||||
      --cpu-quota int               Limit CPU CFS (Completely Fair Scheduler) quota
 | 
					      --cpu-quota int               Limit CPU CFS (Completely Fair Scheduler) quota
 | 
				
			||||||
  -c, --cpu-shares int              CPU shares (relative weight)
 | 
					 | 
				
			||||||
      --cpu-rt-period int           Limit the CPU real-time period in microseconds
 | 
					      --cpu-rt-period int           Limit the CPU real-time period in microseconds
 | 
				
			||||||
      --cpu-rt-runtime int          Limit the CPU real-time runtime in microseconds
 | 
					      --cpu-rt-runtime int          Limit the CPU real-time runtime in microseconds
 | 
				
			||||||
 | 
					  -c, --cpu-shares int              CPU shares (relative weight)
 | 
				
			||||||
 | 
					      --cpus decimal                Number of CPUs (default 0.000)
 | 
				
			||||||
      --cpuset-cpus string          CPUs in which to allow execution (0-3, 0,1)
 | 
					      --cpuset-cpus string          CPUs in which to allow execution (0-3, 0,1)
 | 
				
			||||||
      --cpuset-mems string          MEMs in which to allow execution (0-3, 0,1)
 | 
					      --cpuset-mems string          MEMs in which to allow execution (0-3, 0,1)
 | 
				
			||||||
      --help                        Print usage
 | 
					      --help                        Print usage
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -282,3 +282,38 @@ func (s *DockerSuite) TestUpdateNotAffectMonitorRestartPolicy(c *check.C) {
 | 
				
			||||||
	c.Assert(err, checker.IsNil)
 | 
						c.Assert(err, checker.IsNil)
 | 
				
			||||||
	c.Assert(waitRun(id), checker.IsNil)
 | 
						c.Assert(waitRun(id), checker.IsNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *DockerSuite) TestUpdateWithNanoCPUs(c *check.C) {
 | 
				
			||||||
 | 
						testRequires(c, cpuCfsQuota, cpuCfsPeriod)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file1 := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"
 | 
				
			||||||
 | 
						file2 := "/sys/fs/cgroup/cpu/cpu.cfs_period_us"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, _ := dockerCmd(c, "run", "-d", "--cpus", "0.5", "--name", "top", "busybox", "top")
 | 
				
			||||||
 | 
						c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, _ = dockerCmd(c, "exec", "top", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2))
 | 
				
			||||||
 | 
						c.Assert(strings.TrimSpace(out), checker.Equals, "50000\n100000")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.NanoCpus")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "5e+08", check.Commentf("setting the Nano CPUs failed"))
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.CpuQuota")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS quota should be 0"))
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.CpuPeriod")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS period should be 0"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, _, err := dockerCmdWithError("update", "--cpu-quota", "80000", "top")
 | 
				
			||||||
 | 
						c.Assert(err, checker.NotNil)
 | 
				
			||||||
 | 
						c.Assert(out, checker.Contains, "Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, _ = dockerCmd(c, "update", "--cpus", "0.8", "top")
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.NanoCpus")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "8e+08", check.Commentf("updating the Nano CPUs failed"))
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.CpuQuota")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS quota should be 0"))
 | 
				
			||||||
 | 
						out = inspectField(c, "top", "HostConfig.CpuPeriod")
 | 
				
			||||||
 | 
						c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS period should be 0"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, _ = dockerCmd(c, "exec", "top", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2))
 | 
				
			||||||
 | 
						c.Assert(strings.TrimSpace(out), checker.Equals, "80000\n100000")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue