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

Fixing scheduling latency metrics #64316

Merged

Conversation

krzysied
Copy link
Contributor

What this PR does / why we need it:
Allows to measure and to display scheduling latency metrics during tests. Provides new functionality of resetting scheduler latency metrics.

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #63493

Special notes for your reviewer:
E2eSchedulingLatency, SchedulingAlgorithmLatency, BindingLatency are now available
as subtypes of OperationLatency.

Release note:

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels May 25, 2018
@k8s-ci-robot k8s-ci-robot requested review from gmarek and ncdc May 25, 2018 14:19
@k8s-ci-robot k8s-ci-robot added the sig/scheduling Categorizes an issue or PR as relevant to SIG Scheduling. label May 25, 2018
@krzysied
Copy link
Contributor Author

/retest

@krzysied
Copy link
Contributor Author

/assign shyamjvs

@@ -225,7 +227,16 @@ func buildHandlerChain(handler http.Handler, authn authenticator.Request, authz
func newMetricsHandler(config *componentconfig.KubeSchedulerConfiguration) http.Handler {
pathRecorderMux := mux.NewPathRecorderMux("kube-scheduler")
configz.InstallHandler(pathRecorderMux)
pathRecorderMux.Handle("/metrics", prometheus.Handler())
//metrics.Register()
Copy link
Member

Choose a reason for hiding this comment

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

Could you remove this commented code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -243,7 +254,15 @@ func newHealthzHandler(config *componentconfig.KubeSchedulerConfiguration, separ
healthz.InstallHandler(pathRecorderMux)
if !separateMetrics {
configz.InstallHandler(pathRecorderMux)
pathRecorderMux.Handle("/metrics", prometheus.Handler())
defaultMetricsHandler := prometheus.Handler().ServeHTTP
Copy link
Member

Choose a reason for hiding this comment

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

Instead of duplicating the same code as above, could you move this part into a separate function?
Like here - https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/server/routes/metrics.go#L44

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -25,23 +25,26 @@ import (

const schedulerSubsystem = "scheduler"

const BindingType = "binding"
Copy link
Member

Choose a reason for hiding this comment

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

Please put these 3 values within a single const block.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

const SchedulingAlgorithmType ="scheduling_algorithm"
const E2eSchedulingType = "e2e_scheduling"

type resettableCollector interface {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this should be called a resettableCollector (because it's just a collector, and not all of them are resettable). Can't you directly just use a prometheus.Collector?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

)
SchedulingAlgorithmLatency = prometheus.NewHistogram(
prometheus.HistogramOpts{
OperationLatency = prometheus.NewSummaryVec(
Copy link
Member

Choose a reason for hiding this comment

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

Could you name this variable as SchedulingLatency instead? That'll make it more clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Name: "scheduling_algorithm_latency_microseconds",
Help: "Scheduling algorithm latency",
Buckets: prometheus.ExponentialBuckets(1000, 2, 15),
Name: "operation_latency_microseconds",
Copy link
Member

Choose a reason for hiding this comment

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

Could you rename this to scheduling_latencies_summary instead? (to keep up with the naming convention used for apiserver)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Help: "Scheduling algorithm latency",
Buckets: prometheus.ExponentialBuckets(1000, 2, 15),
Name: "operation_latency_microseconds",
Help: "operation latency",
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest writing something more descriptive in the Help string. Like "Scheduling latency in microseconds split by sub-parts of the scheduling operation".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Name: "operation_latency_microseconds",
Help: "operation latency",
// Make the sliding window of 5h.
// TODO: The value for this should be based on our SLI definition (medium term).
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 change:
our -> some
medium -> long

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

},
[]string{"operationType"},
Copy link
Member

Choose a reason for hiding this comment

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

Just operation is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

switch sample.Metric[model.MetricNameLabel] {
case "scheduler_scheduling_algorithm_latency_microseconds":
switch sample.Metric["operationType"] {
case "scheduling_algorithm":
Copy link
Member

Choose a reason for hiding this comment

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

Please replace these hard-coded strings with their corresponding const vars you defined above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -520,6 +524,53 @@ func VerifySchedulerLatency(c clientset.Interface) (*SchedulingLatency, error) {
return latency, nil
}

func ResetSchedulerLatency(c clientset.Interface) error {
Copy link
Member

Choose a reason for hiding this comment

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

Rename this to ResetSchedulerLatencyMetrics?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 26, 2018
@krzysied krzysied force-pushed the scheduling_latency_metric branch 2 times, most recently from 6162545 to fe35b2a Compare May 28, 2018 10:01
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 28, 2018
const schedulerSubsystem = "scheduler"
const (
SchedulerSubsystem = "scheduler"
SchedulingLatencyName = "scheduling_latencies_summary"
Copy link
Member

Choose a reason for hiding this comment

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

I don't think it's too useful to have this const. Maybe just put the string directly inside the metric definition (like other metrics)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do we want to have operation types as a consts and and metric name as a string? Shouldn't we have coherent style - all strings or all consts?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, you have a valid point there.

So ideally we should make all hard-coded strings in files as global constants (so we only define the 'real' string once and later on only have references to it). However, moving too many things to global consts makes the file larger and harder to read. So the rule I'm usually following is to make a string const only if it's referenced enough times (3-4) in the codebase, so it's worth it. But this is subjective :)

SchedulerSubsystem = "scheduler"
SchedulingLatencyName = "scheduling_latencies_summary"

OperationLabel = "opertion"
Copy link
Member

Choose a reason for hiding this comment

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

operation

Copy link
Member

Choose a reason for hiding this comment

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

Also can we rename this variable to OperationType and change the below ones to simply Binding, SchedulingAlgorithm, etc? Will make the meaning more clearer imo.

@@ -130,6 +131,8 @@ func (m *MetricsForE2E) SummaryKind() string {
return "MetricsForE2E"
}

var SchedulingLatencyMetricName = model.LabelValue(schedulerMetric.SchedulerSubsystem + "_" + schedulerMetric.SchedulingLatencyName)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it'll be cleaner to have sth similar to apiserver like this:

var InterestingSchedulerMetrics = []string{
  "scheduler_whatever"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that scheduler latency metric has a special handling (other metrics will have different structure/labels). Always at some point you will need to verify if name == SCHEDULER_METRIC_NAME. That's why I prefer having variable to having value in array.

Copy link
Member

Choose a reason for hiding this comment

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

Yes. However, isn't it the same for apiserver metrics too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so. The apiserver e2e metric are group of metrics with the some structure, so none of those metric requires special handling.
The apiserver latency metrics are more similar to scheduler latency metric. However in this case, metric names are compared to explicit strings.

@@ -521,6 +528,53 @@ func VerifySchedulerLatency(c clientset.Interface) (*SchedulingMetrics, error) {
return latency, nil
}

func ResetSchedulerLatencyMetrics(c clientset.Interface) error {
Copy link
Member

Choose a reason for hiding this comment

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

I see some overlap of this function with getSchedulingLatency(). Can we somehow unify them?

@@ -442,6 +440,7 @@ var _ = SIGDescribe("Density", func() {

uuid = string(utiluuid.NewUUID())

framework.ExpectNoError(framework.ResetSchedulerLatencyMetrics(c))
Copy link
Member

Choose a reason for hiding this comment

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

Actually, let's name this function as ResetSchedulerMetrics (as we may expand it in future to reset more metrics than just latency).

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 30, 2018
@wojtek-t
Copy link
Member

/approve

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 30, 2018
@shyamjvs
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 30, 2018
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: krzysied, shyamjvs, wojtek-t

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@shyamjvs
Copy link
Member

/kind cleanup
/priority important-soon

@k8s-ci-robot k8s-ci-robot added kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. labels May 30, 2018
@shyamjvs
Copy link
Member

These metrics are important for our tests. @jberkus could you please approve for milestone?

@wojtek-t wojtek-t added status/approved-for-milestone sig/scalability Categorizes an issue or PR as relevant to SIG Scalability. labels May 30, 2018
@wojtek-t
Copy link
Member

Approving as scalability sig lead

@k8s-github-robot
Copy link

[MILESTONENOTIFIER] Milestone Pull Request: Up-to-date for process

@krzysied @shyamjvs @wojtek-t

Pull Request Labels
  • sig/scalability sig/scheduling: Pull Request will be escalated to these SIGs if needed.
  • priority/important-soon: Escalate to the pull request owners and SIG owner; move out of milestone after several unsuccessful escalation attempts.
  • kind/cleanup: Adding tests, refactoring, fixing old bugs.
Help

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 63328, 64316, 64444, 64449, 64453). If you want to cherry-pick this change to another branch, please follow the instructions here.

@k8s-github-robot k8s-github-robot merged commit a2d8636 into kubernetes:master May 30, 2018
const schedulerSubsystem = "scheduler"
const (
// SchedulerSubsystem - subsystem name used by scheduler
SchedulerSubsystem = "scheduler"
Copy link
Member

@bsalamat bsalamat May 30, 2018

Choose a reason for hiding this comment

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

Renaming metrics is a breaking change. It is not backward compatible and is going to break monitoring systems that rely on these metrics. This PR should be reverted.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that's a valid concern and also the option I was initially suggesting in #63493 (comment). I've cc'd there sig-scheduling and you - following lazy consensus since there weren't any objections :)

So, what do you think about re-adding the old metric alongside the new one (instead of replacing it)?

Copy link
Member

Choose a reason for hiding this comment

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

Wasn't this metric broken anyway?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think so.. IIUC we were just not capturing the values properly in our test framework (which expects summary instead of histogram).

Choose a reason for hiding this comment

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

If we're going to add "aliases" for metrics, I think we should make more of a push toward prometheus best practices. The various histograms in this file and their relationships are a bit confusing.

Copy link
Member

Choose a reason for hiding this comment

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

I agree with @misterikkit. Some of these names were not following Prometheus best practices. The new ones introduces in this PR are not following those best practices either. We should definitely keep the old ones for backward compatibility and maybe add new aliases based on the best practices.

@bsalamat
Copy link
Member

bsalamat commented Jun 1, 2018

@krzysied Did you have a chance to revert the changes to the metrics names?

@shyamjvs
Copy link
Member

shyamjvs commented Jun 4, 2018

@bsalamat @misterikkit Does the following sgty:

  • Re-introduce the old metrics (which are histogram-type)
  • Keep the new metrics (which are summary-type)

And to clarify, this is not a question of "aliases" - the new metrics aren't just a name change, they're introducing summary-type metrics (like mentioned above). And the reason is we want to have accurate percentiles of scheduling latencies for measuring the performance better (some context here - #63493 (comment))

And wrt naming the new metrics, sure we can change the name.. that's not a problem. Could you point us to what best practices you're referring?

@shyamjvs
Copy link
Member

shyamjvs commented Jun 4, 2018

@krzysied can make the changes based on what we agree above.

@misterikkit
Copy link

the new metrics aren't just a name change, they're introducing summary-type metrics

Ahh, I failed to notice the distinction. I guess the sliding window is a more useful view of performance over the last N minutes, but is that better for observing health in a live cluster?

And wrt naming the new metrics, sure we can change the name.. that's not a problem. Could you point us to what best practices you're referring?

https://prometheus.io/docs/practices/naming/

@krzysied
Copy link
Contributor Author

krzysied commented Jun 6, 2018

I've created the PR #64838 that re-introduces old metrics and changes new one to satisfy prometheus best practice.

@bsalamat @misterikkit Could you please take a look and give an option as to whether this change looks good to you?

k8s-github-robot pushed a commit that referenced this pull request Jun 15, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Adding summary metric for scheduling latency

**What this PR does / why we need it**:
Re-introduces histogram metrics for the backward compatibility.
Changes SchedulingLatency metric to satisfy prometheus best practice.
ref #64316

**Release note**:

```release-note
NONE
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note-none Denotes a PR that doesn't merit a release note. sig/scalability Categorizes an issue or PR as relevant to SIG Scalability. sig/scheduling Categorizes an issue or PR as relevant to SIG Scheduling. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scheduler metrics not captured properly in density test
8 participants