-
Notifications
You must be signed in to change notification settings - Fork 38.7k
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
Start exporting the in-cluster network programming latency metric. #71999
Conversation
@MateuszMatejczyk: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. 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. |
Hi @MateuszMatejczyk. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
/assign @wojtek-t |
/assign @wojtek-t |
I will do the first pass later this week and then will add more reviewers from networking team. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkg/proxy/endpoints.go
Outdated
} | ||
return len(ect.items) > 0 | ||
} | ||
|
||
func getLastChangeTriggerTime(endpoints *v1.Endpoints) time.Time { | ||
val, _ := time.Parse(time.RFC3339Nano, endpoints.Annotations[v1.EndpointsLastChangeTriggerTime]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't silently ignore errors - if not more, at least log an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added log statement and a comment explaining why we can ignore the error.
/hold cancel With endpoint controller changes already being merged, we are ready to resurrect this change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, PTAL
pkg/proxy/endpoints.go
Outdated
@@ -30,6 +30,7 @@ import ( | |||
"k8s.io/client-go/tools/record" | |||
utilproxy "k8s.io/kubernetes/pkg/proxy/util" | |||
utilnet "k8s.io/kubernetes/pkg/util/net" | |||
"time" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
pkg/proxy/endpoints_test.go
Outdated
@@ -26,6 +26,8 @@ import ( | |||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |||
"k8s.io/apimachinery/pkg/types" | |||
"k8s.io/apimachinery/pkg/util/sets" | |||
"time" | |||
"sort" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
pkg/proxy/endpoints.go
Outdated
@@ -92,6 +93,9 @@ type EndpointChangeTracker struct { | |||
// isIPv6Mode indicates if change tracker is under IPv6/IPv4 mode. Nil means not applicable. | |||
isIPv6Mode *bool | |||
recorder record.EventRecorder | |||
// Map from the Endpoints namespaced-name to the time of the trigger that caused the endpoints | |||
// object to change. Used to calculate the network-programming-latency. | |||
lastChangeTriggerTimes map[types.NamespacedName]time.Time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
Added in the documentation of the metric that exports the Network Programming Latency.
} | ||
change.current = ect.endpointsToEndpointsMap(current) | ||
// if change.previous equal to change.current, it means no change | ||
if reflect.DeepEqual(change.previous, change.current) { | ||
delete(ect.items, namespacedName) | ||
delete(ect.lastChangeTriggerTimes, namespacedName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, the situation you described is something like this:
T0: proxier.Sync()
T1: proxier observes Endpoints E1 change, E1.EndpointsLastChangeTriggerTime = t0
T2: proxier observes Endpoints E1 change, E1.EndpointsLastChangeTriggerTime = t1 (t1>=t0)
T3: proxier.Sync()
In such case the implementation will ignore the second timestamp and use t0 (which is guaranteed to be <= t1) to measure the latency.
Let me know if it makes sense.
Name: "network_programming_latency_seconds", | ||
Help: "In Cluster Network Programming Latency in seconds", | ||
// The last bucket will be [0.001s*2^20 ~= 17min, +inf) | ||
Buckets: prometheus.ExponentialBuckets(0.001, 2, 20), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced that the buckets are correct.
I'm fine with leaving it as is for now, but please leave a TODO to reevaluate it before 1.14 release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two more comments - other than that lgtm.
That LGTM. @freehan - can you please take another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a nit, LGTM overall
pkg/proxy/endpoints.go
Outdated
// Reset the lastChangeTriggerTimes for the Endpoints object. Given that the network programming | ||
// SLI is defined as the duration between a time of an event and a time when the network was | ||
// programmed to incorporate that event, if there are events that happened between two | ||
// consecutive syncs syncs and that canceled each other out, e.g. pod A added -> pod A deleted, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 syncs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, done.
} | ||
change.current = ect.endpointsToEndpointsMap(current) | ||
// if change.previous equal to change.current, it means no change | ||
if reflect.DeepEqual(change.previous, change.current) { | ||
delete(ect.items, namespacedName) | ||
delete(ect.lastChangeTriggerTimes, namespacedName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Noop sounds good.
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: mm4tt, 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 |
/retest |
@mm4tt: The following test failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. 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. I understand the commands that are listed here. |
/retest |
The DNS Programming Latency defintion can be found [here](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/dns_programming_latency.md) This PR covers only "headless with selector" services, other service kinds are blocked on the impossibility of determining the LastUpdateTime of a service object. The PR bears some similarities to kubernetes/kubernetes#71999, which introdced In-Cluster Network Programming Latency. The main difference is that there is no actual "programming" happening in CoreDNS (for comparison, in kube-proxy the network programming consists of writing IPTables/IPVS rules). The CoreDNS serves the content directly from the endpoints/service/pod cache, creating DNS records on the fly. Thus, we assume that the programming of DNS ends in the moment when the endpoints/service/pod change reaches the CoreDNS via the Watch mechanism.
The DNS Programming Latency definition can be found [here](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/dns_programming_latency.md) This PR covers only "headless with selector" services, other service kinds are blocked on the impossibility of determining the LastUpdateTime of a service object. The PR bears some similarities to kubernetes/kubernetes#71999, which introdced In-Cluster Network Programming Latency. The main difference is that there is no actual "programming" happening in CoreDNS (for comparison, in kube-proxy the network programming consists of writing IPTables/IPVS rules). The CoreDNS serves the content directly from the endpoints/service/pod cache, creating DNS records on the fly. Thus, we assume that the programming of DNS ends in the moment when the endpoints/service/pod change reaches the CoreDNS via the Watch mechanism.
The DNS Programming Latency definition can be found [here](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/dns_programming_latency.md) This PR covers only "headless with selector" services, other service kinds are blocked on the impossibility of determining the LastUpdateTime of a service object. The PR bears some similarities to kubernetes/kubernetes#71999, which introdced In-Cluster Network Programming Latency. The main difference is that there is no actual "programming" happening in CoreDNS (for comparison, in kube-proxy the network programming consists of writing IPTables/IPVS rules). The CoreDNS serves the content directly from the endpoints/service/pod cache, creating DNS records on the fly. Thus, we assume that the programming of DNS ends in the moment when the endpoints/service/pod change reaches the CoreDNS via the Watch mechanism.
The DNS Programming Latency definition can be found [here](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/dns_programming_latency.md) This PR covers only "headless with selector" services, other service kinds are blocked on the impossibility of determining the LastUpdateTime of a service object. The PR bears some similarities to kubernetes/kubernetes#71999, which introdced In-Cluster Network Programming Latency. The main difference is that there is no actual "programming" happening in CoreDNS (for comparison, in kube-proxy the network programming consists of writing IPTables/IPVS rules). The CoreDNS serves the content directly from the endpoints/service/pod cache, creating DNS records on the fly. Thus, we assume that the programming of DNS ends in the moment when the endpoints/service/pod change reaches the CoreDNS via the Watch mechanism.
What type of PR is this?
/kind feature
What this PR does / why we need it:
This is the final step of implementing the first version of in-cluster network programming latency that was proposed here - https://github.com/kubernetes/community/blob/master/sig-scalability/slos/network_programming_latency.md
The computation of the latency is based on the EndpointsLastChangeTriggerTime annotation, which implementation can be found in #71998
Does this PR introduce a user-facing change?:
NONE