fix kube-proxy panic

This commit is contained in:
m1093782566 2017-08-29 14:28:40 +08:00
parent c071a77156
commit 1faa6f56b9
6 changed files with 72 additions and 1 deletions

View File

@ -439,6 +439,19 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty
}
}
types := []api.ServiceAffinity{api.ServiceAffinityNone, api.ServiceAffinityClientIP}
ss.SessionAffinity = types[c.Rand.Intn(len(types))]
switch ss.SessionAffinity {
case api.ServiceAffinityClientIP:
timeoutSeconds := int32(c.Rand.Intn(int(api.MaxClientIPServiceAffinitySeconds)))
ss.SessionAffinityConfig = &api.SessionAffinityConfig{
ClientIP: &api.ClientIPConfig{
TimeoutSeconds: &timeoutSeconds,
},
}
case api.ServiceAffinityNone:
ss.SessionAffinityConfig = nil
}
},
func(n *api.Node, c fuzz.Continue) {
c.FuzzNoCustom(n)

View File

@ -101,6 +101,19 @@ func SetDefaults_Service(obj *v1.Service) {
if obj.Spec.SessionAffinity == "" {
obj.Spec.SessionAffinity = v1.ServiceAffinityNone
}
if obj.Spec.SessionAffinity == v1.ServiceAffinityNone {
obj.Spec.SessionAffinityConfig = nil
}
if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
if obj.Spec.SessionAffinityConfig == nil || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
obj.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
ClientIP: &v1.ClientIPConfig{
TimeoutSeconds: &timeoutSeconds,
},
}
}
}
if obj.Spec.Type == "" {
obj.Spec.Type = v1.ServiceTypeClusterIP
}

View File

@ -667,11 +667,53 @@ func TestSetDefaultService(t *testing.T) {
if svc2.Spec.SessionAffinity != v1.ServiceAffinityNone {
t.Errorf("Expected default session affinity type:%s, got: %s", v1.ServiceAffinityNone, svc2.Spec.SessionAffinity)
}
if svc2.Spec.SessionAffinityConfig != nil {
t.Errorf("Expected empty session affinity config when session affinity type: %s, got: %v", v1.ServiceAffinityNone, svc2.Spec.SessionAffinityConfig)
}
if svc2.Spec.Type != v1.ServiceTypeClusterIP {
t.Errorf("Expected default type:%s, got: %s", v1.ServiceTypeClusterIP, svc2.Spec.Type)
}
}
func TestSetDefaultServiceSessionAffinityConfig(t *testing.T) {
testCases := map[string]v1.Service{
"SessionAffinityConfig is empty": {
Spec: v1.ServiceSpec{
SessionAffinity: v1.ServiceAffinityClientIP,
SessionAffinityConfig: nil,
},
},
"ClientIP is empty": {
Spec: v1.ServiceSpec{
SessionAffinity: v1.ServiceAffinityClientIP,
SessionAffinityConfig: &v1.SessionAffinityConfig{
ClientIP: nil,
},
},
},
"TimeoutSeconds is empty": {
Spec: v1.ServiceSpec{
SessionAffinity: v1.ServiceAffinityClientIP,
SessionAffinityConfig: &v1.SessionAffinityConfig{
ClientIP: &v1.ClientIPConfig{
TimeoutSeconds: nil,
},
},
},
},
}
for name, test := range testCases {
obj2 := roundTrip(t, runtime.Object(&test))
svc2 := obj2.(*v1.Service)
if svc2.Spec.SessionAffinityConfig == nil || svc2.Spec.SessionAffinityConfig.ClientIP == nil || svc2.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
t.Fatalf("Case: %s, unexpected empty SessionAffinityConfig/ClientIP/TimeoutSeconds when session affinity type: %s, got: %v", name, v1.ServiceAffinityClientIP, svc2.Spec.SessionAffinityConfig)
}
if *svc2.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds != v1.DefaultClientIPServiceAffinitySeconds {
t.Errorf("Case: %s, default TimeoutSeconds should be %d when session affinity type: %s, got: %d", name, v1.DefaultClientIPServiceAffinitySeconds, v1.ServiceAffinityClientIP, *svc2.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
}
}
}
func TestSetDefaultSecretVolumeSource(t *testing.T) {
s := v1.PodSpec{}
s.Volumes = []v1.Volume{

View File

@ -196,6 +196,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *api.ServicePort, se
}
var stickyMaxAgeSeconds int
if service.Spec.SessionAffinity == api.ServiceAffinityClientIP {
// Kube-apiserver side guarantees SessionAffinityConfig won't be nil when session affinity type is ClientIP
stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
}
info := &serviceInfo{

View File

@ -448,7 +448,7 @@ func (proxier *Proxier) mergeService(service *api.Service) sets.String {
info.loadBalancerStatus = *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer)
info.nodePort = int(servicePort.NodePort)
info.sessionAffinityType = service.Spec.SessionAffinity
// Set session affinity timeout value when sessionAffinity==ClientIP
// Kube-apiserver side guarantees SessionAffinityConfig won't be nil when session affinity type is ClientIP
if service.Spec.SessionAffinity == api.ServiceAffinityClientIP {
info.stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
}

View File

@ -2998,6 +2998,8 @@ const (
ServiceAffinityNone ServiceAffinity = "None"
)
const DefaultClientIPServiceAffinitySeconds int32 = 10800
// SessionAffinityConfig represents the configurations of session affinity.
type SessionAffinityConfig struct {
// clientIP contains the configurations of Client IP based session affinity.