From 54662ca7fac2ac554c58e4faaed6593ffa513345 Mon Sep 17 00:00:00 2001 From: George Kudrayvtsev Date: Tue, 28 Nov 2017 18:04:51 -0800 Subject: [PATCH 1/3] Updates Kube-proxy validators to allow Windows 'kernelspace' mode. --- pkg/proxy/apis/kubeproxyconfig/types.go | 7 ++++--- pkg/proxy/apis/kubeproxyconfig/validation/validation.go | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/proxy/apis/kubeproxyconfig/types.go b/pkg/proxy/apis/kubeproxyconfig/types.go index d8bf19fe5f3..13c92a1a392 100644 --- a/pkg/proxy/apis/kubeproxyconfig/types.go +++ b/pkg/proxy/apis/kubeproxyconfig/types.go @@ -160,9 +160,10 @@ type KubeProxyConfiguration struct { type ProxyMode string const ( - ProxyModeUserspace ProxyMode = "userspace" - ProxyModeIPTables ProxyMode = "iptables" - ProxyModeIPVS ProxyMode = "ipvs" + ProxyModeUserspace ProxyMode = "userspace" + ProxyModeIPTables ProxyMode = "iptables" + ProxyModeIPVS ProxyMode = "ipvs" + ProxyModeKernelspace ProxyMode = "kernelspace" ) // IPVSSchedulerMethod is the algorithm for allocating TCP connections and diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go index 55bbe7930d5..cf576e564d4 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go @@ -146,9 +146,10 @@ func validateProxyMode(mode kubeproxyconfig.ProxyMode, fldPath *field.Path) fiel case kubeproxyconfig.ProxyModeUserspace: case kubeproxyconfig.ProxyModeIPTables: case kubeproxyconfig.ProxyModeIPVS: + case kubeproxyconfig.ProxyModeKernelspace: case "": default: - modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeIPTables), string(kubeproxyconfig.ProxyModeIPVS)} + modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeIPTables), string(kubeproxyconfig.ProxyModeIPVS), string(kubeproxyconfig.ProxyModeKernelspace)} errMsg := fmt.Sprintf("must be %s or blank (blank means the best-available proxy (currently iptables)", strings.Join(modes, ",")) allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) } From 234ce8da41effbc964a5c77658f279f88a639d0e Mon Sep 17 00:00:00 2001 From: George Kudrayvtsev Date: Wed, 29 Nov 2017 14:05:39 -0800 Subject: [PATCH 2/3] Makes modes OS-specific (+ fixes tests). --- pkg/proxy/apis/kubeproxyconfig/types.go | 12 +++++++----- .../apis/kubeproxyconfig/validation/validation.go | 14 +++++++++++--- .../kubeproxyconfig/validation/validation_test.go | 13 +++++++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/pkg/proxy/apis/kubeproxyconfig/types.go b/pkg/proxy/apis/kubeproxyconfig/types.go index 13c92a1a392..2a971c120d7 100644 --- a/pkg/proxy/apis/kubeproxyconfig/types.go +++ b/pkg/proxy/apis/kubeproxyconfig/types.go @@ -152,11 +152,13 @@ type KubeProxyConfiguration struct { ConfigSyncPeriod metav1.Duration } -// Currently two modes of proxying are available: 'userspace' (older, stable) or 'iptables' -// (newer, faster). If blank, use the best-available proxy (currently iptables, but may -// change in future versions). If the iptables proxy is selected, regardless of how, but -// the system's kernel or iptables versions are insufficient, this always falls back to the -// userspace proxy. +// Currently, four modes of proxying are available total: 'userspace' (older, stable), 'iptables' +// (newer, faster), 'ipvs', and 'kernelspace' (Windows only, newer). +// +// If blank, use the best-available proxy (currently iptables, but may change in +// future versions). If the iptables proxy is selected, regardless of how, but +// the system's kernel or iptables versions are insufficient, this always falls +// back to the userspace proxy. type ProxyMode string const ( diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go index cf576e564d4..4edbe92af55 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go @@ -19,6 +19,7 @@ package validation import ( "fmt" "net" + "runtime" "strconv" "strings" @@ -146,11 +147,18 @@ func validateProxyMode(mode kubeproxyconfig.ProxyMode, fldPath *field.Path) fiel case kubeproxyconfig.ProxyModeUserspace: case kubeproxyconfig.ProxyModeIPTables: case kubeproxyconfig.ProxyModeIPVS: - case kubeproxyconfig.ProxyModeKernelspace: case "": + case kubeproxyconfig.ProxyModeKernelspace: + if runtime.GOOS != "windows" { + errMsg := fmt.Sprintf("%s is only supported on Windows", string(kubeproxyconfig.ProxyModeKernelspace)) + allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) + } default: - modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeIPTables), string(kubeproxyconfig.ProxyModeIPVS), string(kubeproxyconfig.ProxyModeKernelspace)} - errMsg := fmt.Sprintf("must be %s or blank (blank means the best-available proxy (currently iptables)", strings.Join(modes, ",")) + modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeIPTables), string(kubeproxyconfig.ProxyModeIPVS)} + if runtime.GOOS == "windows" { + modes = append(modes, string(kubeproxyconfig.ProxyModeKernelspace)) + } + errMsg := fmt.Sprintf("must be %s or blank (blank means the best-available proxy [currently iptables])", strings.Join(modes, ",")) allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) } return allErrs diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go index f316a304462..b3498264fed 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go @@ -18,6 +18,7 @@ package validation import ( "fmt" + "runtime" "strings" "testing" "time" @@ -488,11 +489,15 @@ func TestValidateProxyMode(t *testing.T) { newPath := field.NewPath("KubeProxyConfiguration") successCases := []kubeproxyconfig.ProxyMode{ kubeproxyconfig.ProxyModeUserspace, - kubeproxyconfig.ProxyModeIPTables, - kubeproxyconfig.ProxyModeIPVS, kubeproxyconfig.ProxyMode(""), } + if runtime.GOOS == "windows" { + successCases = append(successCases, kubeproxyconfig.ProxyModeKernelspace) + } else { + successCases = append(successCases, kubeproxyconfig.ProxyModeIPTables, kubeproxyconfig.ProxyModeIPVS) + } + for _, successCase := range successCases { if errs := validateProxyMode(successCase, newPath.Child("ProxyMode")); len(errs) != 0 { t.Errorf("expected success: %v", errs) @@ -505,13 +510,13 @@ func TestValidateProxyMode(t *testing.T) { }{ { mode: kubeproxyconfig.ProxyMode("non-existing"), - msg: "or blank (blank means the best-available proxy (currently iptables)", + msg: "or blank (blank means the best-available proxy [currently iptables])", }, } for _, errorCase := range errorCases { if errs := validateProxyMode(errorCase.mode, newPath.Child("ProxyMode")); len(errs) == 0 { - t.Errorf("expected failure for %s", errorCase.msg) + t.Errorf("expected failure %s for %v", errorCase.msg, errorCase.mode) } else if !strings.Contains(errs[0].Error(), errorCase.msg) { t.Errorf("unexpected error: %v, expected: %s", errs[0], errorCase.msg) } From e48b6f3d157a040e73a3658605c6cc12fdddee0c Mon Sep 17 00:00:00 2001 From: George Kudrayvtsev Date: Mon, 4 Dec 2017 16:57:31 -0800 Subject: [PATCH 3/3] Separates validation per-runtime. --- .../kubeproxyconfig/validation/validation.go | 31 ++++++++++++++----- .../validation/validation_test.go | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go index 4edbe92af55..376d281c9d8 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go @@ -142,28 +142,43 @@ func validateKubeProxyConntrackConfiguration(config kubeproxyconfig.KubeProxyCon } func validateProxyMode(mode kubeproxyconfig.ProxyMode, fldPath *field.Path) field.ErrorList { + if runtime.GOOS == "windows" { + return validateProxyModeWindows(mode, fldPath) + } + + return validateProxyModeLinux(mode, fldPath) +} + +func validateProxyModeLinux(mode kubeproxyconfig.ProxyMode, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + switch mode { case kubeproxyconfig.ProxyModeUserspace: case kubeproxyconfig.ProxyModeIPTables: case kubeproxyconfig.ProxyModeIPVS: case "": - case kubeproxyconfig.ProxyModeKernelspace: - if runtime.GOOS != "windows" { - errMsg := fmt.Sprintf("%s is only supported on Windows", string(kubeproxyconfig.ProxyModeKernelspace)) - allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) - } default: modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeIPTables), string(kubeproxyconfig.ProxyModeIPVS)} - if runtime.GOOS == "windows" { - modes = append(modes, string(kubeproxyconfig.ProxyModeKernelspace)) - } errMsg := fmt.Sprintf("must be %s or blank (blank means the best-available proxy [currently iptables])", strings.Join(modes, ",")) allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) } return allErrs } +func validateProxyModeWindows(mode kubeproxyconfig.ProxyMode, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + switch mode { + case kubeproxyconfig.ProxyModeUserspace: + case kubeproxyconfig.ProxyModeKernelspace: + default: + modes := []string{string(kubeproxyconfig.ProxyModeUserspace), string(kubeproxyconfig.ProxyModeKernelspace)} + errMsg := fmt.Sprintf("must be %s or blank (blank means the most-available proxy [currently userspace])", strings.Join(modes, ",")) + allErrs = append(allErrs, field.Invalid(fldPath.Child("ProxyMode"), string(mode), errMsg)) + } + return allErrs +} + func validateClientConnectionConfiguration(config kubeproxyconfig.ClientConnectionConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(config.Burst), fldPath.Child("Burst"))...) diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go index b3498264fed..2736e53af66 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go @@ -510,7 +510,7 @@ func TestValidateProxyMode(t *testing.T) { }{ { mode: kubeproxyconfig.ProxyMode("non-existing"), - msg: "or blank (blank means the best-available proxy [currently iptables])", + msg: "or blank (blank means the", }, }