Merge pull request #50173 from luxas/kubeadm_constants

Automatic merge from submit-queue

kubeadm: Centralize commonly used paths/constants to the constants pkg

**What this PR does / why we need it**:
Before there were constants defined for the control plane components in three different places:
 - images
 - phases/controlplane
 - phases/selfhosting

Now they are in one centralized place. I also moved funcs for building common paths to that lib.

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #

Dependency for: https://github.com/kubernetes/kubernetes/pull/48899

**Special notes for your reviewer**:

Most of this PR really is autogenerated with a replace tool. I tested this and things work just normally as well.

**Release note**:

```release-note
NONE
```
@timothysc @dmmcquay @pipejakob @kubernetes/sig-cluster-lifecycle-pr-reviews
This commit is contained in:
Kubernetes Submit Queue 2017-08-09 01:41:19 -07:00 committed by GitHub
commit 35e5197eca
15 changed files with 273 additions and 166 deletions

View File

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

View File

@ -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"],
)

View File

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

View File

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

View File

@ -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(

View File

@ -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]
}

View File

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

View File

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

View File

@ -56,21 +56,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

View File

@ -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

View File

@ -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",

View File

@ -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,

View File

@ -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{

View File

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

View File

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