Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions depot/containerstore/containerstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ type ContainerConfig struct {
INodeLimit uint64
MaxCPUShares uint64
SetCPUWeight bool
CPUWeight int

MinInstanceMmemoryMB int
MaxInstanceMmemoryMB int

ReservedExpirationTime time.Duration
ReapInterval time.Duration
Expand Down
109 changes: 107 additions & 2 deletions depot/containerstore/containerstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ var _ = Describe("Container Store", func() {
OwnerName: ownerName,
INodeLimit: iNodeLimit,
MaxCPUShares: maxCPUShares,
CPUWeight: 12,
MinInstanceMmemoryMB: 128,
MaxInstanceMmemoryMB: 8192,
ReapInterval: 20 * time.Millisecond,
ReservedExpirationTime: 20 * time.Millisecond,
MetricReportInterval: 30 * time.Second,
Expand Down Expand Up @@ -507,14 +510,116 @@ var _ = Describe("Container Store", func() {

Expect(int(containerSpec.Limits.Pid.Max)).To(Equal(resource.MaxPids))

expectedCPUShares := uint64(float64(maxCPUShares) * float64(runReq.CPUWeight) / 100.0)
expectedCPUShares := uint64(float64(maxCPUShares) * float64(containerConfig.CPUWeight) / 100.0)
Expect(containerSpec.Limits.CPU.LimitInShares).To(Equal(expectedCPUShares))

expectedCPUWeight := uint64(resource.MemoryMB)
Expect(containerSpec.Limits.CPU.Weight).To(Equal(expectedCPUWeight))
})
})

Context("when the requested memory is more than MaxInstanceMmemoryMB", func() {
BeforeEach(func() {
allocationReq.Resource.MemoryMB = 10240
resource.MemoryMB = 10240

containerConfig.CPUWeight = 100
containerStore = containerstore.New(
containerConfig,
&totalCapacity,
gardenClientFactory,
dependencyManager,
volumeManager,
credManager,
logManager,
clock,
eventEmitter,
megatron,
"/var/vcap/data/cf-system-trusted-certs",
metronClient,
rootFSSizer,
false,
"/var/vcap/packages/healthcheck",
proxyManager,
cellID,
true,
advertisePreferenceForInstanceAddress,
json.Marshal,
)
})

It("creates the container in garden with the correct limits ", func() {
_, err := containerStore.Create(logger, "some-trace-id", containerGuid)
Expect(err).NotTo(HaveOccurred())

Expect(gardenClient.CreateCallCount()).To(Equal(1))
containerSpec := gardenClient.CreateArgsForCall(0)
Expect(containerSpec.Limits.Memory.LimitInBytes).To(BeEquivalentTo(resource.MemoryMB * 1024 * 1024))

Expect(containerSpec.Limits.Disk.Scope).To(Equal(garden.DiskLimitScopeTotal))
Expect(containerSpec.Limits.Disk.ByteHard).To(BeEquivalentTo((resource.DiskMB * 1024 * 1024) + 1000))
Expect(containerSpec.Limits.Disk.InodeHard).To(Equal(iNodeLimit))

Expect(int(containerSpec.Limits.Pid.Max)).To(Equal(resource.MaxPids))

expectedCPUShares := uint64(float64(maxCPUShares) * float64(containerConfig.CPUWeight) / 100.0)
Expect(containerSpec.Limits.CPU.LimitInShares).To(Equal(expectedCPUShares))
Expect(containerSpec.Limits.CPU.Weight).To(BeZero())

})
})

Context("when the requested memory is less than MaxInstanceMmemoryMB", func() {
BeforeEach(func() {
allocationReq.Resource.MemoryMB = 100
resource.MemoryMB = 100

containerConfig.CPUWeight = 1
containerStore = containerstore.New(
containerConfig,
&totalCapacity,
gardenClientFactory,
dependencyManager,
volumeManager,
credManager,
logManager,
clock,
eventEmitter,
megatron,
"/var/vcap/data/cf-system-trusted-certs",
metronClient,
rootFSSizer,
false,
"/var/vcap/packages/healthcheck",
proxyManager,
cellID,
true,
advertisePreferenceForInstanceAddress,
json.Marshal,
)
})

It("creates the container in garden with the correct limits", func() {
_, err := containerStore.Create(logger, "some-trace-id", containerGuid)
Expect(err).NotTo(HaveOccurred())

Expect(gardenClient.CreateCallCount()).To(Equal(1))
containerSpec := gardenClient.CreateArgsForCall(0)
Expect(containerSpec.Limits.Memory.LimitInBytes).To(BeEquivalentTo(resource.MemoryMB * 1024 * 1024))

Expect(containerSpec.Limits.Disk.Scope).To(Equal(garden.DiskLimitScopeTotal))
Expect(containerSpec.Limits.Disk.ByteHard).To(BeEquivalentTo((resource.DiskMB * 1024 * 1024) + 1000))
Expect(containerSpec.Limits.Disk.InodeHard).To(Equal(iNodeLimit))

Expect(int(containerSpec.Limits.Pid.Max)).To(Equal(resource.MaxPids))

expectedCPUShares := uint64(float64(maxCPUShares) * float64(containerConfig.CPUWeight) / 100.0)
Expect(containerSpec.Limits.CPU.LimitInShares).To(Equal(expectedCPUShares))
Expect(containerSpec.Limits.CPU.Weight).To(BeZero())

})
})

It("creates the container in garden with the correct limits", func() {
_, err := containerStore.Create(logger, "some-trace-id", containerGuid)
Expect(err).NotTo(HaveOccurred())
Expand All @@ -529,7 +634,7 @@ var _ = Describe("Container Store", func() {

Expect(int(containerSpec.Limits.Pid.Max)).To(Equal(resource.MaxPids))

expectedCPUShares := uint64(float64(maxCPUShares) * float64(runReq.CPUWeight) / 100.0)
expectedCPUShares := uint64(float64(maxCPUShares) * float64(containerConfig.CPUWeight) / 100.0)
Expect(containerSpec.Limits.CPU.LimitInShares).To(Equal(expectedCPUShares))
Expect(containerSpec.Limits.CPU.Weight).To(BeZero())
})
Expand Down
16 changes: 15 additions & 1 deletion depot/containerstore/storenode.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ func (n *storeNode) createGardenContainer(logger lager.Logger, traceID string, i
return nil, err
}

n.config.CPUWeight = n.calculateCpuWeight(info.MemoryMB)

containerSpec := garden.ContainerSpec{
Handle: info.Guid,
Privileged: info.Privileged,
Expand All @@ -409,7 +411,7 @@ func (n *storeNode) createGardenContainer(logger lager.Logger, traceID string, i
Max: uint64(info.MaxPids),
},
CPU: garden.CPULimits{
LimitInShares: uint64(float64(n.config.MaxCPUShares) * float64(info.CPUWeight) / 100.0),
LimitInShares: uint64(float64(n.config.MaxCPUShares) * float64(n.config.CPUWeight) / 100.0),
},
},
Properties: gardenProperties,
Expand Down Expand Up @@ -883,3 +885,15 @@ func createContainer(logger lager.Logger, spec garden.ContainerSpec, client gard
}
return container, nil
}

func (n *storeNode) calculateCpuWeight(memoryMB int) int {
if memoryMB > n.config.MaxInstanceMmemoryMB {
return 100
}

if memoryMB < n.config.MinInstanceMmemoryMB {
memoryMB = n.config.MinInstanceMmemoryMB
}

return 100 * memoryMB / n.config.MaxInstanceMmemoryMB
}
4 changes: 4 additions & 0 deletions initializer/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ type ExecutorConfig struct {
ReadWorkPoolSize int `json:"read_work_pool_size,omitempty"`
ReservedExpirationTime durationjson.Duration `json:"reserved_expiration_time,omitempty"`
SetCPUWeight bool `json:"set_cpu_weight,omitempty"`
MinInstanceMmemoryMB int `json:"min_instance_memory_mb,omitempty"`
MaxInstanceMmemoryMB int `json:"max_instance_memory_mb,omitempty"`
SkipCertVerify bool `json:"skip_cert_verify,omitempty"`
TempDir string `json:"temp_dir,omitempty"`
TrustedSystemCertificatesPath string `json:"trusted_system_certificates_path"`
Expand Down Expand Up @@ -270,6 +272,8 @@ func Initialize(logger lager.Logger, config ExecutorConfig, cellID, zone string,
INodeLimit: config.ContainerInodeLimit,
MaxCPUShares: config.ContainerMaxCpuShares,
SetCPUWeight: config.SetCPUWeight,
MinInstanceMmemoryMB: config.MinInstanceMmemoryMB,
MaxInstanceMmemoryMB: config.MaxInstanceMmemoryMB,
ReservedExpirationTime: time.Duration(config.ReservedExpirationTime),
ReapInterval: time.Duration(config.ContainerReapInterval),
MaxLogLinesPerSecond: config.MaxLogLinesPerSecond,
Expand Down