-
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
fix kube-proxy panic because of nil sessionAffinityConfig #51500
fix kube-proxy panic because of nil sessionAffinityConfig #51500
Conversation
/assign @thockin |
pkg/proxy/iptables/proxier.go
Outdated
@@ -196,7 +196,15 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *api.ServicePort, se | |||
} | |||
var stickyMaxAgeSeconds int | |||
if service.Spec.SessionAffinity == api.ServiceAffinityClientIP { | |||
stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds) | |||
// We changed the API definition that sessionAffinityConfig is required when |
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.
Isn't that set in defaulting? When we read it back from API it should get default values. Before we merge this, I need to understand why that isn't 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.
Isn't that set in defaulting? When we read it back from API it should get default values.
When we set the default value in pkg/api/v1/defaults.go, we meet the UT issues.
--- FAIL: TestRoundTripTypes (0.31s)
roundtrip.go:326: Service: diff:
object.Spec.Selector:
a: map[string]string{}
b: map[string]string(nil)
object.Spec.ExternalIPs:
a: []string{}
b: []string(nil)
object.Spec.SessionAffinityConfig:
a: <nil>
b: &api.SessionAffinityConfig{ClientIP:(*api.ClientIPConfig)(0xc420643f48)}
object.Spec.LoadBalancerSourceRanges:
a: []string{}
b: []string(nil)
object.Status.LoadBalancer.Ingress:
a: []api.LoadBalancerIngress{}
b: []api.LoadBalancerIngress(nil)
It looks like a testcase that goes through defaulting, which causes the diff to fail. Unfortunately, we don't have a great general solution to this (yet) except to patch up the test case to not depend on defaulting. Set that value explicitly.
So, we set the value explicitly which means the timeout value is required when session affinity type is client ip. For example, we set it explicitly in pkg/master/controller.go.
I guess your may refer to
// ClientIPConfig represents the configurations of Client IP based session affinity.
type ClientIPConfig struct {
// timeoutSeconds specifies the seconds of ClientIP type session sticky time.
// The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
// Default value is 10800(for 3 hours).
// +optional
TimeoutSeconds *int32
}
The comment message maybe not proper.
Sorry, I am lost. Defaulting causes round-trip failures, so you manually
specify values in a test. OK. But the defaulting still is in place, right?
How does that manifest as a nil pointer on the consumer?
…On Mon, Aug 28, 2017 at 11:52 PM, DuJun ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In pkg/proxy/iptables/proxier.go
<#51500 (comment)>
:
> @@ -196,7 +196,15 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *api.ServicePort, se
}
var stickyMaxAgeSeconds int
if service.Spec.SessionAffinity == api.ServiceAffinityClientIP {
- stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
+ // We changed the API definition that sessionAffinityConfig is required when
Isn't that set in defaulting? When we read it back from API it should get
default values.
When we set the default value in pkg/api/v1/defaults.go, we meet the UT
issues.
--- FAIL: TestRoundTripTypes (0.31s)
roundtrip.go:326: Service: diff:
object.Spec.Selector:
a: map[string]string{}
b: map[string]string(nil)
object.Spec.ExternalIPs:
a: []string{}
b: []string(nil)
object.Spec.SessionAffinityConfig:
a: <nil>
b: &api.SessionAffinityConfig{ClientIP:(*api.ClientIPConfig)(0xc420643f48)}
object.Spec.LoadBalancerSourceRanges:
a: []string{}
b: []string(nil)
object.Status.LoadBalancer.Ingress:
a: []api.LoadBalancerIngress{}
b: []api.LoadBalancerIngress(nil)
It looks like a testcase that goes through defaulting, which causes the
diff to fail. Unfortunately, we don't have a great general solution to this
(yet) except to patch up the test case to not depend on defaulting. Set
that value explicitly.
So, we set the value explicitly which means the timeout value is required
when session affinity type is client ip. For example, we set it explicitly
in pkg/master/controller.go.
I guess your may refer to
// ClientIPConfig represents the configurations of Client IP based session affinity.
type ClientIPConfig struct {
// timeoutSeconds specifies the seconds of ClientIP type session sticky time.
// The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
// Default value is 10800(for 3 hours).
// +optional
TimeoutSeconds *int32
}
The comment message maybe not proper.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#51500 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFVgVGdPZE_NhrwZ4hPDxtIIuNxfB-m8ks5sc7VCgaJpZM4PFb8X>
.
|
Because the service data is still stored in etcd - for example, service |
See https://github.com/kubernetes/kubernetes/blob/master/pkg/master/controller.go#L245 KUBE-APISERVER currently doesn't support updating session affinity config for service |
When we read it out of the API, I thought it should get defaulted again, as
it transitions from internal to versioned.
@lavalamp @cheftako ?
…On Tue, Aug 29, 2017 at 12:12 AM, DuJun ***@***.***> wrote:
How does that manifest as a nil pointer on the consumer?
Because the service data is still stored in etcd - for example, service
kubernetes. When we delete the legacy services whose session affinity
type is Client IP, kube-proxy stops panic.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#51500 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFVgVFKEy5EcFhM-lInXU1RfHDnqvWAbks5sc7nXgaJpZM4PFb8X>
.
|
Do you refer to
? I am afraid I didn't set default values here. |
6953697
to
820645c
Compare
I think I have almost found out how to fix the defaulting issue - I need to hack @thockin |
bf99220
to
4d50b4d
Compare
It's true. |
4d50b4d
to
6c609b9
Compare
pkg/api/fuzzer/fuzzer.go
Outdated
@@ -439,6 +439,14 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { | |||
ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty | |||
} | |||
} | |||
if ss.SessionAffinity == api.ServiceAffinityClientIP && ss.SessionAffinityConfig == nil { |
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.
we probably should fuzz affinity explicitly. There are many examples to follow, but basically declare a slice of valid values, pick a random number mod the length of that slice, set the value and THEN do this fixup. Basically every enumerated field should go through this.
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.
The chance of the fuzzer choosing a valid string is ~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.
ACK. Please see if the changes are fine.
PS. Since there is a restriction on affinity type and affinity config - config is required when type is ClientIP. So, I employ a temporary struct,
struct {
affinityType api.ServiceAffinity
affinityConfig *api.SessionAffinityConfig
}
to describe the relationship between them.
This was in some form of the original PR, Iknow I looked at it. Github tools ... ugh. Yes, defaulting is necessary |
6c609b9
to
cb7ba1e
Compare
/test pull-kubernetes-e2e-gce-bazel |
kindly ping @smarterclayton Can you help reviewing this PR when you have a chance? |
pkg/api/fuzzer/fuzzer.go
Outdated
@@ -439,6 +439,28 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { | |||
ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty | |||
} | |||
} | |||
|
|||
timeoutSeconds := api.DefaultClientIPServiceAffinitySeconds |
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.
if we really want to fuzz this, we should do:
possible := []string{ api.ServiceAffinityNone, api.ServiceAffinityClientIP }
ss.SessionAffinity = possible[random % len(possible)]
switch ss.SessionAffinity {
case api.ServiceAffinityClientIP:
ss.SessionAffinityConfig = new(api.SessionAffinityConfig)
ss.SessionAffinityConfig.ClientIP = new(api.ClientIPConfig)
ss.SessionAffinityConfig.ClientIP.TimeoutSeconds = random() % api.SessionAffinityMax
}
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 for your good example :)
pkg/api/v1/defaults.go
Outdated
@@ -101,6 +101,14 @@ func SetDefaults_Service(obj *v1.Service) { | |||
if obj.Spec.SessionAffinity == "" { | |||
obj.Spec.SessionAffinity = v1.ServiceAffinityNone | |||
} | |||
if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP && obj.Spec.SessionAffinityConfig == nil { |
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 forget || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == 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.
Yes, I agree. But, do you mean obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil
?
TimeoutSeconds
is *int32
type and we treat *TimeoutSeconds == 0
as an invalid value, ref: https://github.com/kubernetes/kubernetes/blob/master/pkg/api/validation/validation.go#L1913
@@ -101,6 +101,14 @@ func SetDefaults_Service(obj *v1.Service) { | |||
if obj.Spec.SessionAffinity == "" { | |||
obj.Spec.SessionAffinity = v1.ServiceAffinityNone |
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 check for ServiceAffinityNone and set SessionAffinityConfig == nil
?
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.
Currently, we will ignore SessionAffinityConfig
when ServiceAffinityNone, but I am fine to check it :)
And update tests |
cb7ba1e
to
782af87
Compare
782af87
to
0e2549c
Compare
I pushed an update. PTAL. |
0e2549c
to
617e6f4
Compare
/retest |
/lgtm |
/retest |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: m1093782566, thockin Associated issue: 51499 The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Automatic merge from submit-queue (batch tested with PRs 51819, 51706, 51761, 51818, 51500) |
What this PR does / why we need it:
fix kube-proxy panic because of nil sessionAffinityConfig
Which issue this PR fixes: closes #51499
Special notes for your reviewer:
I apology that this bug is introduced by #49850 :(
@thockin @smarterclayton @gnufied
Release note: