mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
Add a new package for handling all ComponentConfig-related code
This commit is contained in:
parent
5028577360
commit
f96ada0c04
120
cmd/kubeadm/app/componentconfigs/defaults.go
Normal file
120
cmd/kubeadm/app/componentconfigs/defaults.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package componentconfigs
|
||||||
|
|
||||||
|
import (
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||||
|
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
|
||||||
|
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||||
|
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file
|
||||||
|
KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultKubeProxyConfiguration assigns default values for the kube-proxy ComponentConfig
|
||||||
|
func DefaultKubeProxyConfiguration(internalcfg *kubeadmapi.MasterConfiguration) {
|
||||||
|
// IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go
|
||||||
|
// and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go. TODO: Remove this requirement when v1alpha2 is removed.
|
||||||
|
externalproxycfg := &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
|
||||||
|
|
||||||
|
// Do a roundtrip to the external version for defaulting
|
||||||
|
Scheme.Convert(internalcfg.ComponentConfigs.KubeProxy, externalproxycfg, nil)
|
||||||
|
|
||||||
|
if externalproxycfg.ClusterCIDR == "" && internalcfg.Networking.PodSubnet != "" {
|
||||||
|
externalproxycfg.ClusterCIDR = internalcfg.Networking.PodSubnet
|
||||||
|
}
|
||||||
|
|
||||||
|
if externalproxycfg.ClientConnection.KubeConfigFile == "" {
|
||||||
|
externalproxycfg.ClientConnection.KubeConfigFile = KubeproxyKubeConfigFileName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the rest of the kube-proxy defaulting code
|
||||||
|
kubeproxyconfigv1alpha1.SetDefaults_KubeProxyConfiguration(externalproxycfg)
|
||||||
|
|
||||||
|
if internalcfg.ComponentConfigs.KubeProxy == nil {
|
||||||
|
internalcfg.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Figure out how to handle errors in defaulting code
|
||||||
|
// Go back to the internal version
|
||||||
|
Scheme.Convert(externalproxycfg, internalcfg.ComponentConfigs.KubeProxy, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultKubeletConfiguration assigns default values for the kubelet ComponentConfig
|
||||||
|
func DefaultKubeletConfiguration(internalcfg *kubeadmapi.MasterConfiguration) {
|
||||||
|
// IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go
|
||||||
|
// and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go. TODO: Remove this requirement when v1alpha2 is removed.
|
||||||
|
externalkubeletcfg := &kubeletconfigv1beta1.KubeletConfiguration{}
|
||||||
|
|
||||||
|
// Do a roundtrip to the external version for defaulting
|
||||||
|
Scheme.Convert(internalcfg.ComponentConfigs.Kubelet, externalkubeletcfg, nil)
|
||||||
|
|
||||||
|
if externalkubeletcfg.StaticPodPath == "" {
|
||||||
|
externalkubeletcfg.StaticPodPath = kubeadmapiv1alpha3.DefaultManifestsDir
|
||||||
|
}
|
||||||
|
if externalkubeletcfg.ClusterDNS == nil {
|
||||||
|
dnsIP, err := constants.GetDNSIP(internalcfg.Networking.ServiceSubnet)
|
||||||
|
if err != nil {
|
||||||
|
externalkubeletcfg.ClusterDNS = []string{kubeadmapiv1alpha3.DefaultClusterDNSIP}
|
||||||
|
} else {
|
||||||
|
externalkubeletcfg.ClusterDNS = []string{dnsIP.String()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if externalkubeletcfg.ClusterDomain == "" {
|
||||||
|
externalkubeletcfg.ClusterDomain = internalcfg.Networking.DNSDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce security-related kubelet options
|
||||||
|
|
||||||
|
// Require all clients to the kubelet API to have client certs signed by the cluster CA
|
||||||
|
externalkubeletcfg.Authentication.X509.ClientCAFile = kubeadmapiv1alpha3.DefaultCACertPath
|
||||||
|
externalkubeletcfg.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false)
|
||||||
|
|
||||||
|
// On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server
|
||||||
|
// and ask it whether the client is authorized to access the kubelet API
|
||||||
|
externalkubeletcfg.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook
|
||||||
|
|
||||||
|
// Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API
|
||||||
|
externalkubeletcfg.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true)
|
||||||
|
|
||||||
|
// Disable the readonly port of the kubelet, in order to not expose unnecessary information
|
||||||
|
externalkubeletcfg.ReadOnlyPort = 0
|
||||||
|
|
||||||
|
// Enables client certificate rotation for the kubelet
|
||||||
|
externalkubeletcfg.RotateCertificates = true
|
||||||
|
|
||||||
|
// Serve a /healthz webserver on localhost:10248 that kubeadm can talk to
|
||||||
|
externalkubeletcfg.HealthzBindAddress = "127.0.0.1"
|
||||||
|
externalkubeletcfg.HealthzPort = utilpointer.Int32Ptr(10248)
|
||||||
|
|
||||||
|
kubeletconfigv1beta1.SetDefaults_KubeletConfiguration(externalkubeletcfg)
|
||||||
|
|
||||||
|
if internalcfg.ComponentConfigs.Kubelet == nil {
|
||||||
|
internalcfg.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Figure out how to handle errors in defaulting code
|
||||||
|
// Go back to the internal version
|
||||||
|
Scheme.Convert(externalkubeletcfg, internalcfg.ComponentConfigs.Kubelet, nil)
|
||||||
|
}
|
148
cmd/kubeadm/app/componentconfigs/registrations.go
Normal file
148
cmd/kubeadm/app/componentconfigs/registrations.go
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package componentconfigs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||||
|
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
|
||||||
|
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddToSchemeFunc is a function that adds known types and API GroupVersions to a scheme
|
||||||
|
type AddToSchemeFunc func(*runtime.Scheme) error
|
||||||
|
|
||||||
|
// Registration is an object for registering a Kubernetes ComponentConfig type to be recognized and handled by kubeadm
|
||||||
|
type Registration struct {
|
||||||
|
// MarshalGroupVersion is the preferred external API version to use when marshalling the ComponentConfig
|
||||||
|
MarshalGroupVersion schema.GroupVersion
|
||||||
|
// AddToSchemeFuncs are a set of functions that register APIs to the scheme
|
||||||
|
AddToSchemeFuncs []AddToSchemeFunc
|
||||||
|
// DefaulterFunc is a function that based on the internal kubeadm configuration defaults the ComponentConfig struct
|
||||||
|
DefaulterFunc func(*kubeadmapi.MasterConfiguration)
|
||||||
|
// ValidateFunc is a function that should validate the ComponentConfig type embedded in the internal kubeadm config struct
|
||||||
|
ValidateFunc func(*kubeadmapi.MasterConfiguration, *field.Path) field.ErrorList
|
||||||
|
// EmptyValue holds a pointer to an empty struct of the internal ComponentConfig type
|
||||||
|
EmptyValue runtime.Object
|
||||||
|
// GetFromInternalConfig returns the pointer to the ComponentConfig API object from the internal kubeadm config struct
|
||||||
|
GetFromInternalConfig func(*kubeadmapi.MasterConfiguration) (runtime.Object, bool)
|
||||||
|
// SetToInternalConfig sets the pointer to a ComponentConfig API object embedded in the internal kubeadm config struct
|
||||||
|
SetToInternalConfig func(runtime.Object, *kubeadmapi.MasterConfiguration) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals obj to bytes for the current Registration
|
||||||
|
func (r Registration) Marshal(obj runtime.Object) ([]byte, error) {
|
||||||
|
return kubeadmutil.MarshalToYamlForCodecs(obj, r.MarshalGroupVersion, Codecs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals the bytes to a runtime.Object using the Codecs registered in this Scheme
|
||||||
|
func (r Registration) Unmarshal(fileContent []byte) (runtime.Object, error) {
|
||||||
|
// Do a deepcopy of the empty value so we don't mutate it, which could lead to strange errors
|
||||||
|
obj := r.EmptyValue.DeepCopyObject()
|
||||||
|
|
||||||
|
// Decode the file content into obj which is a pointer to an empty struct of the internal ComponentConfig
|
||||||
|
// object, using the componentconfig Codecs that knows about all APIs
|
||||||
|
if err := runtime.DecodeInto(Codecs.UniversalDecoder(), fileContent, obj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// KubeletConfigurationKind is the kind for the kubelet ComponentConfig
|
||||||
|
KubeletConfigurationKind RegistrationKind = "KubeletConfiguration"
|
||||||
|
// KubeProxyConfigurationKind is the kind for the kubelet ComponentConfig
|
||||||
|
KubeProxyConfigurationKind RegistrationKind = "KubeProxyConfiguration"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegistrationKind is a string type to ensure not any string can be a key in the Registrations map
|
||||||
|
type RegistrationKind string
|
||||||
|
|
||||||
|
// Registrations holds a set of ComponentConfig Registration objects, where the map key is the kind
|
||||||
|
type Registrations map[RegistrationKind]Registration
|
||||||
|
|
||||||
|
// Known contains the known ComponentConfig registrations to kubeadm
|
||||||
|
var Known Registrations = map[RegistrationKind]Registration{
|
||||||
|
KubeProxyConfigurationKind: {
|
||||||
|
// TODO: When a beta version of the kube-proxy ComponentConfig API is available, start using it
|
||||||
|
MarshalGroupVersion: kubeproxyconfigv1alpha1.SchemeGroupVersion,
|
||||||
|
AddToSchemeFuncs: []AddToSchemeFunc{kubeproxyconfig.AddToScheme, kubeproxyconfigv1alpha1.AddToScheme},
|
||||||
|
DefaulterFunc: DefaultKubeProxyConfiguration,
|
||||||
|
ValidateFunc: ValidateKubeProxyConfiguration,
|
||||||
|
EmptyValue: &kubeproxyconfig.KubeProxyConfiguration{},
|
||||||
|
GetFromInternalConfig: func(cfg *kubeadmapi.MasterConfiguration) (runtime.Object, bool) {
|
||||||
|
return cfg.ComponentConfigs.KubeProxy, cfg.ComponentConfigs.KubeProxy != nil
|
||||||
|
},
|
||||||
|
SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.MasterConfiguration) bool {
|
||||||
|
kubeproxyConfig, ok := obj.(*kubeproxyconfig.KubeProxyConfiguration)
|
||||||
|
if ok {
|
||||||
|
cfg.ComponentConfigs.KubeProxy = kubeproxyConfig
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
},
|
||||||
|
},
|
||||||
|
KubeletConfigurationKind: {
|
||||||
|
MarshalGroupVersion: kubeletconfigv1beta1.SchemeGroupVersion,
|
||||||
|
AddToSchemeFuncs: []AddToSchemeFunc{kubeletconfig.AddToScheme, kubeletconfigv1beta1.AddToScheme},
|
||||||
|
DefaulterFunc: DefaultKubeletConfiguration,
|
||||||
|
ValidateFunc: ValidateKubeletConfiguration,
|
||||||
|
EmptyValue: &kubeletconfig.KubeletConfiguration{},
|
||||||
|
GetFromInternalConfig: func(cfg *kubeadmapi.MasterConfiguration) (runtime.Object, bool) {
|
||||||
|
return cfg.ComponentConfigs.Kubelet, cfg.ComponentConfigs.Kubelet != nil
|
||||||
|
},
|
||||||
|
SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.MasterConfiguration) bool {
|
||||||
|
kubeletConfig, ok := obj.(*kubeletconfig.KubeletConfiguration)
|
||||||
|
if ok {
|
||||||
|
cfg.ComponentConfigs.Kubelet = kubeletConfig
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddToScheme adds all the known ComponentConfig API types referenced in the Registrations object to the scheme
|
||||||
|
func (rs *Registrations) AddToScheme(scheme *runtime.Scheme) error {
|
||||||
|
for _, registration := range *rs {
|
||||||
|
for _, addToSchemeFunc := range registration.AddToSchemeFuncs {
|
||||||
|
if err := addToSchemeFunc(scheme); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default applies to the ComponentConfig defaults to the internal kubeadm API type
|
||||||
|
func (rs *Registrations) Default(internalcfg *kubeadmapi.MasterConfiguration) {
|
||||||
|
for _, registration := range *rs {
|
||||||
|
registration.DefaulterFunc(internalcfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the ComponentConfig parts of the internal kubeadm API type
|
||||||
|
func (rs *Registrations) Validate(internalcfg *kubeadmapi.MasterConfiguration) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
for kind, registration := range *rs {
|
||||||
|
allErrs = append(allErrs, registration.ValidateFunc(internalcfg, field.NewPath(string(kind)))...)
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
41
cmd/kubeadm/app/componentconfigs/scheme.go
Normal file
41
cmd/kubeadm/app/componentconfigs/scheme.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package componentconfigs
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Scheme is the runtime.Scheme to which all supported kubeadm ComponentConfig API types are registered.
|
||||||
|
var Scheme = runtime.NewScheme()
|
||||||
|
|
||||||
|
// Codecs provides access to encoding and decoding for the scheme.
|
||||||
|
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||||
|
AddToScheme(Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddToScheme builds the kubeadm ComponentConfig scheme using all known ComponentConfig versions.
|
||||||
|
func AddToScheme(scheme *runtime.Scheme) {
|
||||||
|
utilruntime.Must(Known.AddToScheme(scheme))
|
||||||
|
}
|
46
cmd/kubeadm/app/componentconfigs/validation.go
Normal file
46
cmd/kubeadm/app/componentconfigs/validation.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package componentconfigs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeletvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation"
|
||||||
|
proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateKubeProxyConfiguration validates proxy configuration and collects all encountered errors
|
||||||
|
func ValidateKubeProxyConfiguration(internalcfg *kubeadmapi.MasterConfiguration, _ *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if internalcfg.ComponentConfigs.KubeProxy == nil {
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
return proxyvalidation.Validate(internalcfg.ComponentConfigs.KubeProxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateKubeletConfiguration validates kubelet configuration and collects all encountered errors
|
||||||
|
func ValidateKubeletConfiguration(internalcfg *kubeadmapi.MasterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if internalcfg.ComponentConfigs.Kubelet == nil {
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := kubeletvalidation.ValidateKubeletConfiguration(internalcfg.ComponentConfigs.Kubelet); err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error()))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
351
cmd/kubeadm/app/componentconfigs/validation_test.go
Normal file
351
cmd/kubeadm/app/componentconfigs/validation_test.go
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package componentconfigs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
|
||||||
|
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
masterConfig *kubeadm.MasterConfiguration
|
||||||
|
msg string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "192.168.59.103",
|
||||||
|
HealthzBindAddress: "0.0.0.0:10256",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
// only BindAddress is invalid
|
||||||
|
BindAddress: "10.10.12.11:2000",
|
||||||
|
HealthzBindAddress: "0.0.0.0:10256",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "not a valid textual representation of an IP address",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "10.10.12.11",
|
||||||
|
// only HealthzBindAddress is invalid
|
||||||
|
HealthzBindAddress: "0.0.0.0",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "must be IP:port",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "10.10.12.11",
|
||||||
|
HealthzBindAddress: "0.0.0.0:12345",
|
||||||
|
// only MetricsBindAddress is invalid
|
||||||
|
MetricsBindAddress: "127.0.0.1",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "must be IP:port",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "10.10.12.11",
|
||||||
|
HealthzBindAddress: "0.0.0.0:12345",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
// only ClusterCIDR is invalid
|
||||||
|
ClusterCIDR: "192.168.59.0",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "must be a valid CIDR block (e.g. 10.100.0.0/16)",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "10.10.12.11",
|
||||||
|
HealthzBindAddress: "0.0.0.0:12345",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
// only UDPIdleTimeout is invalid
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: -1 * time.Second},
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "must be greater than 0",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "10.10.12.11",
|
||||||
|
HealthzBindAddress: "0.0.0.0:12345",
|
||||||
|
MetricsBindAddress: "127.0.0.1:10249",
|
||||||
|
ClusterCIDR: "192.168.59.0/24",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||||
|
// only ConfigSyncPeriod is invalid
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: -1 * time.Second},
|
||||||
|
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||||
|
},
|
||||||
|
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: utilpointer.Int32Ptr(2),
|
||||||
|
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||||
|
Min: utilpointer.Int32Ptr(1),
|
||||||
|
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
msg: "must be greater than 0",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, rt := range tests {
|
||||||
|
err := ValidateKubeProxyConfiguration(rt.masterConfig, nil).ToAggregate()
|
||||||
|
if (err != nil) != rt.expectErr {
|
||||||
|
t.Errorf("%d failed ValidateKubeProxyConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil)
|
||||||
|
}
|
||||||
|
if err != nil && !strings.Contains(err.Error(), rt.msg) {
|
||||||
|
t.Errorf("%d failed ValidateKubeProxyConfiguration: unexpected error: %v, expected: %s", i, err, rt.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateKubeletConfiguration(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
masterConfig *kubeadm.MasterConfiguration
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
Kubelet: &kubeletconfig.KubeletConfiguration{
|
||||||
|
CgroupsPerQOS: true,
|
||||||
|
EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved"},
|
||||||
|
SystemCgroups: "",
|
||||||
|
CgroupRoot: "",
|
||||||
|
EventBurst: 10,
|
||||||
|
EventRecordQPS: 5,
|
||||||
|
HealthzPort: 10248,
|
||||||
|
ImageGCHighThresholdPercent: 85,
|
||||||
|
ImageGCLowThresholdPercent: 80,
|
||||||
|
IPTablesDropBit: 15,
|
||||||
|
IPTablesMasqueradeBit: 14,
|
||||||
|
KubeAPIBurst: 10,
|
||||||
|
KubeAPIQPS: 5,
|
||||||
|
MaxOpenFiles: 1000000,
|
||||||
|
MaxPods: 110,
|
||||||
|
OOMScoreAdj: -999,
|
||||||
|
PodsPerCore: 100,
|
||||||
|
Port: 65535,
|
||||||
|
ReadOnlyPort: 0,
|
||||||
|
RegistryBurst: 10,
|
||||||
|
RegistryPullQPS: 5,
|
||||||
|
HairpinMode: "promiscuous-bridge",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterConfig: &kubeadm.MasterConfiguration{
|
||||||
|
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||||
|
Kubelet: &kubeletconfig.KubeletConfiguration{
|
||||||
|
CgroupsPerQOS: false,
|
||||||
|
EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved", "illegal-key"},
|
||||||
|
SystemCgroups: "/",
|
||||||
|
CgroupRoot: "",
|
||||||
|
EventBurst: -10,
|
||||||
|
EventRecordQPS: -10,
|
||||||
|
HealthzPort: -10,
|
||||||
|
ImageGCHighThresholdPercent: 101,
|
||||||
|
ImageGCLowThresholdPercent: 101,
|
||||||
|
IPTablesDropBit: -10,
|
||||||
|
IPTablesMasqueradeBit: -10,
|
||||||
|
KubeAPIBurst: -10,
|
||||||
|
KubeAPIQPS: -10,
|
||||||
|
MaxOpenFiles: -10,
|
||||||
|
MaxPods: -10,
|
||||||
|
OOMScoreAdj: -1001,
|
||||||
|
PodsPerCore: -10,
|
||||||
|
Port: 0,
|
||||||
|
ReadOnlyPort: -10,
|
||||||
|
RegistryBurst: -10,
|
||||||
|
RegistryPullQPS: -10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, rt := range tests {
|
||||||
|
err := ValidateKubeletConfiguration(rt.masterConfig, nil).ToAggregate()
|
||||||
|
if (err != nil) != rt.expectErr {
|
||||||
|
t.Errorf("%d failed ValidateKubeletConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user