diff --git a/cmd/kubeadm/app/componentconfigs/BUILD b/cmd/kubeadm/app/componentconfigs/BUILD index 1a5c8af7683..446bd12ac81 100644 --- a/cmd/kubeadm/app/componentconfigs/BUILD +++ b/cmd/kubeadm/app/componentconfigs/BUILD @@ -35,6 +35,7 @@ go_library( "//staging/src/k8s.io/kube-proxy/config/v1alpha1:go_default_library", "//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/cmd/kubeadm/app/componentconfigs/defaults.go b/cmd/kubeadm/app/componentconfigs/defaults.go index 13754ed0714..2c95352f157 100644 --- a/cmd/kubeadm/app/componentconfigs/defaults.go +++ b/cmd/kubeadm/app/componentconfigs/defaults.go @@ -17,6 +17,7 @@ limitations under the License. package componentconfigs import ( + "k8s.io/klog" "path/filepath" kubeproxyconfigv1alpha1 "k8s.io/kube-proxy/config/v1alpha1" @@ -31,8 +32,27 @@ import ( ) const ( - // KubeproxyKubeConfigFileName defines the file name for the kube-proxy's kubeconfig file - KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" + // kubeproxyKubeConfigFileName defines the file name for the kube-proxy's kubeconfig file + kubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" + + // kubeletReadOnlyPort specifies the default insecure http server port + // 0 will disable insecure http server. + kubeletReadOnlyPort int32 = 0 + + // kubeletRotateCertificates specifies the default value to enable certificate rotation + kubeletRotateCertificates = true + + // kubeletAuthenticationAnonymousEnabled specifies the default value to disable anonymous access + kubeletAuthenticationAnonymousEnabled = false + + // kubeletAuthorizationMode specifies the default authorization mode + kubeletAuthorizationMode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook + + // kubeletAuthenticationWebhookEnabled set the default value to enable authentication webhook + kubeletAuthenticationWebhookEnabled = true + + // kubeletHealthzBindAddress specifies the default healthz bind address + kubeletHealthzBindAddress = "127.0.0.1" ) // DefaultKubeProxyConfiguration assigns default values for the kube-proxy ComponentConfig @@ -46,10 +66,14 @@ func DefaultKubeProxyConfiguration(internalcfg *kubeadmapi.ClusterConfiguration) if externalproxycfg.ClusterCIDR == "" && internalcfg.Networking.PodSubnet != "" { externalproxycfg.ClusterCIDR = internalcfg.Networking.PodSubnet + } else if internalcfg.Networking.PodSubnet != "" && externalproxycfg.ClusterCIDR != internalcfg.Networking.PodSubnet { + warnDefaultComponentConfigValue(externalproxycfg.Kind, "cluster-cidr", internalcfg.Networking.PodSubnet, externalproxycfg.ClusterCIDR) } if externalproxycfg.ClientConnection.Kubeconfig == "" { - externalproxycfg.ClientConnection.Kubeconfig = KubeproxyKubeConfigFileName + externalproxycfg.ClientConnection.Kubeconfig = kubeproxyKubeConfigFileName + } else if externalproxycfg.ClientConnection.Kubeconfig != kubeproxyKubeConfigFileName { + warnDefaultComponentConfigValue(externalproxycfg.Kind, "kubeconfig", kubeproxyKubeConfigFileName, externalproxycfg.ClientConnection.Kubeconfig) } // TODO: The following code should be remvoved after dual-stack is GA. @@ -81,41 +105,79 @@ func DefaultKubeletConfiguration(internalcfg *kubeadmapi.ClusterConfiguration) { if externalkubeletcfg.StaticPodPath == "" { externalkubeletcfg.StaticPodPath = kubeadmapiv1beta2.DefaultManifestsDir + } else if externalkubeletcfg.StaticPodPath != kubeadmapiv1beta2.DefaultManifestsDir { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "pod-manifest-path", kubeadmapiv1beta2.DefaultManifestsDir, externalkubeletcfg.StaticPodPath) } + + clusterDNS := "" + dnsIP, err := constants.GetDNSIP(internalcfg.Networking.ServiceSubnet) + if err != nil { + clusterDNS = kubeadmapiv1beta2.DefaultClusterDNSIP + } else { + clusterDNS = dnsIP.String() + } + if externalkubeletcfg.ClusterDNS == nil { - dnsIP, err := constants.GetDNSIP(internalcfg.Networking.ServiceSubnet) - if err != nil { - externalkubeletcfg.ClusterDNS = []string{kubeadmapiv1beta2.DefaultClusterDNSIP} - } else { - externalkubeletcfg.ClusterDNS = []string{dnsIP.String()} - } + externalkubeletcfg.ClusterDNS = []string{clusterDNS} + } else if len(externalkubeletcfg.ClusterDNS) != 1 || externalkubeletcfg.ClusterDNS[0] != clusterDNS { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "cluster-dns", []string{clusterDNS}, externalkubeletcfg.ClusterDNS) } + if externalkubeletcfg.ClusterDomain == "" { externalkubeletcfg.ClusterDomain = internalcfg.Networking.DNSDomain + } else if internalcfg.Networking.DNSDomain != "" && externalkubeletcfg.ClusterDomain != internalcfg.Networking.DNSDomain { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "cluster-domain", internalcfg.Networking.DNSDomain, externalkubeletcfg.ClusterDomain) } - // 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 = filepath.Join(internalcfg.CertificatesDir, constants.CACertName) - externalkubeletcfg.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false) + clientCAFile := filepath.Join(internalcfg.CertificatesDir, constants.CACertName) + if externalkubeletcfg.Authentication.X509.ClientCAFile == "" { + externalkubeletcfg.Authentication.X509.ClientCAFile = clientCAFile + } else if externalkubeletcfg.Authentication.X509.ClientCAFile != clientCAFile { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "client-ca-file", clientCAFile, externalkubeletcfg.Authentication.X509.ClientCAFile) + } + + if externalkubeletcfg.Authentication.Anonymous.Enabled == nil { + externalkubeletcfg.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(kubeletAuthenticationAnonymousEnabled) + } else if *externalkubeletcfg.Authentication.Anonymous.Enabled != kubeletAuthenticationAnonymousEnabled { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "anonymous-auth", kubeletAuthenticationAnonymousEnabled, *externalkubeletcfg.Authentication.Anonymous.Enabled) + } // 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 + if externalkubeletcfg.Authorization.Mode == "" { + externalkubeletcfg.Authorization.Mode = kubeletAuthorizationMode + } else if externalkubeletcfg.Authorization.Mode != kubeletAuthorizationMode { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "authorization-mode", kubeletAuthorizationMode, externalkubeletcfg.Authorization.Mode) + } // 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 + if externalkubeletcfg.Authentication.Webhook.Enabled == nil { + externalkubeletcfg.Authentication.Webhook.Enabled = utilpointer.BoolPtr(kubeletAuthenticationWebhookEnabled) + } else if *externalkubeletcfg.Authentication.Webhook.Enabled != kubeletAuthenticationWebhookEnabled { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "authentication-token-webhook", kubeletAuthenticationWebhookEnabled, *externalkubeletcfg.Authentication.Webhook.Enabled) + } // Serve a /healthz webserver on localhost:10248 that kubeadm can talk to - externalkubeletcfg.HealthzBindAddress = "127.0.0.1" - externalkubeletcfg.HealthzPort = utilpointer.Int32Ptr(constants.KubeletHealthzPort) + if externalkubeletcfg.HealthzBindAddress == "" { + externalkubeletcfg.HealthzBindAddress = kubeletHealthzBindAddress + } else if externalkubeletcfg.HealthzBindAddress != kubeletHealthzBindAddress { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "healthz-bind-address", kubeletHealthzBindAddress, externalkubeletcfg.HealthzBindAddress) + } + + if externalkubeletcfg.HealthzPort == nil { + externalkubeletcfg.HealthzPort = utilpointer.Int32Ptr(constants.KubeletHealthzPort) + } else if *externalkubeletcfg.HealthzPort != constants.KubeletHealthzPort { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "healthz-port", constants.KubeletHealthzPort, *externalkubeletcfg.HealthzPort) + } + + if externalkubeletcfg.ReadOnlyPort != kubeletReadOnlyPort { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "read-only-port", kubeletReadOnlyPort, externalkubeletcfg.ReadOnlyPort) + } + + if externalkubeletcfg.RotateCertificates != kubeletRotateCertificates { + warnDefaultComponentConfigValue(externalkubeletcfg.Kind, "rotate-certificates", kubeletRotateCertificates, externalkubeletcfg.RotateCertificates) + } Scheme.Default(externalkubeletcfg) @@ -127,3 +189,10 @@ func DefaultKubeletConfiguration(internalcfg *kubeadmapi.ClusterConfiguration) { // Go back to the internal version Scheme.Convert(externalkubeletcfg, internalcfg.ComponentConfigs.Kubelet, nil) } + +// warnDefaultComponentConfigValue prints a warning if the user modified a field in a certain +// CompomentConfig from the default recommended value in kubeadm. +func warnDefaultComponentConfigValue(componentConfigKind, paramName string, defaultValue, userValue interface{}) { + klog.Warningf("The recommended value for %q in %q is: %v; the provided value is: %v", + paramName, componentConfigKind, defaultValue, userValue) +}