Browse Source

Merge pull request #20924 from Microsoft/10662-CPUResourceControls

Add CPU count and maximum resource controls for Windows
Vincent Demeester 9 years ago
parent
commit
172ca1ca8c

+ 5 - 0
daemon/daemon_unix.go

@@ -411,6 +411,11 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
 	if resources.CPUQuota > 0 && resources.CPUQuota < 1000 {
 		return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
 	}
+	if resources.CPUPercent > 0 {
+		warnings = append(warnings, "%s does not support CPU percent. Percent discarded.", runtime.GOOS)
+		logrus.Warnf("%s does not support CPU percent. Percent discarded.", runtime.GOOS)
+		resources.CPUPercent = 0
+	}
 
 	// cpuset subsystem checks and adjustments
 	if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset {

+ 26 - 1
daemon/daemon_windows.go

@@ -16,6 +16,7 @@ import (
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
+	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/reference"
 	"github.com/docker/docker/runconfig"
 	// register the windows graph driver
@@ -94,10 +95,34 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
 	return nil
 }
 
+func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) {
+	warnings := []string{}
+
+	// cpu subsystem checks and adjustments
+	if resources.CPUPercent < 0 || resources.CPUPercent > 100 {
+		return warnings, fmt.Errorf("Range of CPU percent is from 1 to 100")
+	}
+
+	if resources.CPUPercent > 0 && resources.CPUShares > 0 {
+		return warnings, fmt.Errorf("Conflicting options: CPU Shares and CPU Percent cannot both be set")
+	}
+
+	return warnings, nil
+}
+
 // verifyPlatformContainerSettings performs platform-specific validation of the
 // hostconfig and config structures.
 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
-	return nil, nil
+
+	warnings := []string{}
+
+	w, err := verifyContainerResources(&hostConfig.Resources, nil)
+	warnings = append(warnings, w...)
+	if err != nil {
+		return warnings, err
+	}
+
+	return warnings, nil
 }
 
 // verifyDaemonSettings performs validation of daemon config struct

+ 2 - 3
daemon/oci_windows.go

@@ -160,9 +160,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
 	cpuShares := uint64(c.HostConfig.CPUShares)
 	s.Windows.Resources = &windowsoci.Resources{
 		CPU: &windowsoci.CPU{
-			//TODO Count: ...,
-			//TODO Percent: ...,
-			Shares: &cpuShares,
+			Percent: &c.HostConfig.CPUPercent,
+			Shares:  &cpuShares,
 		},
 		Memory: &windowsoci.Memory{
 		//TODO Limit: ...,

+ 3 - 0
docs/reference/api/docker_remote_api_v1.24.md

@@ -282,6 +282,7 @@ Create a container
              "MemorySwap": 0,
              "MemoryReservation": 0,
              "KernelMemory": 0,
+             "CpuPercent": 80,
              "CpuShares": 512,
              "CpuPeriod": 100000,
              "CpuQuota": 50000,
@@ -354,6 +355,7 @@ Json Parameters:
       You must use this with `memory` and make the swap value larger than `memory`.
 -   **MemoryReservation** - Memory soft limit in bytes.
 -   **KernelMemory** - Kernel memory limit in bytes.
+-   **CpuPercent** - An integer value containing the usable percentage of the available CPUs. (Windows daemon only)
 -   **CpuShares** - An integer value containing the container's CPU Shares
       (ie. the relative weight vs other containers).
 -   **CpuPeriod** - The length of a CPU period in microseconds.
@@ -542,6 +544,7 @@ Return low-level information on the container `id`
 			"ContainerIDFile": "",
 			"CpusetCpus": "",
 			"CpusetMems": "",
+			"CpuPercent": 80,
 			"CpuShares": 0,
 			"CpuPeriod": 100000,
 			"Devices": [],

+ 1 - 0
docs/reference/commandline/run.md

@@ -23,6 +23,7 @@ parent = "smn_cli"
       --cap-drop=[]                 Drop Linux capabilities
       --cgroup-parent=""            Optional parent cgroup for the container
       --cidfile=""                  Write the container ID to the file
+      --cpu-percent=0               Limit percentage of CPU available for execution by the container. Windows daemon only.
       --cpu-period=0                Limit CPU CFS (Completely Fair Scheduler) period
       --cpu-quota=0                 Limit CPU CFS (Completely Fair Scheduler) quota
       --cpuset-cpus=""              CPUs in which to allow execution (0-3, 0,1)

+ 2 - 0
runconfig/opts/parse.go

@@ -78,6 +78,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 		flUser              = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
 		flWorkingDir        = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
 		flCPUShares         = cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
+		flCPUPercent        = cmd.Int64([]string{"-cpu-percent"}, 0, "CPU percent (Windows only)")
 		flCPUPeriod         = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
 		flCPUQuota          = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
 		flCpusetCpus        = cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
@@ -354,6 +355,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 		MemorySwappiness:     flSwappiness,
 		KernelMemory:         KernelMemory,
 		OomKillDisable:       flOomKillDisable,
+		CPUPercent:           *flCPUPercent,
 		CPUShares:            *flCPUShares,
 		CPUPeriod:            *flCPUPeriod,
 		CpusetCpus:           *flCpusetCpus,