-
Notifications
You must be signed in to change notification settings - Fork 40.2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Introduce trafficDistribution field for Kubernetes Services #123487
Conversation
/assign @danwinship |
This PR may require API review. If so, when the changes are ready, complete the pre-review checklist and request an API review. Status of requested reviews is tracked in the API Review project. |
Changelog suggestion -A new field, `trafficDistribution`, has been added to the Service `spec`. This field provides a way to express preferences for how traffic is distributed to Service endpoints. It can be enabled through the `ServiceTrafficDistribution` feature gate.
+A new (alpha) field, `trafficDistribution`, has been added to the Service `spec`.
+This field provides a way to express preferences for how traffic is distributed to the endpoints for a Service.
+It can be enabled through the `ServiceTrafficDistribution` feature gate. |
12b9f20
to
a7f4767
Compare
func validateServiceTrafficDistribution(service *core.Service) field.ErrorList { | ||
allErrs := field.ErrorList{} | ||
|
||
if service.Spec.TrafficDistribution == nil || *service.Spec.TrafficDistribution == "" { |
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.
ok, it seems we are not going to use Default
value and use nil as Default, I was thinking that was the best option too, and it is easy to implementn backwards compatibility and skew support
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.
Yep that is the case!
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.
Re-open.
I'm not sure unspecified makes sense in the new naming, and if it does make sense we should not equate "" with unspecified. "" is a value.
func endpointReady(endpoint discoveryv1.Endpoint) bool { | ||
return endpoint.Conditions.Ready != nil && *endpoint.Conditions.Ready | ||
} |
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.
How will this play with terminating endpoints @robscott ?
The feature is critical for rolling updates, I think is fair to say that users will expect it to keep working once hints are enabled, do we need to consider them for the hints or just only in the proxy implementation?
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.
ok, it is answered later in the unit tests https://github.com/kubernetes/kubernetes/pull/123487/files#r1503894252, it seems externalTrafficPolicy Local disable hints
@@ -50,6 +51,9 @@ type Reconciler struct { | |||
// topologyCache tracks the distribution of Nodes and endpoints across zones | |||
// to enable TopologyAwareHints. | |||
topologyCache *topologycache.TopologyCache | |||
// trafficDistributionEnabled determines if endpointDistribution field is to | |||
// be considered when reconciling EndpointSlice hints. | |||
trafficDistributionEnabled bool |
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.
do we need to make this an option?
if this is going to be a field this will be assumed to be always true and governed by the feature gate until then,
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.
By "option", did you mean something like reconciler := NewReconciler(other_params, WithTrafficDistributionEnabled())
?
- If not, can you please elaborate? Yes the idea here was for this to be a featuregate equivalent, similar to what
topologyCache
does for topology hints to some extend...niltopologyCache
means feature gate is disabled. - If yes, doesn't it needlessly make this more complex for just one option?
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.
in the future when the feature gate graduates this will be always true, bceause the feature will be removed, so no need to pass a parameter
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 think the question is: why is the feature gate passed as an argument to the reconciler? is it because feature module is not available to k8s.io/endpointslice
?
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 think the question is: why is the feature gate passed as an argument to the reconciler? is it because feature module is not available to k8s.io/endpointslice?
@khenidak -- Yes that is the intent -- the package is used independently as well (outside the kube-controller-manager binary), which means it's not helpful to explicitly create a dependency from the k8s.io/endpointslice
package to the featuregates. Hence the need to pass a flag.
in the future when the feature gate graduates this will be always true, bceause the feature will be removed, so no need to pass a parameter
@aojea -- Thanks I understood the intent and have made the change. My thoughts initially were to eventually remove this additional parameter from NewReconciler
when it is not needed -- I was hoping such change to the package's API surface should be one which independent users of this package can easily accommodate. But I agree if we can avoid such things at lower cost, then why not.
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.
changes to public apis are disruptive for users as they conflict when they revendor,
if endpoint.Zone != nil { | ||
zone = *endpoint.Zone | ||
} | ||
slice.Endpoints[i].Hints = &discoveryv1.EndpointHints{ForZones: []discoveryv1.ForZone{{Name: zone}}} |
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.
s/slice.Endpoints[i].Hints/endpoint.Hints/
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.
also, are we ok with empty hints?
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.
s/slice.Endpoints[i].Hints/endpoint.Hints/
The intent is to modify the value in the slice. Using endpoint.Hints
would just modify the copied endpoint
(and not the one in the slice), which would be incorrect.
also, are we ok with empty hints?
Yes you are right, we would be okay with that!
|
||
// needsUpdate returns true if any ready endpoint in the slice has a | ||
// missing or incorrect hint. | ||
func (preferCloseHeuristic) needsUpdate(slice *discoveryv1.EndpointSlice) bool { |
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.
why do we need to separate needsUpdate(..)
and update(..)
?
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 question! The answer to this is how ReconcileHints
is structured:
needsUpdate
helps us decide when an endpointslice needs update so that we can deepcopy it (and not modify the original)update
helps us modify the an EndpointSlice inplace.
There is a case where we DON'T need to deepcopy and just modify the original EndpointSlice (viz. slicesToCreate
), so having this separation helps us use them independently.
/unhold Added the "options" construct. Would need an lgtm again from someone here :) |
/unhold |
…ficDistributionEnabled field
fe082b7
to
ec6fd2b
Compare
/lgtm |
LGTM label has been added. Git tree hash: bdec775adc250a85d8f2bbdaa8e1df7c9827bac3
|
I think we need to find a way to offer PreferNode, and I'd prefer (ha!) not to have 4 different traffic-control knobs. |
/test pull-kubernetes-node-e2e-containerd |
I think we should be able to use the Assuming if I'm understanding the concern correctly, on the question of whether:
...this exact thing is something we've delved into in the past at Pulling in the thoughts from that conversation here for a more structured comparision of the choice we have made (viz. defining PreferClosePros
Cons
If we really treat this as a valid-concern, a possible solution here would be an introduction of an implementaiton specific heuristic for kube-proxy to deliver prefer-node-behaviour (something like PreferZoneProsThe advantage with only having precise terms like ConsThis choice forces smarter implementations to only be able to deliver prefer-zone-behaviour, even though they could have delivered a a prefer-node-and-waterfall-based-on-load-behaviour. The implementation would either have to:
|
There's a new field called "trafficDistribution" in k/k, whose e2e test needs 3 zones. kubernetes/kubernetes#123487 Signed-off-by: Zhecheng Li <zhechengli@microsoft.com>
There's a new field called "trafficDistribution" in k/k, whose e2e test needs 3 zones. feature: kubernetes/kubernetes#123487 e2e: kubernetes/kubernetes#123812 Signed-off-by: Zhecheng Li <zhechengli@microsoft.com>
KEP-4444 link is changed. |
What type of PR is this?
/kind feature
/kind api-change
What this PR does / why we need it:
This is an initial implementation of the changes discussed in KEP-4444 (new field offering greater control over traffic distribution to Service endpoints)
Special notes for your reviewer:
We were planning on finalizing the names during the implementation. Given no one liked the initial field name (
routingPreference
), I've choosen a different one from the discussions:Field name:
trafficDistribution
Allowed values:
PreferClose
(not specifying any value results in default behaviour)Does this PR introduce a user-facing change?
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:
/sig network
/priority important-soon