Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
sandbox: consider cpusets if quota is not enforced
Browse files Browse the repository at this point in the history
If quota is not being enforced on any containers but CPUsets are
specified, take the number of CPU sets into account when sizing the
virtual machine.

Fixes: #2971

Signed-off-by: Eric Ernst <[email protected]>
  • Loading branch information
egernst committed Sep 21, 2020
1 parent 0e0ef63 commit 8ef2946
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
27 changes: 22 additions & 5 deletions virtcontainers/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -1863,7 +1863,10 @@ func (s *Sandbox) updateResources() error {
return fmt.Errorf("sandbox config is nil")
}

sandboxVCPUs := s.calculateSandboxCPUs()
sandboxVCPUs, err := s.calculateSandboxCPUs()
if err != nil {
return err
}
// Add default vcpus for sandbox
sandboxVCPUs += s.hypervisor.hypervisorConfig().NumVCPUs

Expand Down Expand Up @@ -1923,8 +1926,9 @@ func (s *Sandbox) calculateSandboxMemory() int64 {
return memorySandbox
}

func (s *Sandbox) calculateSandboxCPUs() uint32 {
func (s *Sandbox) calculateSandboxCPUs() (uint32, error) {
mCPU := uint32(0)
cpusetCount := int(0)

for _, c := range s.config.Containers {
// Do not hot add again non-running containers resources
Expand All @@ -1938,9 +1942,22 @@ func (s *Sandbox) calculateSandboxCPUs() uint32 {
mCPU += utils.CalculateMilliCPUs(*cpu.Quota, *cpu.Period)
}

set, err := cpuset.Parse(cpu.Cpus)
if err != nil {
return 0, nil
}
cpusetCount += set.Size()
}
}
return utils.CalculateVCpusFromMilliCpus(mCPU)

// If we aren't being constrained, then we could have two scenarios:
// 1. BestEffort QoS: no proper support today in Kata.
// 2. We could be constrained only by CPUSets. Check for this:
if mCPU == 0 && cpusetCount > 0 {
return uint32(cpusetCount), nil
}

return utils.CalculateVCpusFromMilliCpus(mCPU), nil
}

// GetHypervisorType is used for getting Hypervisor name currently used.
Expand Down Expand Up @@ -2273,11 +2290,11 @@ func (s *Sandbox) getSandboxCPUSet() (string, string, error) {
memResult := cpuset.NewCPUSet()
for _, ctr := range s.config.Containers {
if ctr.Resources.CPU != nil {
currCpuSet, err := cpuset.Parse(ctr.Resources.CPU.Cpus)
currCPUSet, err := cpuset.Parse(ctr.Resources.CPU.Cpus)
if err != nil {
return "", "", fmt.Errorf("unable to parse CPUset.cpus for container %s: %v", ctr.ID, err)
}
cpuResult = cpuResult.Union(currCpuSet)
cpuResult = cpuResult.Union(currCPUSet)

currMemSet, err := cpuset.Parse(ctr.Resources.CPU.Mems)
if err != nil {
Expand Down
15 changes: 12 additions & 3 deletions virtcontainers/sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,18 @@ func TestCreateMockSandbox(t *testing.T) {
func TestCalculateSandboxCPUs(t *testing.T) {
sandbox := &Sandbox{}
sandbox.config = &SandboxConfig{}

unconstrained := newTestContainerConfigNoop("cont-00001")
constrained := newTestContainerConfigNoop("cont-00001")
constrained := newTestContainerConfigNoop("cont-00002")
unconstrainedCpusets0_1 := newTestContainerConfigNoop("cont-00003")
unconstrainedCpusets2 := newTestContainerConfigNoop("cont-00004")
constrainedCpusets0_7 := newTestContainerConfigNoop("cont-00005")
quota := int64(4000)
period := uint64(1000)
constrained.Resources.CPU = &specs.LinuxCPU{Period: &period, Quota: &quota}

unconstrainedCpusets0_1.Resources.CPU = &specs.LinuxCPU{Cpus: "0-1"}
unconstrainedCpusets2.Resources.CPU = &specs.LinuxCPU{Cpus: "2"}
constrainedCpusets0_7.Resources.CPU = &specs.LinuxCPU{Period: &period, Quota: &quota, Cpus: "0-7"}
tests := []struct {
name string
containers []ContainerConfig
Expand All @@ -123,11 +129,14 @@ func TestCalculateSandboxCPUs(t *testing.T) {
{"2-constrained", []ContainerConfig{constrained, constrained}, 8},
{"3-mix-constraints", []ContainerConfig{unconstrained, constrained, constrained}, 8},
{"3-constrained", []ContainerConfig{constrained, constrained, constrained}, 12},
{"unconstrained-1-cpuset", []ContainerConfig{unconstrained, unconstrained, unconstrainedCpusets0_1}, 2},
{"unconstrained-2-cpuset", []ContainerConfig{unconstrainedCpusets0_1, unconstrainedCpusets2}, 3},
{"constrained-cpuset", []ContainerConfig{constrainedCpusets0_7}, 4},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sandbox.config.Containers = tt.containers
got := sandbox.calculateSandboxCPUs()
got, _ := sandbox.calculateSandboxCPUs()
assert.Equal(t, got, tt.want)
})
}
Expand Down

0 comments on commit 8ef2946

Please sign in to comment.