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

Add stats monitor for calculating UsageNanoCores periodically #10010

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jsturtevant
Copy link
Contributor

fixes: #9531 and kubernetes/kubernetes#122092

UsageNanoCores should be calculated on a regular interval. This was previously maintained by kubelet but since moving the stats down to the CRI layer this causes issues. See kubernetes/kubernetes#122092 (comment) for details.

@jsturtevant jsturtevant force-pushed the stats-monitor branch 2 times, most recently from 4714878 to 8a7dd89 Compare March 29, 2024 17:48
Signed-off-by: James Sturtevant <jstur@microsoft.com>
Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
Signed-off-by: James Sturtevant <jstur@microsoft.com>
@jsturtevant
Copy link
Contributor Author

I've run this against the failing windows k8s e2e test and it is passing:

 k get nodes -o wide
NAME                                   STATUS   ROLES           AGE     VERSION                             INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION     CONTAINER-RUNTIME
capz-conf-bdbf5                        Ready    <none>          3h46m   v1.31.0-alpha.0.11+79c61d5f0305c5   10.1.0.5      <none>        Windows Server 2022 Datacenter   10.0.20348.2340    containerd://2.0.0-rc.0-9-g7fe6d0390
capz-conf-jtmj2                        Ready    <none>          3h46m   v1.31.0-alpha.0.11+79c61d5f0305c5   10.1.0.4      <none>        Windows Server 2022 Datacenter   10.0.20348.2340    containerd://2.0.0-rc.0-9-g7fe6d0390
capz-conf-vqawh7-control-plane-g77p6   Ready    control-plane   3h50m   v1.31.0-alpha.0.11+79c61d5f0305c5   10.0.0.4      <none>        Ubuntu 22.04.4 LTS               6.5.0-1016-azure   containerd://2.0.0-rc.0-9-g7fe6d0390
./hack/ginkgo-e2e.sh --node-os-distro=windows --ginkgo.focus="should not be exceeded" --report-dir=/home/jstur/out/kubetest --disable-log-dump=true 

Ran 1 of 7407 Specs in 135.611 seconds
SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 7406 Skipped


All tests passed...
Will keep running them until they fail.
This was attempt #42
No, seriously... you can probably stop now.

@jsturtevant
Copy link
Contributor Author

fyi @haircommander @knabben

@jsturtevant
Copy link
Contributor Author

/assign @kiashok

@kiashok
Copy link
Contributor

kiashok commented Apr 2, 2024

LGTM!

cc @dmcgowan @mikebrow @fuweid could you please take a look?


func TestGetUsageNanoCores(t *testing.T) {
timestamp := time.Now()
secondAfterTimeStamp := timestamp.Add(time.Second)
Copy link

Choose a reason for hiding this comment

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

Should we add another test for microseconds or emulate parallel requests to guarantee the old behavior do not appear as a regression?

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 can add a test where it is one milli second afterward to make sure the calculation would make that different value.

I thought I added a test where it made sure the cached value was returned, but maybe I missed it...

func newMetricMonitor(c *criService) *metricMonitor {
return &metricMonitor{
c: c,
collectionPeriod: 10 * time.Second,
Copy link

Choose a reason for hiding this comment

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

That's an arbitrary value (inherited from another scenario). Should this become configurable in the long term?

Copy link
Member

@mikebrow mikebrow left a comment

Choose a reason for hiding this comment

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

Feels like a breaking change when you consider n-3 versions of kubelet and though kubelet is the primary we have other users... let's do it with a config from the start pls.

For example monitor CPU Usage when set to 0 would be cache disabled on demand only as before. 10s default.. hmm

@@ -285,6 +288,9 @@ func (c *criService) Run(ready func()) error {
}()
}

log.L.Info("Starting metric cache provider")
c.metricMonitor.Start()
Copy link
Member

@mikebrow mikebrow Apr 4, 2024

Choose a reason for hiding this comment

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

fair to have this monitor.. but I think it should be configured...

Also not clear to me that the conversation in the kubelet issue came to agreement on implementation details.. IE. whether or not this would become an on update process (push model?) and/or how intermediate changes would affect in the field CRI users. Obviously if the stats are only updated once every 10s.. and they are pulling out of cycle every 10s they could be "behind" by 10s. Also if the pod only lives for 9s..

What if the user does not want to pay for this 10s heartbeat thread? May affect $$ when the monitoring thread keeps alive otherwise idle nodes without having some method to disable. Not to say we don't already have keep alive monitoring probe's just sayin, does this make sense to always be on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also not clear to me that the conversation in the kubelet issue came to agreement on implementation details..

that's fair, it seems this needs more discussion and I will add it to the sig-node agenda again.

Also if the pod only lives for 9s..

This is something that isn't handled today I think. The kubelet code has a comment that If no caller calls // this function, the cpu usage will stay nil

Obviously if the stats are only updated once every 10s.. and they are pulling out of cycle every 10s they could be "behind" by 10s.

The only stat that is "cached" now is the Usagenanocores as the CRI spec defines this as

// Total CPU usage (sum of all cores) averaged over the sample window.
// The "core" unit can be interpreted as CPU core-nanoseconds per second.

The "sample window" was hard coded to 10s in kubelet but it isn't defined in the cri definition and because it isn't defined here it is the source of the problem. It needs to clearer who is responsible for generating the value over the "sample window".

@jsturtevant
Copy link
Contributor Author

let's do it with a config from the start pls.

Sounds good, wasn't sure if wanted to start with this but will make those updates, once we have more clarity

@jsturtevant
Copy link
Contributor Author

Followed up with @mikebrow and @haircommander in a short call:

  • Will adjust this to be configurable option with the default of 0 seconds which would equate to the same behavior today but can be turned on for the CRI only stats KEP in kubelet.
  • all of the CPU stats should be collected and cached at the same interval, since the time stamp is for all CPU metrics.
  • The end user will be able to choose the collection timeframe, it shouldn't matter to kubelet if it is 2 seconds or 10 seconds

@k8s-ci-robot
Copy link

PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Zero values from CPU usageNanoCores stats
5 participants