-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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
Promotes Source IP preservation for Virtual IPs from Beta to GA #41162
Conversation
da4410b
to
bf27c47
Compare
pkg/api/service/annotations.go
Outdated
AnnotationValueExternalTrafficGlobal = "Global" | ||
|
||
// TODO: The alpha annotations have been deprecated, remove them when we move this feature to GA. | ||
// TODO: The beta annotations have been deprecated, remove them when we release k8s 1.7. |
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.
You'll have to send a notice to kubernetes-announce, too
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.
Sure, made a note for this.
pkg/api/service/util.go
Outdated
// If they transition to the first class field, there's no way to go back to beta without | ||
// rolling back the cluster. | ||
if l, ok := service.Annotations[BetaAnnotationExternalTraffic]; ok { | ||
if l == string(api.ServiceExternalTrafficTypeOnlyLocal) { |
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.
This would read better as a switch
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/api/types.go
Outdated
// local endpoints only. This preserves Source IP and avoids a second hop for | ||
// LoadBalancer and Nodeport type services. | ||
// +optional | ||
ExternalTraffic ServiceExternalTrafficType |
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 in love with the naming around this feature (never was). Can we think of anything more expressive?
Maybe externalTrafficPolicy: Local
or something a little less awkward?
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.
Sounds good, so the candidates would be:
externalTrafficPolicy: Local
externalTrafficPolicy: Global
And do we want to use externalTrafficPolicy: None
for the other service types (not NodePort or LoadBalancer)? This field is now being defaulted to empty string ("").
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 guess "" is appropriate for those cases. Defaulting (and update) should detect LoadBalancer and NodePort and choose "Global", I think. Thoughts? If we do that then we really should change it back to "" if the type is updated to anything else.
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.
Yeah I have the same thought.
function defaultExternalTrafficIfNeeded() exists for defaulting this field to Global for LoadBalancer and NodePort service if this field is not set.
And function externalTrafficUpdate() exists for changing this field back to "" when the type is updated to others (not LoadBalancer nor NodePort).
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.
Changed to use externalTrafficPolicy: Local or Global
.
pkg/api/validation/validation.go
Outdated
// Validate ExternalTraffic and HealthCheckNodePort have legal value. | ||
if service.Spec.HealthCheckNodePort < 0 { | ||
allErrs = append(allErrs, field.Invalid(specPath.Child("healthCheckNodePort"), service.Spec.HealthCheckNodePort, | ||
"can not set HealthCheckNodePort to negative value")) |
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.
error messages should be positive: "must be greater than 0"
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/api/validation/validation.go
Outdated
allErrs = append(allErrs, field.Invalid(specPath.Child("healthCheckNodePort"), service.Spec.HealthCheckNodePort, | ||
"can not set HealthCheckNodePort to negative value")) | ||
} | ||
if service.Spec.ExternalTraffic != "" && |
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 is "" allowed? won't defaulting set it to a sane value?
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.
Yeah I also think this is inappropriate. I'm changing the default value to None.
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.
Updates...Per discussion above, "" might be allowed for service that does not have LoadBalancer or NodePort type.
pkg/api/validation/validation.go
Outdated
service.Spec.Type != api.ServiceTypeNodePort && | ||
service.Spec.ExternalTraffic != "" { | ||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "externalTraffic"), service.Spec.ExternalTraffic, | ||
"can only be set on nodePort / loadBalancer service")) |
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.
NodePort and LoadBalancer
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/api/validation/validation.go
Outdated
(service.Spec.Type != api.ServiceTypeLoadBalancer || | ||
service.Spec.ExternalTraffic != api.ServiceExternalTrafficTypeOnlyLocal) { | ||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "healthCheckNodePort"), service.Spec.ExternalTraffic, | ||
"can only be set on loadBalancer service with ExternalTraffic=OnlyLocal")) |
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.
LoadBalancer
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/api/validation/validation.go
Outdated
|
||
_, healthCheckBetaOk := service.Annotations[apiservice.BetaAnnotationHealthCheckNodePort] | ||
_, onlyLocalBetaOk := service.Annotations[apiservice.BetaAnnotationExternalTraffic] | ||
type serviceExternalTrafficAnnotationsUpdateStatus struct { |
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.
comments?
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/api/validation/validation.go
Outdated
// to first class fields before making any modifications, even though the | ||
// system continues to respect the beta version. | ||
|
||
// On upgrading to a 1.6 cluster, the user is locked in at the current |
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 sure I get this. Why do we need to stop users from creating new instances with the beta annotation - this is a breaking change, and I don't think we can allow it. Beta has to keep working for at least 1 release, and that means fully working.
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 wanted to say up-conversion, but saw your old comment about it. Supporting beta annotations for one more release seems to be the right thing to do. I will re-think this part.
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.
Yeah, we should not up-convert
@bprashanth - when this went Beta I raised an issue wrt healthchecks and NodePort. I can't find the comment - do you recall what the issue I raised was? |
5d037ff
to
7825dcf
Compare
Per discussion above, updated to fully support both ESIPP Beta annotations and first class fields:
|
cc @freehan who might also be familiar with ESIPP validation :) |
Rebased. Note that most of the worth-looking-at changes are in the first two commits :) |
/assign @freehan Many thanks for helping out! |
Rebased :) @freehan Any changes to take a 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.
Looks good overall. Some nits.
pkg/api/service/util.go
Outdated
continue | ||
} | ||
return int32(p) | ||
// First check the beta annotation and then the first class field. This is so |
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.
nit: s/This is so/so that
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/api/service/util.go
Outdated
|
||
// ClearExternalTrafficPolicy resets the ExternalTrafficPolicy field. | ||
func ClearExternalTrafficPolicy(service *api.Service) { | ||
// First check the beta annotation and then the first class field. This is so existing |
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.
same here
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/api/service/util.go
Outdated
// SetServiceHealthCheckNodePort sets the given health check node port on service. | ||
// It does not check whether this service needs healthCheckNodePort. | ||
func SetServiceHealthCheckNodePort(service *api.Service, hcNodePort int32) { | ||
// First check the beta annotation and then the first class field. This is so existing |
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.
same here
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/api/service/util.go
Outdated
// DefaultExternalTrafficPolicyIfNeeded defaults the ExternalTrafficPolicy field | ||
// for NodePort / LoadBalancer service to Global for consistency. | ||
// TODO: Move this default logic to default.go once beta annotation is deprecated. | ||
func DefaultExternalTrafficPolicyIfNeeded(service *api.Service) { |
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.
nit: s/DefaultExternalTrafficPolicyIfNeeded/SetDefaultExternalTrafficPolicyIfNeeded
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/api/v1/service/util.go
Outdated
// DefaultExternalTrafficPolicyIfNeeded defaults the ExternalTrafficPolicy field | ||
// for NodePort / LoadBalancer service to Global for consistency. | ||
// TODO: Move this default logic to default.go once beta annotation is deprecated. | ||
func DefaultExternalTrafficPolicyIfNeeded(service *v1.Service) { |
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.
nit: s/DefaultExternalTrafficPolicyIfNeeded/SetDefaultExternalTrafficPolicyIfNeeded
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.
// have legal value. | ||
func validateServiceExternalTrafficFields(service *api.Service) field.ErrorList { | ||
func validateServiceExternalTrafficFieldsValue(service *api.Service) field.ErrorList { |
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.
Not sure if it is relevant.
Is it allowed to use healthcheck node port with Global?
Is it allowed to mixa usage of beta annotation and fields? (I think annotaion is preempting, so we do not care? )
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.
Is it allowed to use healthcheck node port with Global?
Nope, we disallow this case in ValidateServiceExternalTrafficFieldsCombination().
Is it allowed to mixa usage of beta annotation and fields? (I think annotaion is preempting, so we do not care? )
Nope, we disallow this case in validateServiceExternalTrafficAPIVersion().
Sorry for the mess, but I have to separate the validation into multiple pieces because they are called in different phases --- especially ValidateServiceExternalTrafficFieldsCombination() needs to be called after defaulting and resetting ESIPP fields :(
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! WIll address the comments soon.
// have legal value. | ||
func validateServiceExternalTrafficFields(service *api.Service) field.ErrorList { | ||
func validateServiceExternalTrafficFieldsValue(service *api.Service) field.ErrorList { |
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.
Is it allowed to use healthcheck node port with Global?
Nope, we disallow this case in ValidateServiceExternalTrafficFieldsCombination().
Is it allowed to mixa usage of beta annotation and fields? (I think annotaion is preempting, so we do not care? )
Nope, we disallow this case in validateServiceExternalTrafficAPIVersion().
Sorry for the mess, but I have to separate the validation into multiple pieces because they are called in different phases --- especially ValidateServiceExternalTrafficFieldsCombination() needs to be called after defaulting and resetting ESIPP fields :(
/lgtm |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: MrHohn, freehan Assign the PR to them by writing
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Thanks! Squashing commits. |
Automatic merge from submit-queue (batch tested with PRs 45623, 45241, 45460, 41162) |
Automatic merge from submit-queue [Federation] Fix federated service reconcilation issue due to addition of External… …TrafficPolicy field to v1.Service **What this PR does / why we need it**: New fields (ExternalTrafficPolicy) are introduced to v1.Service by this PR #41162. If this field is not specified in service spec, the service controller will assign default and updates the service spec. In federation, the service spec is not updated and we continuously try to reconcile as the federated service and the service in federated cluster do not match. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #45795 **Special notes for your reviewer**: **Release note**: ``` NONE ``` cc @kubernetes/sig-federation-bugs @madhusudancs
Fixes #33625. Feature issue: kubernetes/enhancements#27.
Bullet points:
Release note: