mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
kubeadm: Centralize commonly used paths/constants to the constants pkg
This commit is contained in:
parent
d37f2f1a5d
commit
9a6ef9677a
@ -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
|
||||
}
|
||||
|
||||
|
@ -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"],
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
|
112
cmd/kubeadm/app/constants/constants_test.go
Normal file
112
cmd/kubeadm/app/constants/constants_test.go
Normal 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
@ -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]
|
||||
}
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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{
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user