Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic guest vCPUs to pCPUs pinning #1381

Merged
merged 30 commits into from Sep 12, 2018
Merged

Conversation

vladikr
Copy link
Member

@vladikr vladikr commented Jul 27, 2018

What this PR does / why we need it:
Replying on k8s CPUManager feature, this PR implements a basic guest vCPUs to a dedicated pods' pCPUs pinning.

In general, k8s CPU manager will pin pods' CPUs under certain conditions:

  • pods' QOS is Guaranteed
    • resources requests and limits are equal
    • all containers in the pod express cpu and memory resources
  • requested number of CPUs in integer

Once pods' cpus are dedicated and pinned, virt-launcher can pin VMs' vCPUS to the pods pCPUS

This PR also provides a mechanism that once dedicatedCpuPlacement policy has been requested, it will "enforce" the above conditions on the pod spec, so the k8s cpu manager will pin pods' cpus and reject inconsistent requirements.

The user may either express the vCPU requirements using cpu.cores to resources.[requests, limits].cpu
togethre with cpu.dedicatedCpuPlacement = true

spec:
  domain:
    cpu:
      cores: 2
      dedicatedCpuPlacement: true
    resources:                                                                                                                                                                                                     
      limits:
        memory: 2Gi

OR

spec:
  domain:
    cpu:
      dedicatedCpuPlacement: true
    resources:                                                                                                                                                                                                     
      limits:
        cpu: 2                                                                 
        memory: 2Gi

Special notes for your reviewer:
What's currently missing:

  • Functional tests to verify scheduling
  • validation webhooks
  • Defaults CPU/memory defaults for hooks

Functional tests are dependant on kubevirt/kubevirtci#37

Release note:

Pinning vCPU to a set of pCPUs is now possible

@kubevirt-bot kubevirt-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L labels Jul 27, 2018
@vladikr vladikr added size/L release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L labels Jul 27, 2018
@vladikr vladikr force-pushed the cpu_manager branch 3 times, most recently from 77729c6 to bafa3cf Compare August 7, 2018 16:41
Copy link
Contributor

@yanirq yanirq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validations will be added to check that the VM pod resources and limits will conform with Guaranteed QoS class?


resources := kubev1.ResourceRequirements{}
resources.Limits = make(kubev1.ResourceList)
resources.Limits[kubev1.ResourceCPU] = resource.MustParse("50m")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How was this value decided ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, just needed to start somewhere.
This container only mounts a path. - I'll make it a global default variable

Copy link
Member

@cynepco3hahue cynepco3hahue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that we can introduce CPU pinning, but in my opinion it very limited, we still do not give any possibility to a user to control exact CPU pinning.

func (d *VirtualMachineController) addNodeCpuManagerLabel() {
entries, err := filepath.Glob("/proc/*/cmdline")
if err != nil {
log.DefaultLogger().Reason(err).Errorf("failed to set a cpu manager label on host %s", d.host)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make more specific messages? It will be easier to track it on debug

@@ -22,8 +22,11 @@ package virthandler
import (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need some renaming under this file from VM to VMI, but it must not be a part of the PR 😄

@@ -776,6 +783,33 @@ func (d *VirtualMachineController) heartBeat(interval time.Duration, stopCh chan
}
}

func (d *VirtualMachineController) addNodeCpuManagerLabel() {
entries, err := filepath.Glob("/proc/*/cmdline")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How many time can it take on some loaded machine? (20k process)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't 20k processes running anywhere. on my machine it with ~1k processes it took the following, but that also includes go compilation and getting its' stuck up:

time go run  trym22.go 

real    0m0.143s
user    0m0.115s
sys     0m0.058s

I don't believe it should be a problem, however, this is just a workaround at the moment, until k8s addresses the issue: kubernetes/kubernetes#66525

"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
)

const CPUSET_PATH = "/sys/fs/cgroup/cpuset/cpuset.cpus"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it must be lower case if you do not want to use it outside of the package.

@vladikr
Copy link
Member Author

vladikr commented Aug 9, 2018

I like that we can introduce CPU pinning, but in my opinion it very limited, we still do not give any possibility to a user to control exact CPU pinning.

Thanks for the review!

Yea, it's because we have to rely on the k8s CPU manager, which is limited...
Hope it'll improve in the future or we'll come up with a better approach.
There was a survey from k8s that samples which cpu related features people are interested in:
https://docs.google.com/forms/d/e/1FAIpQLSest47hzQyKO_ENEbAsyZz_78aPCDpuToHjsyg7n75fF70ArA/viewanalytics

@stu-gott stu-gott mentioned this pull request Aug 9, 2018
resources.Limits[k8sv1.ResourceCPU] = *resource.NewQuantity(int64(cpus.Cores), resource.BinarySI)
resources.Requests[k8sv1.ResourceCPU] = *resource.NewQuantity(int64(cpus.Cores), resource.BinarySI)
} else {
if cpuLimit, ok := resources.Limits[k8sv1.ResourceCPU]; ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wonder if we need to check that resources can be converted to an integer because a user can to specify

  • cpus.DedicatedCPUPlacement
  • resources.Limits equal to something like 200m

In this case I think you will fail in converter, so better to add this check to validation webhook

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. I've added several validations but didn't post yet as I'm still struggling with the functional tests.

Also, I wanted to explicitly check, somewhere in the SyncVM that the pods QOS is Guaranteed, but didn't figure out yet how to get to pods informer at that stage.

@vladikr
Copy link
Member Author

vladikr commented Aug 13, 2018

Added validations, still working on the functional tests.

@vladikr vladikr force-pushed the cpu_manager branch 2 times, most recently from 628314e to 81f459a Compare August 14, 2018 05:23
})
It("should reject specs with non-integer cpu limits values", func() {
vmi.Spec.Domain.Resources.Limits = k8sv1.ResourceList{
k8sv1.ResourceCPU: resource.MustParse("800m"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add another negative test with a fraction value (cpu = 1.5) not in milli format.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yanirq you don't trust resource.MustParse() to handle it? ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vladikr if it does so i do :)

@dcritch
Copy link

dcritch commented Aug 15, 2018

I've been testing CPU manager as is with kubevirt and its working pretty good. Trying to understand what this change will improve. Seems like we can specify particular CPUs? Currently with CPU manager, the VM is pinned on whatever CPU the process happens to start on, but can't be specified.

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Adding the qos helper package from
k8s.io/kubernetes/pkg/apis/core/v1/helper/qos to avoid indroducing a dependency
on k8s.io/kubernetes

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
…uested

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Add a SYS_NICE capability to virt-launcher container when cpu pinning is
requested

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
…pinning

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
…h its status

Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
@vladikr
Copy link
Member Author

vladikr commented Sep 12, 2018

ci test please

@davidvossel davidvossel merged commit 2796172 into kubevirt:master Sep 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL topic/performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants