diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index e08ec4dab4e..63b972e4b0d 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -221,25 +221,27 @@ func (i *Init) Validate(cmd *cobra.Command) error { // Run executes master node provisioning, including certificates, needed static pod manifests, etc. func (i *Init) Run(out io.Writer) error { - // PHASE 1: Generate certificates - err := cmdphases.CreatePKIAssets(i.cfg) + k8sVersion, err := version.ParseSemantic(i.cfg.KubernetesVersion) if err != nil { + return fmt.Errorf("couldn't parse kubernetes version %q: %v", i.cfg.KubernetesVersion, err) + } + + // PHASE 1: Generate certificates + if err := cmdphases.CreatePKIAssets(i.cfg); err != nil { return err } // PHASE 2: Generate kubeconfig files for the admin and the kubelet - err = kubeconfigphase.CreateInitKubeConfigFiles(kubeadmconstants.KubernetesDir, i.cfg) - if err != nil { + if err := kubeconfigphase.CreateInitKubeConfigFiles(kubeadmconstants.KubernetesDir, i.cfg); err != nil { return err } // PHASE 3: Bootstrap the control plane - if err := controlplanephase.WriteStaticPodManifests(i.cfg); err != nil { + if err := controlplanephase.WriteStaticPodManifests(i.cfg, k8sVersion, kubeadmconstants.GetStaticPodDirectory()); err != nil { return err } - adminKubeConfigPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.AdminKubeConfigFileName) - client, err := kubeadmutil.CreateClientAndWaitForAPI(adminKubeConfigPath) + client, err := kubeadmutil.CreateClientAndWaitForAPI(kubeadmconstants.GetAdminKubeConfigPath()) if err != nil { return err } @@ -258,25 +260,18 @@ func (i *Init) Run(out io.Writer) error { return err } - if err := tokenphase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil { + if err := tokenphase.CreateBootstrapConfigMapIfNotExists(client, kubeadmconstants.GetAdminKubeConfigPath()); err != nil { return err } // PHASE 5: Install and deploy all addons, and configure things as necessary - k8sVersion, err := version.ParseSemantic(i.cfg.KubernetesVersion) - if err != nil { - return fmt.Errorf("couldn't parse kubernetes version %q: %v", i.cfg.KubernetesVersion, err) - } - // Create the necessary ServiceAccounts - err = apiconfigphase.CreateServiceAccounts(client) - if err != nil { + if err := apiconfigphase.CreateServiceAccounts(client); err != nil { return err } - err = apiconfigphase.CreateRBACRules(client, k8sVersion) - if err != nil { + if err := apiconfigphase.CreateRBACRules(client, k8sVersion); err != nil { return err } diff --git a/cmd/kubeadm/app/constants/BUILD b/cmd/kubeadm/app/constants/BUILD index 735d973a56e..e166329e927 100644 --- a/cmd/kubeadm/app/constants/BUILD +++ b/cmd/kubeadm/app/constants/BUILD @@ -5,6 +5,7 @@ licenses(["notice"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -29,3 +30,10 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["constants_test.go"], + library = ":go_default_library", + tags = ["automanaged"], +) diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index 51d8134c44b..fccc3ef92af 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -17,6 +17,7 @@ limitations under the License. package constants import ( + "fmt" "path/filepath" "time" @@ -97,6 +98,18 @@ const ( // MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports MinExternalEtcdVersion = "3.0.14" + + // DefaultEtcdVersion indicates the default etcd version that kubeadm uses + DefaultEtcdVersion = "3.0.17" + + Etcd = "etcd" + KubeAPIServer = "kube-apiserver" + KubeControllerManager = "kube-controller-manager" + KubeScheduler = "kube-scheduler" + KubeProxy = "kube-proxy" + + // SelfHostingPrefix describes the prefix workloads that are self-hosted by kubeadm has + SelfHostingPrefix = "self-hosted-" ) var ( @@ -119,11 +132,29 @@ var ( // DefaultTokenUsages specifies the default functions a token will get DefaultTokenUsages = []string{"signing", "authentication"} + // MasterComponents defines the master component names + MasterComponents = []string{KubeAPIServer, KubeControllerManager, KubeScheduler} + // MinimumControlPlaneVersion specifies the minimum control plane version kubeadm can deploy MinimumControlPlaneVersion = version.MustParseSemantic("v1.7.0") ) -// BuildStaticManifestFilepath returns the location on the disk where the Static Pod should be present -func BuildStaticManifestFilepath(componentName string) string { - return filepath.Join(KubernetesDir, ManifestsSubDirName, componentName+".yaml") +// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present +func GetStaticPodDirectory() string { + return filepath.Join(KubernetesDir, ManifestsSubDirName) +} + +// GetStaticPodFilepath returns the location on the disk where the Static Pod should be present +func GetStaticPodFilepath(componentName, manifestsDir string) string { + return filepath.Join(manifestsDir, componentName+".yaml") +} + +// GetAdminKubeConfigPath returns the location on the disk where admin kubeconfig is located by default +func GetAdminKubeConfigPath() string { + return filepath.Join(KubernetesDir, AdminKubeConfigFileName) +} + +// AddSelfHostedPrefix adds the self-hosted- prefix to the component name +func AddSelfHostedPrefix(componentName string) string { + return fmt.Sprintf("%s%s", SelfHostingPrefix, componentName) } diff --git a/cmd/kubeadm/app/constants/constants_test.go b/cmd/kubeadm/app/constants/constants_test.go new file mode 100644 index 00000000000..29cffa2abbd --- /dev/null +++ b/cmd/kubeadm/app/constants/constants_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2017 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 constants + +import ( + "testing" +) + +func TestGetStaticPodDirectory(t *testing.T) { + expected := "/etc/kubernetes/manifests" + actual := GetStaticPodDirectory() + + if actual != expected { + t.Errorf( + "failed GetStaticPodDirectory:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + +func TestGetAdminKubeConfigPath(t *testing.T) { + expected := "/etc/kubernetes/admin.conf" + actual := GetAdminKubeConfigPath() + + if actual != expected { + t.Errorf( + "failed GetAdminKubeConfigPath:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + +func TestGetStaticPodFilepath(t *testing.T) { + var tests = []struct { + componentName, manifestsDir, expected string + }{ + { + componentName: "kube-apiserver", + manifestsDir: "/etc/kubernetes/manifests", + expected: "/etc/kubernetes/manifests/kube-apiserver.yaml", + }, + { + componentName: "kube-controller-manager", + manifestsDir: "/etc/kubernetes/manifests/", + expected: "/etc/kubernetes/manifests/kube-controller-manager.yaml", + }, + { + componentName: "foo", + manifestsDir: "/etc/bar/", + expected: "/etc/bar/foo.yaml", + }, + } + for _, rt := range tests { + actual := GetStaticPodFilepath(rt.componentName, rt.manifestsDir) + if actual != rt.expected { + t.Errorf( + "failed GetStaticPodFilepath:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestAddSelfHostedPrefix(t *testing.T) { + var tests = []struct { + componentName, expected string + }{ + { + componentName: "kube-apiserver", + expected: "self-hosted-kube-apiserver", + }, + { + componentName: "kube-controller-manager", + expected: "self-hosted-kube-controller-manager", + }, + { + componentName: "kube-scheduler", + expected: "self-hosted-kube-scheduler", + }, + { + componentName: "foo", + expected: "self-hosted-foo", + }, + } + for _, rt := range tests { + actual := AddSelfHostedPrefix(rt.componentName) + if actual != rt.expected { + t.Errorf( + "failed AddSelfHostedPrefix:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} diff --git a/cmd/kubeadm/app/images/BUILD b/cmd/kubeadm/app/images/BUILD index 6209daaf175..b2e3dd7c011 100644 --- a/cmd/kubeadm/app/images/BUILD +++ b/cmd/kubeadm/app/images/BUILD @@ -13,7 +13,7 @@ go_library( srcs = ["images.go"], tags = ["automanaged"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", ], ) @@ -23,7 +23,7 @@ go_test( srcs = ["images_test.go"], library = ":go_default_library", tags = ["automanaged"], - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], + deps = ["//cmd/kubeadm/app/constants:go_default_library"], ) filegroup( diff --git a/cmd/kubeadm/app/images/images.go b/cmd/kubeadm/app/images/images.go index d0a6922de54..2ac3fefa71b 100644 --- a/cmd/kubeadm/app/images/images.go +++ b/cmd/kubeadm/app/images/images.go @@ -20,29 +20,19 @@ import ( "fmt" "runtime" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) -const ( - KubeEtcdImage = "etcd" - KubeAPIServerImage = "apiserver" - KubeControllerManagerImage = "controller-manager" - KubeSchedulerImage = "scheduler" - - etcdVersion = "3.0.17" -) - -func GetCoreImage(image string, cfg *kubeadmapi.MasterConfiguration, overrideImage string) string { +func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string { if overrideImage != "" { return overrideImage } - repoPrefix := cfg.ImageRepository - kubernetesImageTag := kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion) + kubernetesImageTag := kubeadmutil.KubernetesVersionToImageTag(k8sVersion) return map[string]string{ - KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "etcd", runtime.GOARCH, etcdVersion), - KubeAPIServerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-apiserver", runtime.GOARCH, kubernetesImageTag), - KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-controller-manager", runtime.GOARCH, kubernetesImageTag), - KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-scheduler", runtime.GOARCH, kubernetesImageTag), + constants.Etcd: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "etcd", runtime.GOARCH, constants.DefaultEtcdVersion), + constants.KubeAPIServer: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-apiserver", runtime.GOARCH, kubernetesImageTag), + constants.KubeControllerManager: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-controller-manager", runtime.GOARCH, kubernetesImageTag), + constants.KubeScheduler: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-scheduler", runtime.GOARCH, kubernetesImageTag), }[image] } diff --git a/cmd/kubeadm/app/images/images_test.go b/cmd/kubeadm/app/images/images_test.go index 10a37f0703f..6c1173e6c25 100644 --- a/cmd/kubeadm/app/images/images_test.go +++ b/cmd/kubeadm/app/images/images_test.go @@ -21,15 +21,9 @@ import ( "runtime" "testing" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) -type getCoreImageTest struct { - i string - c *kubeadmapi.MasterConfiguration - o string -} - const ( testversion = "v10.1.2-alpha.1.100+0123456789abcdef+SOMETHING" expected = "v10.1.2-alpha.1.100_0123456789abcdef_SOMETHING" @@ -37,38 +31,43 @@ const ( ) func TestGetCoreImage(t *testing.T) { - var imageTest = []struct { - t getCoreImageTest - expected string + var tests = []struct { + image, repo, version, override, expected string }{ - {getCoreImageTest{o: "override"}, "override"}, - {getCoreImageTest{ - i: KubeEtcdImage, - c: &kubeadmapi.MasterConfiguration{ImageRepository: gcrPrefix}}, - fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion), + { + override: "override", + expected: "override", }, - {getCoreImageTest{ - i: KubeAPIServerImage, - c: &kubeadmapi.MasterConfiguration{ImageRepository: gcrPrefix, KubernetesVersion: testversion}}, - fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, expected), + { + image: constants.Etcd, + repo: gcrPrefix, + expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, constants.DefaultEtcdVersion), }, - {getCoreImageTest{ - i: KubeControllerManagerImage, - c: &kubeadmapi.MasterConfiguration{ImageRepository: gcrPrefix, KubernetesVersion: testversion}}, - fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, expected), + { + image: constants.KubeAPIServer, + repo: gcrPrefix, + version: testversion, + expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, expected), }, - {getCoreImageTest{ - i: KubeSchedulerImage, - c: &kubeadmapi.MasterConfiguration{ImageRepository: gcrPrefix, KubernetesVersion: testversion}}, - fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, expected), + { + image: constants.KubeControllerManager, + repo: gcrPrefix, + version: testversion, + expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, expected), + }, + { + image: constants.KubeScheduler, + repo: gcrPrefix, + version: testversion, + expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, expected), }, } - for _, it := range imageTest { - actual := GetCoreImage(it.t.i, it.t.c, it.t.o) - if actual != it.expected { + for _, rt := range tests { + actual := GetCoreImage(rt.image, rt.repo, rt.version, rt.override) + if actual != rt.expected { t.Errorf( "failed GetCoreImage:\n\texpected: %s\n\t actual: %s", - it.expected, + rt.expected, actual, ) } diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index 17e92ce64e5..50fad128452 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -45,78 +45,66 @@ const ( DefaultCloudConfigPath = "/etc/kubernetes/cloud-config" defaultv17AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" - - etcd = "etcd" - kubeAPIServer = "kube-apiserver" - kubeControllerManager = "kube-controller-manager" - kubeScheduler = "kube-scheduler" ) // WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk // where kubelet will pick and schedule them. -func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error { - - // TODO: Move the "pkg/util/version".Version object into the internal API instead of always parsing the string - k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) - if err != nil { - return err - } +func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.Version, manifestsDir string) error { // Get the required hostpath mounts mounts := getHostPathVolumesForTheControlPlane(cfg) // Prepare static pod specs staticPodSpecs := map[string]v1.Pod{ - kubeAPIServer: componentPod(v1.Container{ - Name: kubeAPIServer, - Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, cfg.UnifiedControlPlaneImage), + kubeadmconstants.KubeAPIServer: componentPod(v1.Container{ + Name: kubeadmconstants.KubeAPIServer, + Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), Command: getAPIServerCommand(cfg, k8sVersion), - VolumeMounts: mounts.GetVolumeMounts(kubeAPIServer), + VolumeMounts: mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer), LivenessProbe: componentProbe(int(cfg.API.BindPort), "/healthz", v1.URISchemeHTTPS), Resources: componentResources("250m"), Env: getProxyEnvVars(), - }, mounts.GetVolumes(kubeAPIServer)), - kubeControllerManager: componentPod(v1.Container{ - Name: kubeControllerManager, - Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, cfg.UnifiedControlPlaneImage), + }, mounts.GetVolumes(kubeadmconstants.KubeAPIServer)), + kubeadmconstants.KubeControllerManager: componentPod(v1.Container{ + Name: kubeadmconstants.KubeControllerManager, + Image: images.GetCoreImage(kubeadmconstants.KubeControllerManager, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), Command: getControllerManagerCommand(cfg, k8sVersion), - VolumeMounts: mounts.GetVolumeMounts(kubeControllerManager), + VolumeMounts: mounts.GetVolumeMounts(kubeadmconstants.KubeControllerManager), LivenessProbe: componentProbe(10252, "/healthz", v1.URISchemeHTTP), Resources: componentResources("200m"), Env: getProxyEnvVars(), - }, mounts.GetVolumes(kubeControllerManager)), - kubeScheduler: componentPod(v1.Container{ - Name: kubeScheduler, - Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, cfg.UnifiedControlPlaneImage), + }, mounts.GetVolumes(kubeadmconstants.KubeControllerManager)), + kubeadmconstants.KubeScheduler: componentPod(v1.Container{ + Name: kubeadmconstants.KubeScheduler, + Image: images.GetCoreImage(kubeadmconstants.KubeScheduler, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), Command: getSchedulerCommand(cfg), - VolumeMounts: mounts.GetVolumeMounts(kubeScheduler), + VolumeMounts: mounts.GetVolumeMounts(kubeadmconstants.KubeScheduler), LivenessProbe: componentProbe(10251, "/healthz", v1.URISchemeHTTP), Resources: componentResources("100m"), Env: getProxyEnvVars(), - }, mounts.GetVolumes(kubeScheduler)), + }, mounts.GetVolumes(kubeadmconstants.KubeScheduler)), } // Add etcd static pod spec only if external etcd is not configured if len(cfg.Etcd.Endpoints) == 0 { etcdPod := componentPod(v1.Container{ - Name: etcd, + Name: kubeadmconstants.Etcd, Command: getEtcdCommand(cfg), - Image: images.GetCoreImage(images.KubeEtcdImage, cfg, cfg.Etcd.Image), + Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, "", cfg.Etcd.Image), // Mount the etcd datadir path read-write so etcd can store data in a more persistent manner VolumeMounts: []v1.VolumeMount{newVolumeMount(etcdVolumeName, cfg.Etcd.DataDir, false)}, LivenessProbe: componentProbe(2379, "/health", v1.URISchemeHTTP), }, []v1.Volume{newVolume(etcdVolumeName, cfg.Etcd.DataDir)}) - staticPodSpecs[etcd] = etcdPod + staticPodSpecs[kubeadmconstants.Etcd] = etcdPod } - manifestsPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName) - if err := os.MkdirAll(manifestsPath, 0700); err != nil { - return fmt.Errorf("failed to create directory %q [%v]", manifestsPath, err) + if err := os.MkdirAll(manifestsDir, 0700); err != nil { + return fmt.Errorf("failed to create directory %q [%v]", manifestsDir, err) } for name, spec := range staticPodSpecs { - filename := filepath.Join(manifestsPath, name+".yaml") + filename := kubeadmconstants.GetStaticPodFilepath(name, manifestsDir) serialized, err := yaml.Marshal(spec) if err != nil { return fmt.Errorf("failed to marshal manifest for %q to YAML [%v]", name, err) diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index 25780b00c87..7de0cd63b53 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -55,21 +55,25 @@ func TestWriteStaticPodManifests(t *testing.T) { expectedAPIProbePort int32 }{ { - cfg: &kubeadmapi.MasterConfiguration{}, - expectErr: true, + cfg: &kubeadmapi.MasterConfiguration{ + KubernetesVersion: "v1.7.0", + }, + expectErr: false, }, { cfg: &kubeadmapi.MasterConfiguration{ API: kubeadmapi.API{ BindPort: 443, }, + KubernetesVersion: "v1.7.0", }, - expectErr: true, + expectErr: false, expectedAPIProbePort: 443, }, } for _, rt := range tests { - actual := WriteStaticPodManifests(rt.cfg) + + actual := WriteStaticPodManifests(rt.cfg, version.MustParseSemantic(rt.cfg.KubernetesVersion), fmt.Sprintf("%s/etc/kubernetes/manifests", tmpdir)) if (actual == nil) && rt.expectErr { t.Error("expected an error from WriteStaticPodManifests but got none") continue diff --git a/cmd/kubeadm/app/phases/controlplane/volumes.go b/cmd/kubeadm/app/phases/controlplane/volumes.go index 4873595b365..14cf4c0bccb 100644 --- a/cmd/kubeadm/app/phases/controlplane/volumes.go +++ b/cmd/kubeadm/app/phases/controlplane/volumes.go @@ -49,36 +49,36 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) c // HostPath volumes for the API Server // Read-only mount for the certificates directory // TODO: Always mount the K8s Certificates directory to a static path inside of the container - mounts.NewHostPathMount(kubeAPIServer, k8sCertsVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true) + mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, k8sCertsVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true) // Read-only mount for the ca certs (/etc/ssl/certs) directory - mounts.NewHostPathMount(kubeAPIServer, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true) + mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true) // If external etcd is specified, mount the directories needed for accessing the CA/serving certs and the private key if len(cfg.Etcd.Endpoints) != 0 { etcdVols, etcdVolMounts := getEtcdCertVolumes(cfg.Etcd) - mounts.AddHostPathMounts(kubeAPIServer, etcdVols, etcdVolMounts) + mounts.AddHostPathMounts(kubeadmconstants.KubeAPIServer, etcdVols, etcdVolMounts) } // HostPath volumes for the controller manager // Read-only mount for the certificates directory // TODO: Always mount the K8s Certificates directory to a static path inside of the container - mounts.NewHostPathMount(kubeControllerManager, k8sCertsVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true) + mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, k8sCertsVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true) // Read-only mount for the ca certs (/etc/ssl/certs) directory - mounts.NewHostPathMount(kubeControllerManager, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true) + mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true) // Read-only mount for the controller manager kubeconfig file controllerManagerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) - mounts.NewHostPathMount(kubeControllerManager, kubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true) + mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true) // HostPath volumes for the scheduler // Read-only mount for the scheduler kubeconfig file schedulerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName) - mounts.NewHostPathMount(kubeScheduler, kubeConfigVolumeName, schedulerKubeConfigFile, schedulerKubeConfigFile, true) + mounts.NewHostPathMount(kubeadmconstants.KubeScheduler, kubeConfigVolumeName, schedulerKubeConfigFile, schedulerKubeConfigFile, true) // On some systems were we host-mount /etc/ssl/certs, it is also required to mount /etc/pki. This is needed // due to symlinks pointing from files in /etc/ssl/certs into /etc/pki/ if isPkiVolumeMountNeeded() { - mounts.NewHostPathMount(kubeAPIServer, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true) - mounts.NewHostPathMount(kubeControllerManager, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true) + mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true) + mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true) } return mounts diff --git a/cmd/kubeadm/app/phases/controlplane/volumes_test.go b/cmd/kubeadm/app/phases/controlplane/volumes_test.go index 9a9d521dfd5..81f58a28d16 100644 --- a/cmd/kubeadm/app/phases/controlplane/volumes_test.go +++ b/cmd/kubeadm/app/phases/controlplane/volumes_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/api/core/v1" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) func TestNewVolume(t *testing.T) { @@ -304,7 +305,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { Etcd: kubeadmapi.Etcd{}, }, vol: map[string][]v1.Volume{ - kubeAPIServer: { + kubeadmconstants.KubeAPIServer: { { Name: "k8s-certs", VolumeSource: v1.VolumeSource{ @@ -318,7 +319,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, }, - kubeControllerManager: { + kubeadmconstants.KubeControllerManager: { { Name: "k8s-certs", VolumeSource: v1.VolumeSource{ @@ -338,7 +339,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, }, - kubeScheduler: { + kubeadmconstants.KubeScheduler: { { Name: "kubeconfig", VolumeSource: v1.VolumeSource{ @@ -348,7 +349,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, volMount: map[string][]v1.VolumeMount{ - kubeAPIServer: { + kubeadmconstants.KubeAPIServer: { { Name: "k8s-certs", MountPath: testCertsDir, @@ -360,7 +361,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { ReadOnly: true, }, }, - kubeControllerManager: { + kubeadmconstants.KubeControllerManager: { { Name: "k8s-certs", MountPath: testCertsDir, @@ -377,7 +378,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { ReadOnly: true, }, }, - kubeScheduler: { + kubeadmconstants.KubeScheduler: { { Name: "kubeconfig", MountPath: "/etc/kubernetes/scheduler.conf", @@ -398,7 +399,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, vol: map[string][]v1.Volume{ - kubeAPIServer: { + kubeadmconstants.KubeAPIServer: { { Name: "k8s-certs", VolumeSource: v1.VolumeSource{ @@ -424,7 +425,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, }, - kubeControllerManager: { + kubeadmconstants.KubeControllerManager: { { Name: "k8s-certs", VolumeSource: v1.VolumeSource{ @@ -444,7 +445,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, }, - kubeScheduler: { + kubeadmconstants.KubeScheduler: { { Name: "kubeconfig", VolumeSource: v1.VolumeSource{ @@ -454,7 +455,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { }, }, volMount: map[string][]v1.VolumeMount{ - kubeAPIServer: { + kubeadmconstants.KubeAPIServer: { { Name: "k8s-certs", MountPath: testCertsDir, @@ -476,7 +477,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { ReadOnly: true, }, }, - kubeControllerManager: { + kubeadmconstants.KubeControllerManager: { { Name: "k8s-certs", MountPath: testCertsDir, @@ -493,7 +494,7 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { ReadOnly: true, }, }, - kubeScheduler: { + kubeadmconstants.KubeScheduler: { { Name: "kubeconfig", MountPath: "/etc/kubernetes/scheduler.conf", diff --git a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation.go b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation.go index cf7b2edae7a..bcddca3d74b 100644 --- a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation.go +++ b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation.go @@ -25,19 +25,19 @@ import ( // mutatePodSpec makes a Static Pod-hosted PodSpec suitable for self-hosting func mutatePodSpec(cfg *kubeadmapi.MasterConfiguration, name string, podSpec *v1.PodSpec) { mutators := map[string][]func(*kubeadmapi.MasterConfiguration, *v1.PodSpec){ - kubeAPIServer: { + kubeadmconstants.KubeAPIServer: { addNodeSelectorToPodSpec, setMasterTolerationOnPodSpec, setRightDNSPolicyOnPodSpec, setVolumesOnKubeAPIServerPodSpec, }, - kubeControllerManager: { + kubeadmconstants.KubeControllerManager: { addNodeSelectorToPodSpec, setMasterTolerationOnPodSpec, setRightDNSPolicyOnPodSpec, setVolumesOnKubeControllerManagerPodSpec, }, - kubeScheduler: { + kubeadmconstants.KubeScheduler: { addNodeSelectorToPodSpec, setMasterTolerationOnPodSpec, setRightDNSPolicyOnPodSpec, diff --git a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go index e84214bf8b8..9b2ce07b38b 100644 --- a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go +++ b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go @@ -32,7 +32,7 @@ func TestMutatePodSpec(t *testing.T) { expected v1.PodSpec }{ { - component: kubeAPIServer, + component: kubeadmconstants.KubeAPIServer, podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ NodeSelector: map[string]string{ @@ -45,7 +45,7 @@ func TestMutatePodSpec(t *testing.T) { }, }, { - component: kubeControllerManager, + component: kubeadmconstants.KubeControllerManager, podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ NodeSelector: map[string]string{ @@ -58,7 +58,7 @@ func TestMutatePodSpec(t *testing.T) { }, }, { - component: kubeScheduler, + component: kubeadmconstants.KubeScheduler, podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ NodeSelector: map[string]string{ diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting.go index 66762dc0493..c6ad27eff7c 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting.go @@ -20,7 +20,6 @@ import ( "fmt" "io/ioutil" "os" - "path/filepath" "time" "k8s.io/api/core/v1" @@ -35,14 +34,6 @@ import ( "k8s.io/kubernetes/pkg/api" ) -const ( - kubeAPIServer = "kube-apiserver" - kubeControllerManager = "kube-controller-manager" - kubeScheduler = "kube-scheduler" - - selfHostingPrefix = "self-hosted-" -) - // CreateSelfHostedControlPlane is responsible for turning a Static Pod-hosted control plane to a self-hosted one // It achieves that task this way: // 1. Load the Static Pod specification from disk (from /etc/kubernetes/manifests) @@ -64,12 +55,9 @@ func CreateSelfHostedControlPlane(cfg *kubeadmapi.MasterConfiguration, client cl return err } - // The sequence here isn't set in stone, but seems to work well to start with the API server - components := []string{kubeAPIServer, kubeControllerManager, kubeScheduler} - - for _, componentName := range components { + for _, componentName := range kubeadmconstants.MasterComponents { start := time.Now() - manifestPath := buildStaticManifestFilepath(componentName) + manifestPath := kubeadmconstants.GetStaticPodFilepath(componentName, kubeadmconstants.GetStaticPodDirectory()) // Load the Static Pod file in order to be able to create a self-hosted variant of that file podSpec, err := loadPodSpecFromFile(manifestPath) @@ -116,17 +104,17 @@ func buildDaemonSet(cfg *kubeadmapi.MasterConfiguration, name string, podSpec *v // Return a DaemonSet based on that Spec return &extensions.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ - Name: addSelfHostedPrefix(name), + Name: kubeadmconstants.AddSelfHostedPrefix(name), Namespace: metav1.NamespaceSystem, Labels: map[string]string{ - "k8s-app": addSelfHostedPrefix(name), + "k8s-app": kubeadmconstants.AddSelfHostedPrefix(name), }, }, Spec: extensions.DaemonSetSpec{ Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - "k8s-app": addSelfHostedPrefix(name), + "k8s-app": kubeadmconstants.AddSelfHostedPrefix(name), }, }, Spec: *podSpec, @@ -151,17 +139,7 @@ func loadPodSpecFromFile(manifestPath string) (*v1.PodSpec, error) { return &staticPod.Spec, nil } -// buildStaticManifestFilepath returns the location on the disk where the Static Pod should be present -func buildStaticManifestFilepath(componentName string) string { - return filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, componentName+".yaml") -} - // buildSelfHostedWorkloadLabelQuery creates the right query for matching a self-hosted Pod func buildSelfHostedWorkloadLabelQuery(componentName string) string { - return fmt.Sprintf("k8s-app=%s", addSelfHostedPrefix(componentName)) -} - -// addSelfHostedPrefix adds the self-hosted- prefix to the component name -func addSelfHostedPrefix(componentName string) string { - return fmt.Sprintf("%s%s", selfHostingPrefix, componentName) + return fmt.Sprintf("k8s-app=%s", kubeadmconstants.AddSelfHostedPrefix(componentName)) } diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go index 558276b5c29..f8d17589ee5 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go @@ -25,6 +25,7 @@ import ( "github.com/ghodss/yaml" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) const ( @@ -543,17 +544,17 @@ func TestBuildDaemonSet(t *testing.T) { dsBytes []byte }{ { - component: kubeAPIServer, + component: kubeadmconstants.KubeAPIServer, podBytes: []byte(testAPIServerPod), dsBytes: []byte(testAPIServerDaemonSet), }, { - component: kubeControllerManager, + component: kubeadmconstants.KubeControllerManager, podBytes: []byte(testControllerManagerPod), dsBytes: []byte(testControllerManagerDaemonSet), }, { - component: kubeScheduler, + component: kubeadmconstants.KubeScheduler, podBytes: []byte(testSchedulerPod), dsBytes: []byte(testSchedulerDaemonSet), },