Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeadm: Replace GetCoreImage with less error prone functions #64976

Merged
merged 1 commit into from Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/kubeadm/app/cmd/init.go
Expand Up @@ -399,13 +399,13 @@ func (i *Init) Run(out io.Writer) error {
if err := waitForKubeletAndFunc(waiter, waiter.WaitForAPI); err != nil {
ctx := map[string]string{
"Error": fmt.Sprintf("%v", err),
"APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
"ControllerManagerImage": images.GetCoreImage(kubeadmconstants.KubeControllerManager, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
"SchedulerImage": images.GetCoreImage(kubeadmconstants.KubeScheduler, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
"APIServerImage": images.GetKubeControlPlaneImage(kubeadmconstants.KubeAPIServer, i.cfg),
"ControllerManagerImage": images.GetKubeControlPlaneImage(kubeadmconstants.KubeControllerManager, i.cfg),
"SchedulerImage": images.GetKubeControlPlaneImage(kubeadmconstants.KubeScheduler, i.cfg),
}
// Set .EtcdImage conditionally
if i.cfg.Etcd.Local != nil {
ctx["EtcdImage"] = fmt.Sprintf(" - %s", images.GetCoreImage(kubeadmconstants.Etcd, i.cfg.ImageRepository, i.cfg.KubernetesVersion, i.cfg.Etcd.Local.Image))
ctx["EtcdImage"] = fmt.Sprintf(" - %s", images.GetEtcdImage(i.cfg))
} else {
ctx["EtcdImage"] = ""
}
Expand Down
55 changes: 34 additions & 21 deletions cmd/kubeadm/app/images/images.go
Expand Up @@ -26,45 +26,58 @@ import (
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
)

// GetCoreImage generates and returns the image for the core Kubernetes components or returns overrideImage if specified
func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string {
if overrideImage != "" {
return overrideImage
// GetGenericArchImage generates and returns an image based on the current runtime arch
func GetGenericArchImage(prefix, image, tag string) string {
return fmt.Sprintf("%s/%s-%s:%s", prefix, image, runtime.GOARCH, tag)
}

// GetKubeControlPlaneImageNoOverride generates and returns the image for the core Kubernetes components ignoring the unified control plane image
func GetKubeControlPlaneImageNoOverride(image string, cfg *kubeadmapi.MasterConfiguration) string {
repoPrefix := cfg.GetControlPlaneImageRepository()
kubernetesImageTag := kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion)
return GetGenericArchImage(repoPrefix, image, kubernetesImageTag)
}

// GetKubeControlPlaneImage generates and returns the image for the core Kubernetes components or returns the unified control plane image if specified
func GetKubeControlPlaneImage(image string, cfg *kubeadmapi.MasterConfiguration) string {
if cfg.UnifiedControlPlaneImage != "" {
return cfg.UnifiedControlPlaneImage
}
return GetKubeControlPlaneImageNoOverride(image, cfg)
}

// GetEtcdImage generates and returns the image for etcd or returns cfg.Etcd.Local.Image if specified
func GetEtcdImage(cfg *kubeadmapi.MasterConfiguration) string {
if cfg.Etcd.Local != nil && cfg.Etcd.Local.Image != "" {
return cfg.Etcd.Local.Image
}
kubernetesImageTag := kubeadmutil.KubernetesVersionToImageTag(k8sVersion)
etcdImageTag := constants.DefaultEtcdVersion
etcdImageVersion, err := constants.EtcdSupportedVersion(k8sVersion)
etcdImageVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
if err == nil {
etcdImageTag = etcdImageVersion.String()
}
return map[string]string{
constants.Etcd: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "etcd", runtime.GOARCH, etcdImageTag),
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]
return GetGenericArchImage(cfg.ImageRepository, constants.Etcd, etcdImageTag)
}

// GetAllImages returns a list of container images kubeadm expects to use on a control plane node
func GetAllImages(cfg *kubeadmapi.MasterConfiguration) []string {
repoPrefix := cfg.GetControlPlaneImageRepository()
imgs := []string{}
imgs = append(imgs, GetCoreImage(constants.KubeAPIServer, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage))
imgs = append(imgs, GetCoreImage(constants.KubeControllerManager, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage))
imgs = append(imgs, GetCoreImage(constants.KubeScheduler, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage))
imgs = append(imgs, fmt.Sprintf("%v/%v-%v:%v", repoPrefix, constants.KubeProxy, runtime.GOARCH, kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion)))
imgs = append(imgs, GetKubeControlPlaneImage(constants.KubeAPIServer, cfg))
imgs = append(imgs, GetKubeControlPlaneImage(constants.KubeControllerManager, cfg))
imgs = append(imgs, GetKubeControlPlaneImage(constants.KubeScheduler, cfg))
imgs = append(imgs, GetKubeControlPlaneImageNoOverride(constants.KubeProxy, cfg))

// pause, etcd and kube-dns are not available on the ci image repository so use the default image repository.
imgs = append(imgs, fmt.Sprintf("%v/pause-%v:%v", cfg.ImageRepository, runtime.GOARCH, "3.1"))
imgs = append(imgs, GetGenericArchImage(cfg.ImageRepository, "pause", "3.1"))

// if etcd is not external then add the image as it will be required
if cfg.Etcd.Local != nil {
imgs = append(imgs, GetCoreImage(constants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Local.Image))
imgs = append(imgs, GetEtcdImage(cfg))
}

dnsImage := fmt.Sprintf("%v/k8s-dns-kube-dns-%v:%v", cfg.ImageRepository, runtime.GOARCH, constants.KubeDNSVersion)
dnsImage := GetGenericArchImage(cfg.ImageRepository, "k8s-dns-kube-dns", constants.KubeDNSVersion)
if features.Enabled(cfg.FeatureGates, features.CoreDNS) {
dnsImage = fmt.Sprintf("%v/coredns:%v", cfg.ImageRepository, constants.CoreDNSVersion)
dnsImage = GetGenericArchImage(cfg.ImageRepository, "coredns", constants.CoreDNSVersion)
}
imgs = append(imgs, dnsImage)
return imgs
Expand Down
142 changes: 124 additions & 18 deletions cmd/kubeadm/app/images/images_test.go
Expand Up @@ -32,43 +32,149 @@ const (
gcrPrefix = "k8s.gcr.io"
)

func TestGetCoreImage(t *testing.T) {
func TestGetGenericArchImage(t *testing.T) {
const (
prefix = "foo"
image = "bar"
tag = "baz"
)
expected := fmt.Sprintf("%s/%s-%s:%s", prefix, image, runtime.GOARCH, tag)
actual := GetGenericArchImage(prefix, image, tag)
if actual != expected {
t.Errorf("failed GetGenericArchImage:\n\texpected: %s\n\t actual: %s", expected, actual)
}
}

func TestGetKubeControlPlaneImageNoOverride(t *testing.T) {
var tests = []struct {
image, repo, version, override, expected string
image string
expected string
cfg *kubeadmapi.MasterConfiguration
}{
{
override: "override",
expected: "override",
// UnifiedControlPlaneImage should be ignored by GetKubeImage
image: constants.KubeAPIServer,
expected: GetGenericArchImage(gcrPrefix, "kube-apiserver", expected),
cfg: &kubeadmapi.MasterConfiguration{
UnifiedControlPlaneImage: "nooverride",
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
{
image: constants.KubeAPIServer,
expected: GetGenericArchImage(gcrPrefix, "kube-apiserver", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
{
image: constants.KubeControllerManager,
expected: GetGenericArchImage(gcrPrefix, "kube-controller-manager", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
{
image: constants.Etcd,
repo: gcrPrefix,
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, constants.DefaultEtcdVersion),
image: constants.KubeScheduler,
expected: GetGenericArchImage(gcrPrefix, "kube-scheduler", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
}
for _, rt := range tests {
actual := GetKubeControlPlaneImageNoOverride(rt.image, rt.cfg)
if actual != rt.expected {
t.Errorf(
"failed GetKubeControlPlaneImageNoOverride:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual,
)
}
}
}

func TestGetKubeControlPlaneImage(t *testing.T) {
var tests = []struct {
image string
expected string
cfg *kubeadmapi.MasterConfiguration
}{
{
expected: "override",
cfg: &kubeadmapi.MasterConfiguration{
UnifiedControlPlaneImage: "override",
},
},
{
image: constants.KubeAPIServer,
repo: gcrPrefix,
version: testversion,
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, expected),
expected: GetGenericArchImage(gcrPrefix, "kube-apiserver", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
{
image: constants.KubeControllerManager,
repo: gcrPrefix,
version: testversion,
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, expected),
expected: GetGenericArchImage(gcrPrefix, "kube-controller-manager", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
{
image: constants.KubeScheduler,
repo: gcrPrefix,
version: testversion,
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, expected),
expected: GetGenericArchImage(gcrPrefix, "kube-scheduler", expected),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
}
for _, rt := range tests {
actual := GetKubeControlPlaneImage(rt.image, rt.cfg)
if actual != rt.expected {
t.Errorf(
"failed GetKubeControlPlaneImage:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual,
)
}
}
}

func TestGetEtcdImage(t *testing.T) {
var tests = []struct {
expected string
cfg *kubeadmapi.MasterConfiguration
}{
{
expected: "override",
cfg: &kubeadmapi.MasterConfiguration{
Etcd: kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{
Image: "override",
},
},
},
},
{
expected: GetGenericArchImage(gcrPrefix, "etcd", constants.DefaultEtcdVersion),
cfg: &kubeadmapi.MasterConfiguration{
ImageRepository: gcrPrefix,
KubernetesVersion: testversion,
},
},
}
for _, rt := range tests {
actual := GetCoreImage(rt.image, rt.repo, rt.version, rt.override)
actual := GetEtcdImage(rt.cfg)
if actual != rt.expected {
t.Errorf(
"failed GetCoreImage:\n\texpected: %s\n\t actual: %s",
"failed GetEtcdImage:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual,
)
Expand Down
6 changes: 3 additions & 3 deletions cmd/kubeadm/app/phases/controlplane/manifests.go
Expand Up @@ -73,7 +73,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
staticPodSpecs := map[string]v1.Pod{
kubeadmconstants.KubeAPIServer: staticpodutil.ComponentPod(v1.Container{
Name: kubeadmconstants.KubeAPIServer,
Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
Image: images.GetKubeControlPlaneImage(kubeadmconstants.KubeAPIServer, cfg),
ImagePullPolicy: v1.PullIfNotPresent,
Command: getAPIServerCommand(cfg),
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer)),
Expand All @@ -83,7 +83,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
}, mounts.GetVolumes(kubeadmconstants.KubeAPIServer)),
kubeadmconstants.KubeControllerManager: staticpodutil.ComponentPod(v1.Container{
Name: kubeadmconstants.KubeControllerManager,
Image: images.GetCoreImage(kubeadmconstants.KubeControllerManager, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
Image: images.GetKubeControlPlaneImage(kubeadmconstants.KubeControllerManager, cfg),
ImagePullPolicy: v1.PullIfNotPresent,
Command: getControllerManagerCommand(cfg, k8sVersion),
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeControllerManager)),
Expand All @@ -93,7 +93,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
}, mounts.GetVolumes(kubeadmconstants.KubeControllerManager)),
kubeadmconstants.KubeScheduler: staticpodutil.ComponentPod(v1.Container{
Name: kubeadmconstants.KubeScheduler,
Image: images.GetCoreImage(kubeadmconstants.KubeScheduler, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
Image: images.GetKubeControlPlaneImage(kubeadmconstants.KubeScheduler, cfg),
ImagePullPolicy: v1.PullIfNotPresent,
Command: getSchedulerCommand(cfg),
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeScheduler)),
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubeadm/app/phases/etcd/local.go
Expand Up @@ -60,7 +60,7 @@ func GetEtcdPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.Pod {
return staticpodutil.ComponentPod(v1.Container{
Name: kubeadmconstants.Etcd,
Command: getEtcdCommand(cfg),
Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Local.Image),
Image: images.GetEtcdImage(cfg),
ImagePullPolicy: v1.PullIfNotPresent,
// Mount the etcd datadir path read-write so etcd can store data in a more persistent manner
VolumeMounts: []v1.VolumeMount{
Expand Down
7 changes: 6 additions & 1 deletion cmd/kubeadm/app/phases/upgrade/prepull.go
Expand Up @@ -59,7 +59,12 @@ func NewDaemonSetPrepuller(client clientset.Interface, waiter apiclient.Waiter,

// CreateFunc creates a DaemonSet for making the image available on every relevant node
func (d *DaemonSetPrepuller) CreateFunc(component string) error {
image := images.GetCoreImage(component, d.cfg.GetControlPlaneImageRepository(), d.cfg.KubernetesVersion, d.cfg.UnifiedControlPlaneImage)
var image string
if component == constants.Etcd {
image = images.GetEtcdImage(d.cfg)
} else {
image = images.GetKubeControlPlaneImage(component, d.cfg)
}
ds := buildPrePullDaemonSet(component, image)

// Create the DaemonSet in the API Server
Expand Down