浏览代码

Merge pull request #5373 from vmarmol/master

Separating cgroup Memory and MemoryReservation.
Guillaume J. Charmes 11 年之前
父节点
当前提交
85540f6aa0

+ 18 - 4
daemon/execdriver/native/configuration/parse.go

@@ -21,10 +21,11 @@ var actions = map[string]Action{
 
 	"net.join": joinNetNamespace, // join another containers net namespace
 
-	"cgroups.cpu_shares":  cpuShares,  // set the cpu shares
-	"cgroups.memory":      memory,     // set the memory limit
-	"cgroups.memory_swap": memorySwap, // set the memory swap limit
-	"cgroups.cpuset.cpus": cpusetCpus, // set the cpus used
+	"cgroups.cpu_shares":         cpuShares,         // set the cpu shares
+	"cgroups.memory":             memory,            // set the memory limit
+	"cgroups.memory_reservation": memoryReservation, // set the memory reservation
+	"cgroups.memory_swap":        memorySwap,        // set the memory swap limit
+	"cgroups.cpuset.cpus":        cpusetCpus,        // set the cpus used
 
 	"apparmor_profile": apparmorProfile, // set the apparmor profile to apply
 
@@ -70,6 +71,19 @@ func memory(container *libcontainer.Container, context interface{}, value string
 	return nil
 }
 
+func memoryReservation(container *libcontainer.Container, context interface{}, value string) error {
+	if container.Cgroups == nil {
+		return fmt.Errorf("cannot set cgroups when they are disabled")
+	}
+
+	v, err := utils.RAMInBytes(value)
+	if err != nil {
+		return err
+	}
+	container.Cgroups.MemoryReservation = v
+	return nil
+}
+
 func memorySwap(container *libcontainer.Container, context interface{}, value string) error {
 	if container.Cgroups == nil {
 		return fmt.Errorf("cannot set cgroups when they are disabled")

+ 17 - 1
daemon/execdriver/native/configuration/parse_test.go

@@ -93,7 +93,7 @@ func TestCpuShares(t *testing.T) {
 	}
 }
 
-func TestCgroupMemory(t *testing.T) {
+func TestMemory(t *testing.T) {
 	var (
 		container = template.New()
 		opts      = []string{
@@ -109,6 +109,22 @@ func TestCgroupMemory(t *testing.T) {
 	}
 }
 
+func TestMemoryReservation(t *testing.T) {
+	var (
+		container = template.New()
+		opts      = []string{
+			"cgroups.memory_reservation=500m",
+		}
+	)
+	if err := ParseConfiguration(container, nil, opts); err != nil {
+		t.Fatal(err)
+	}
+
+	if expected := int64(500 * 1024 * 1024); container.Cgroups.MemoryReservation != expected {
+		t.Fatalf("expected memory reservation %d got %d", expected, container.Cgroups.MemoryReservation)
+	}
+}
+
 func TestAddCap(t *testing.T) {
 	var (
 		container = template.New()

+ 1 - 0
daemon/execdriver/native/create.go

@@ -91,6 +91,7 @@ func (d *driver) setupCgroups(container *libcontainer.Container, c *execdriver.C
 	if c.Resources != nil {
 		container.Cgroups.CpuShares = c.Resources.CpuShares
 		container.Cgroups.Memory = c.Resources.Memory
+		container.Cgroups.MemoryReservation = c.Resources.Memory
 		container.Cgroups.MemorySwap = c.Resources.MemorySwap
 	}
 	return nil

+ 8 - 7
pkg/cgroups/cgroups.go

@@ -12,13 +12,14 @@ type Cgroup struct {
 	Name   string `json:"name,omitempty"`
 	Parent string `json:"parent,omitempty"`
 
-	DeviceAccess bool   `json:"device_access,omitempty"` // name of parent cgroup or slice
-	Memory       int64  `json:"memory,omitempty"`        // Memory limit (in bytes)
-	MemorySwap   int64  `json:"memory_swap,omitempty"`   // Total memory usage (memory + swap); set `-1' to disable swap
-	CpuShares    int64  `json:"cpu_shares,omitempty"`    // CPU shares (relative weight vs. other containers)
-	CpuQuota     int64  `json:"cpu_quota,omitempty"`     // CPU hardcap limit (in usecs). Allowed cpu time in a given period.
-	CpuPeriod    int64  `json:"cpu_period,omitempty"`    // CPU period to be used for hardcapping (in usecs). 0 to use system default.
-	CpusetCpus   string `json:"cpuset_cpus,omitempty"`   // CPU to use
+	DeviceAccess      bool   `json:"device_access,omitempty"`      // name of parent cgroup or slice
+	Memory            int64  `json:"memory,omitempty"`             // Memory limit (in bytes)
+	MemoryReservation int64  `json:"memory_reservation,omitempty"` // Memory reservation or soft_limit (in bytes)
+	MemorySwap        int64  `json:"memory_swap,omitempty"`        // Total memory usage (memory + swap); set `-1' to disable swap
+	CpuShares         int64  `json:"cpu_shares,omitempty"`         // CPU shares (relative weight vs. other containers)
+	CpuQuota          int64  `json:"cpu_quota,omitempty"`          // CPU hardcap limit (in usecs). Allowed cpu time in a given period.
+	CpuPeriod         int64  `json:"cpu_period,omitempty"`         // CPU period to be used for hardcapping (in usecs). 0 to use system default.
+	CpusetCpus        string `json:"cpuset_cpus,omitempty"`        // CPU to use
 
 	UnitProperties [][2]string `json:"unit_properties,omitempty"` // systemd unit properties
 }

+ 6 - 3
pkg/cgroups/fs/memory.go

@@ -13,7 +13,7 @@ type memoryGroup struct {
 func (s *memoryGroup) Set(d *data) error {
 	dir, err := d.join("memory")
 	// only return an error for memory if it was not specified
-	if err != nil && (d.c.Memory != 0 || d.c.MemorySwap != 0) {
+	if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
 		return err
 	}
 	defer func() {
@@ -22,12 +22,15 @@ func (s *memoryGroup) Set(d *data) error {
 		}
 	}()
 
-	if d.c.Memory != 0 || d.c.MemorySwap != 0 {
+	// Only set values if some config was specified.
+	if d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0 {
 		if d.c.Memory != 0 {
 			if err := writeFile(dir, "memory.limit_in_bytes", strconv.FormatInt(d.c.Memory, 10)); err != nil {
 				return err
 			}
-			if err := writeFile(dir, "memory.soft_limit_in_bytes", strconv.FormatInt(d.c.Memory, 10)); err != nil {
+		}
+		if d.c.MemoryReservation != 0 {
+			if err := writeFile(dir, "memory.soft_limit_in_bytes", strconv.FormatInt(d.c.MemoryReservation, 10)); err != nil {
 				return err
 			}
 		}

+ 4 - 0
pkg/cgroups/systemd/apply_systemd.go

@@ -121,6 +121,10 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
 		properties = append(properties,
 			systemd1.Property{"MemoryLimit", dbus.MakeVariant(uint64(c.Memory))})
 	}
+	if c.MemoryReservation != 0 {
+		properties = append(properties,
+			systemd1.Property{"MemorySoftLimit", dbus.MakeVariant(uint64(c.MemoryReservation))})
+	}
 	// TODO: MemorySwap not available in systemd
 
 	if c.CpuShares != 0 {