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) }