From a959caf200c80ad92809cbc9fc7da68f6d91097c Mon Sep 17 00:00:00 2001 From: Christian Schlotter Date: Wed, 13 Jul 2022 19:30:50 +0200 Subject: [PATCH] kcp: patch ImageRepository in ClusterConfiguration if it is not set for v1.25 --- .../kubeadm/api/v1alpha4/kubeadm_types.go | 4 +- .../kubeadm/api/v1beta1/kubeadm_types.go | 4 +- ...strap.cluster.x-k8s.io_kubeadmconfigs.yaml | 12 +- ...uster.x-k8s.io_kubeadmconfigtemplates.yaml | 26 +- .../kubeadm/types/upstreamv1beta2/types.go | 4 +- .../kubeadm/types/upstreamv1beta3/types.go | 4 +- ...cluster.x-k8s.io_kubeadmcontrolplanes.yaml | 20 +- ...x-k8s.io_kubeadmcontrolplanetemplates.yaml | 16 +- .../internal/controllers/controller.go | 14 +- .../kubeadm/internal/controllers/upgrade.go | 11 +- .../kubeadm/internal/workload_cluster.go | 45 +++- .../internal/workload_cluster_coredns.go | 35 ++- .../internal/workload_cluster_coredns_test.go | 222 ++++++++++++------ .../kubeadm/internal/workload_cluster_test.go | 15 +- .../v1beta1/bases/cluster-with-topology.yaml | 3 - .../clusterclass-quick-start-runtimesdk.yaml | 21 -- .../v1beta1/clusterclass-quick-start.yaml | 21 -- test/framework/daemonset_helpers.go | 17 +- .../cluster-template-development.yaml | 2 +- .../templates/clusterclass-quick-start.yaml | 7 +- 20 files changed, 316 insertions(+), 187 deletions(-) diff --git a/bootstrap/kubeadm/api/v1alpha4/kubeadm_types.go b/bootstrap/kubeadm/api/v1alpha4/kubeadm_types.go index 1f5d4df96f07..5e7eb78fd185 100644 --- a/bootstrap/kubeadm/api/v1alpha4/kubeadm_types.go +++ b/bootstrap/kubeadm/api/v1alpha4/kubeadm_types.go @@ -113,8 +113,8 @@ type ClusterConfiguration struct { CertificatesDir string `json:"certificatesDir,omitempty"` // ImageRepository sets the container registry to pull images from. - // If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) - // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io` + // If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) + // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `registry.k8s.io` // will be used for all the other images. // +optional ImageRepository string `json:"imageRepository,omitempty"` diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go index 75b85dd6af9d..222ce4d50b7f 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go @@ -124,8 +124,8 @@ type ClusterConfiguration struct { CertificatesDir string `json:"certificatesDir,omitempty"` // ImageRepository sets the container registry to pull images from. - // If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) - // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io` + // If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) + // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `registry.k8s.io` // will be used for all the other images. // +optional ImageRepository string `json:"imageRepository,omitempty"` diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml index df58d41eb2f6..06f6c0c638cc 100644 --- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml +++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml @@ -1256,12 +1256,12 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry to pull - images from. If empty, `k8s.gcr.io` will be used by default; + images from. If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for - kube-proxy, while `k8s.gcr.io` will be used for all the other - images. + kube-proxy, while `registry.k8s.io` will be used for all the + other images. type: string kind: description: 'Kind is a string value representing the REST resource @@ -2244,12 +2244,12 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry to pull - images from. If empty, `k8s.gcr.io` will be used by default; + images from. If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for - kube-proxy, while `k8s.gcr.io` will be used for all the other - images. + kube-proxy, while `registry.k8s.io` will be used for all the + other images. type: string kind: description: 'Kind is a string value representing the REST resource diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml index ea993202d6b7..aac50884c0ee 100644 --- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml +++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml @@ -1265,12 +1265,13 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry - to pull images from. If empty, `k8s.gcr.io` will be - used by default; in case of kubernetes version is a - CI build (kubernetes version starts with `ci/` or `ci-cross/`) - `gcr.io/k8s-staging-ci-images` will be used as a default - for control plane components and for kube-proxy, while - `k8s.gcr.io` will be used for all the other images. + to pull images from. If empty, `registry.k8s.io` will + be used by default; in case of kubernetes version is + a CI build (kubernetes version starts with `ci/` or + `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be + used as a default for control plane components and for + kube-proxy, while `registry.k8s.io` will be used for + all the other images. type: string kind: description: 'Kind is a string value representing the @@ -2246,12 +2247,13 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry - to pull images from. If empty, `k8s.gcr.io` will be - used by default; in case of kubernetes version is a - CI build (kubernetes version starts with `ci/` or `ci-cross/`) - `gcr.io/k8s-staging-ci-images` will be used as a default - for control plane components and for kube-proxy, while - `k8s.gcr.io` will be used for all the other images. + to pull images from. If empty, `registry.k8s.io` will + be used by default; in case of kubernetes version is + a CI build (kubernetes version starts with `ci/` or + `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be + used as a default for control plane components and for + kube-proxy, while `registry.k8s.io` will be used for + all the other images. type: string kind: description: 'Kind is a string value representing the diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/types.go b/bootstrap/kubeadm/types/upstreamv1beta2/types.go index 96b684a3bd47..413f6fe9b5b0 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta2/types.go +++ b/bootstrap/kubeadm/types/upstreamv1beta2/types.go @@ -116,8 +116,8 @@ type ClusterConfiguration struct { CertificatesDir string `json:"certificatesDir,omitempty"` // ImageRepository sets the container registry to pull images from. - // If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) - // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io` + // If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/`) + // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `registry.k8s.io` // will be used for all the other images. // +optional ImageRepository string `json:"imageRepository,omitempty"` diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/types.go b/bootstrap/kubeadm/types/upstreamv1beta3/types.go index ba64d712a1ec..1959b803969f 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/types.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/types.go @@ -120,8 +120,8 @@ type ClusterConfiguration struct { CertificatesDir string `json:"certificatesDir,omitempty"` // ImageRepository sets the container registry to pull images from. - // If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) - // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io` + // If empty, `registry.k8s.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) + // `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and for kube-proxy, while `registry.k8s.io` // will be used for all the other images. // +optional ImageRepository string `json:"imageRepository,omitempty"` diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml index a2ee418b33b0..5aeb720cd9bc 100644 --- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml +++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml @@ -1482,12 +1482,12 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry to - pull images from. If empty, `k8s.gcr.io` will be used by - default; in case of kubernetes version is a CI build (kubernetes - version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` + pull images from. If empty, `registry.k8s.io` will be used + by default; in case of kubernetes version is a CI build + (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and - for kube-proxy, while `k8s.gcr.io` will be used for all - the other images. + for kube-proxy, while `registry.k8s.io` will be used for + all the other images. type: string kind: description: 'Kind is a string value representing the REST @@ -2702,12 +2702,12 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry to - pull images from. If empty, `k8s.gcr.io` will be used by - default; in case of kubernetes version is a CI build (kubernetes - version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` + pull images from. If empty, `registry.k8s.io` will be used + by default; in case of kubernetes version is a CI build + (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components and - for kube-proxy, while `k8s.gcr.io` will be used for all - the other images. + for kube-proxy, while `registry.k8s.io` will be used for + all the other images. type: string kind: description: 'Kind is a string value representing the REST diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml index 00b4448b8339..501708d0490f 100644 --- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml +++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml @@ -304,13 +304,13 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry - to pull images from. If empty, `k8s.gcr.io` will - be used by default; in case of kubernetes version + to pull images from. If empty, `registry.k8s.io` + will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components - and for kube-proxy, while `k8s.gcr.io` will be used - for all the other images. + and for kube-proxy, while `registry.k8s.io` will + be used for all the other images. type: string kind: description: 'Kind is a string value representing @@ -1467,13 +1467,13 @@ spec: type: object imageRepository: description: ImageRepository sets the container registry - to pull images from. If empty, `k8s.gcr.io` will - be used by default; in case of kubernetes version + to pull images from. If empty, `registry.k8s.io` + will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) `gcr.io/k8s-staging-ci-images` will be used as a default for control plane components - and for kube-proxy, while `k8s.gcr.io` will be used - for all the other images. + and for kube-proxy, while `registry.k8s.io` will + be used for all the other images. type: string kind: description: 'Kind is a string value representing diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go index 081c57de3026..a7eadbb6a1e6 100644 --- a/controlplane/kubeadm/internal/controllers/controller.go +++ b/controlplane/kubeadm/internal/controllers/controller.go @@ -382,13 +382,6 @@ func (r *KubeadmControlPlaneReconciler) reconcile(ctx context.Context, cluster * return ctrl.Result{}, errors.Wrap(err, "failed to set role and role binding for kubeadm") } - // Update kube-proxy daemonset. - if err := workloadCluster.UpdateKubeProxyImageInfo(ctx, kcp); err != nil { - log.Error(err, "failed to update kube-proxy daemonset") - return ctrl.Result{}, err - } - - // Update CoreDNS deployment. // We intentionally only parse major/minor/patch so that the subsequent code // also already applies to beta versions of new releases. parsedVersion, err := version.ParseMajorMinorPatchTolerant(kcp.Spec.Version) @@ -396,6 +389,13 @@ func (r *KubeadmControlPlaneReconciler) reconcile(ctx context.Context, cluster * return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", kcp.Spec.Version) } + // Update kube-proxy daemonset. + if err := workloadCluster.UpdateKubeProxyImageInfo(ctx, kcp, parsedVersion); err != nil { + log.Error(err, "failed to update kube-proxy daemonset") + return ctrl.Result{}, err + } + + // Update CoreDNS deployment. if err := workloadCluster.UpdateCoreDNS(ctx, kcp, parsedVersion); err != nil { return ctrl.Result{}, errors.Wrap(err, "failed to update CoreDNS deployment") } diff --git a/controlplane/kubeadm/internal/controllers/upgrade.go b/controlplane/kubeadm/internal/controllers/upgrade.go index 9913bb6ad576..afeeecad6423 100644 --- a/controlplane/kubeadm/internal/controllers/upgrade.go +++ b/controlplane/kubeadm/internal/controllers/upgrade.go @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/cluster-api/controlplane/kubeadm/internal" "sigs.k8s.io/cluster-api/util" "sigs.k8s.io/cluster-api/util/collections" + "sigs.k8s.io/cluster-api/util/version" ) func (r *KubeadmControlPlaneReconciler) upgradeControlPlane( @@ -75,7 +76,15 @@ func (r *KubeadmControlPlaneReconciler) upgradeControlPlane( } if kcp.Spec.KubeadmConfigSpec.ClusterConfiguration != nil { - imageRepository := kcp.Spec.KubeadmConfigSpec.ClusterConfiguration.ImageRepository + // We intentionally only parse major/minor/patch so that the subsequent code + // also already applies to beta versions of new releases. + parsedVersionTolerant, err := version.ParseMajorMinorPatchTolerant(kcp.Spec.Version) + if err != nil { + return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", kcp.Spec.Version) + } + // Get the imageRepository or the correct value if nothing is set and a migration is necessary. + imageRepository := internal.ImageRepositoryFromClusterConfig(kcp.Spec.KubeadmConfigSpec.ClusterConfiguration, parsedVersionTolerant) + if err := workloadCluster.UpdateImageRepositoryInKubeadmConfigMap(ctx, imageRepository, parsedVersion); err != nil { return ctrl.Result{}, errors.Wrap(err, "failed to update the image repository in the kubeadm config map") } diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go index c83919567840..d294064579ed 100644 --- a/controlplane/kubeadm/internal/workload_cluster.go +++ b/controlplane/kubeadm/internal/workload_cluster.go @@ -82,6 +82,14 @@ var ( // NOTE: The following assumes that kubeadm version equals to Kubernetes version. minVerUnversionedKubeletConfig = semver.MustParse("1.24.0") + // minKubernetesVersionImageRegistryMigration is first kubernetes version where + // the default image registry is registry.k8s.io instead of k8s.gcr.io. + minKubernetesVersionImageRegistryMigration = semver.MustParse("1.25.0") + + // nextKubernetesVersionImageRegistryMigration is the next minor version after + // the default image registry changed to registry.k8s.io. + nextKubernetesVersionImageRegistryMigration = semver.MustParse("1.26.0") + // ErrControlPlaneMinNodes signals that a cluster doesn't meet the minimum required nodes // to remove an etcd member. ErrControlPlaneMinNodes = errors.New("cluster has fewer than 2 control plane nodes; removing an etcd member is not supported") @@ -108,7 +116,7 @@ type WorkloadCluster interface { UpdateControllerManagerInKubeadmConfigMap(ctx context.Context, controllerManager bootstrapv1.ControlPlaneComponent, version semver.Version) error UpdateSchedulerInKubeadmConfigMap(ctx context.Context, scheduler bootstrapv1.ControlPlaneComponent, version semver.Version) error UpdateKubeletConfigMap(ctx context.Context, version semver.Version) error - UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane) error + UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane, version semver.Version) error UpdateCoreDNS(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane, version semver.Version) error RemoveEtcdMemberForMachine(ctx context.Context, machine *clusterv1.Machine) error RemoveMachineFromKubeadmConfigMap(ctx context.Context, machine *clusterv1.Machine, version semver.Version) error @@ -475,7 +483,7 @@ func staticPodName(component, nodeName string) string { } // UpdateKubeProxyImageInfo updates kube-proxy image in the kube-proxy DaemonSet. -func (w *Workload) UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane) error { +func (w *Workload) UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane, version semver.Version) error { // Return early if we've been asked to skip kube-proxy upgrades entirely. if _, ok := kcp.Annotations[controlplanev1.SkipKubeProxyAnnotation]; ok { return nil @@ -500,9 +508,11 @@ func (w *Workload) UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlpla if err != nil { return err } - if kcp.Spec.KubeadmConfigSpec.ClusterConfiguration != nil && - kcp.Spec.KubeadmConfigSpec.ClusterConfiguration.ImageRepository != "" { - newImageName, err = containerutil.ModifyImageRepository(newImageName, kcp.Spec.KubeadmConfigSpec.ClusterConfiguration.ImageRepository) + + // Modify the image repository if a value was explicitly set or an upgrade is required. + imageRepository := ImageRepositoryFromClusterConfig(kcp.Spec.KubeadmConfigSpec.ClusterConfiguration, version) + if imageRepository != "" { + newImageName, err = containerutil.ModifyImageRepository(newImageName, imageRepository) if err != nil { return err } @@ -545,3 +555,28 @@ func yamlToUnstructured(rawYAML []byte) (*unstructured.Unstructured, error) { err := yaml.Unmarshal(rawYAML, unst) return unst, err } + +// ImageRepositoryFromClusterConfig returns the image repository to use. It returns: +// * clusterConfig.ImageRepository if set. +// * "registry.k8s.io" if v1.25 <= version < v1.26 to migrate to the new registry +// * "" otherwise. +// Beginning with kubernetes v1.25, the default registry for kubernetes is registry.k8s.io +// instead of k8s.gcr.io which is why references should get migrated when upgrading to v1.25. +// The migration follows the behavior of `kubeadm upgrade`. +func ImageRepositoryFromClusterConfig(clusterConfig *bootstrapv1.ClusterConfiguration, kubernetesVersion semver.Version) string { + // If ImageRepository is explicitly specified, return early. + if clusterConfig != nil && + clusterConfig.ImageRepository != "" { + return clusterConfig.ImageRepository + } + + // If v1.25 <= version < v1.26 return the default Kubernetes image repository to + // migrate to the new location and not cause changes else. + if kubernetesVersion.GTE(minKubernetesVersionImageRegistryMigration) && + kubernetesVersion.LT(nextKubernetesVersionImageRegistryMigration) { + return kubernetesImageRepository + } + + // Use defaulting or current values otherwise. + return "" +} diff --git a/controlplane/kubeadm/internal/workload_cluster_coredns.go b/controlplane/kubeadm/internal/workload_cluster_coredns.go index 28c1c83a7ccf..bc09f1751bd6 100644 --- a/controlplane/kubeadm/internal/workload_cluster_coredns.go +++ b/controlplane/kubeadm/internal/workload_cluster_coredns.go @@ -47,9 +47,11 @@ const ( coreDNSVolumeKey = "config-volume" coreDNSClusterRoleName = "system:coredns" - kubernetesImageRepository = "k8s.gcr.io" - oldCoreDNSImageName = "coredns" - coreDNSImageName = "coredns/coredns" + // kubernetesImageRepository is the default Kubernetes image repository for build artifacts. + kubernetesImageRepository = "registry.k8s.io" + oldKubernetesImageRepository = "k8s.gcr.io" + oldCoreDNSImageName = "coredns" + coreDNSImageName = "coredns/coredns" ) var ( @@ -115,7 +117,7 @@ func (w *Workload) UpdateCoreDNS(ctx context.Context, kcp *controlplanev1.Kubead clusterConfig := kcp.Spec.KubeadmConfigSpec.ClusterConfiguration // Get the CoreDNS info needed for the upgrade. - info, err := w.getCoreDNSInfo(ctx, clusterConfig) + info, err := w.getCoreDNSInfo(ctx, clusterConfig, version) if err != nil { // Return early if we get a not found error, this can happen if any of the CoreDNS components // cannot be found, e.g. configmap, deployment. @@ -156,7 +158,7 @@ func (w *Workload) UpdateCoreDNS(ctx context.Context, kcp *controlplanev1.Kubead } // getCoreDNSInfo returns all necessary coredns based information. -func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv1.ClusterConfiguration) (*coreDNSInfo, error) { +func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv1.ClusterConfiguration, version semver.Version) (*coreDNSInfo, error) { // Get the coredns configmap and corefile. key := ctrlclient.ObjectKey{Name: coreDNSKey, Namespace: metav1.NamespaceSystem} cm, err := w.getConfigMap(ctx, key) @@ -193,8 +195,17 @@ func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv // Handle imageRepository. toImageRepository := parsedImage.Repository - if clusterConfig.ImageRepository != "" { - toImageRepository = strings.TrimSuffix(clusterConfig.ImageRepository, "/") + // Overwrite the image repository if a value was explicitly set or an upgrade is required. + if imageRegistryRepository := ImageRepositoryFromClusterConfig(clusterConfig, version); imageRegistryRepository != "" { + if imageRegistryRepository == kubernetesImageRepository { + // Only patch to KubernetesImageRepository if oldKubernetesImageRepository is set as prefix. + if strings.HasPrefix(toImageRepository, oldKubernetesImageRepository) { + // Ensure to keep the repository subpaths when patching from oldKubernetesImageRepository to new KubernetesImageRepository. + toImageRepository = strings.TrimSuffix(imageRegistryRepository+strings.TrimPrefix(toImageRepository, oldKubernetesImageRepository), "/") + } + } else { + toImageRepository = strings.TrimSuffix(imageRegistryRepository, "/") + } } if clusterConfig.DNS.ImageRepository != "" { toImageRepository = strings.TrimSuffix(clusterConfig.DNS.ImageRepository, "/") @@ -219,7 +230,8 @@ func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv // Handle the renaming of the upstream image from "k8s.gcr.io/coredns" to "k8s.gcr.io/coredns/coredns" toImageName := parsedImage.Name - if toImageRepository == kubernetesImageRepository && toImageName == oldCoreDNSImageName && targetMajorMinorPatch.GTE(semver.MustParse("1.8.0")) { + if (toImageRepository == oldKubernetesImageRepository || toImageRepository == kubernetesImageRepository) && + toImageName == oldCoreDNSImageName && targetMajorMinorPatch.GTE(semver.MustParse("1.8.0")) { toImageName = coreDNSImageName } @@ -429,10 +441,9 @@ func validateCoreDNSImageTag(fromTag, toTag string) error { if err != nil { return errors.Wrapf(err, "failed to parse CoreDNS target version %q", toTag) } - // make sure that the version we're upgrading to is greater than the current one, - // or if they're the same version, the raw tags should be different (e.g. allow from `v1.17.4-somevendor.0` to `v1.17.4-somevendor.1`). - if x := from.Compare(to); x > 0 || (x == 0 && fromTag == toTag) { - return fmt.Errorf("toVersion %q must be greater than fromVersion %q", toTag, fromTag) + // make sure that the version we're upgrading to is greater or equal to the current one, + if x := from.Compare(to); x > 0 { + return fmt.Errorf("toVersion %q must be greater than or equal to fromVersion %q", toTag, fromTag) } // check if the from version is even in the list of coredns versions if _, ok := migration.Versions[fmt.Sprintf("%d.%d.%d", from.Major, from.Minor, from.Patch)]; !ok { diff --git a/controlplane/kubeadm/internal/workload_cluster_coredns_test.go b/controlplane/kubeadm/internal/workload_cluster_coredns_test.go index bf24a15a2475..44e44f62dd44 100644 --- a/controlplane/kubeadm/internal/workload_cluster_coredns_test.go +++ b/controlplane/kubeadm/internal/workload_cluster_coredns_test.go @@ -611,10 +611,9 @@ func TestValidateCoreDNSImageTag(t *testing.T) { toVer: "1.6.5_foobar.2", }, { - name: "fromVer is equal to toVer", - fromVer: "1.6.5_foobar.1", - toVer: "1.6.5_foobar.1", - expectErrSubStr: "must be greater", + name: "fromVer is equal to toVer", + fromVer: "1.6.5_foobar.1", + toVer: "1.6.5_foobar.1", }, { name: "fromVer is lower but has meta", @@ -1100,30 +1099,8 @@ func TestUpdateCoreDNSCorefile(t *testing.T) { func TestGetCoreDNSInfo(t *testing.T) { t.Run("get coredns info", func(t *testing.T) { - expectedImage := "k8s.gcr.io/some-folder/coredns:1.6.2" - depl := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: "apps/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: coreDNSKey, - Namespace: metav1.NamespaceSystem, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Name: coreDNSKey, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Name: coreDNSKey, - Image: expectedImage, - }}, - }, - }, - }, - } + imageSomeFolder162 := "k8s.gcr.io/some-folder/coredns:1.6.2" + image162 := "k8s.gcr.io/coredns:1.6.2" expectedCorefile := "some-coredns-core-file" cm := &corev1.ConfigMap{ @@ -1139,18 +1116,9 @@ func TestGetCoreDNSInfo(t *testing.T) { emptycm := cm.DeepCopy() delete(emptycm.Data, "Corefile") - emptyDepl := depl.DeepCopy() + emptyDepl := newCoreDNSInfoDeploymentWithimage("") emptyDepl.Spec.Template.Spec.Containers = []corev1.Container{} - badContainerDepl := depl.DeepCopy() - badContainerDepl.Spec.Template.Spec.Containers[0].Image = "k8s.gcr.io/asd:1123/asd:coredns:1.6.1" - - noTagContainerDepl := depl.DeepCopy() - noTagContainerDepl.Spec.Template.Spec.Containers[0].Image = "k8s.gcr.io/coredns" - - badSemverContainerDepl := depl.DeepCopy() - badSemverContainerDepl.Spec.Template.Spec.Containers[0].Image = "k8s.gcr.io/coredns:v1X6.2" - clusterConfig := &bootstrapv1.ClusterConfiguration{ DNS: bootstrapv1.DNS{ ImageMeta: bootstrapv1.ImageMeta{ @@ -1163,21 +1131,29 @@ func TestGetCoreDNSInfo(t *testing.T) { badImgTagDNS.DNS.ImageTag = "v1X6.2-foobar.1" tests := []struct { - name string - expectErr bool - objs []client.Object - clusterConfig *bootstrapv1.ClusterConfiguration - toImage string + name string + expectErr bool + objs []client.Object + clusterConfig *bootstrapv1.ClusterConfiguration + kubernetesVersion semver.Version + expectedInfo coreDNSInfo }{ { name: "returns core dns info", - objs: []client.Object{depl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), cm}, clusterConfig: clusterConfig, - toImage: "myrepo/coredns:1.7.2-foobar.1", + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.7.2", + FromImage: imageSomeFolder162, + ToImage: "myrepo/coredns:1.7.2-foobar.1", + ToImageTag: "1.7.2-foobar.1", + }, }, { name: "uses global config ImageRepository if DNS ImageRepository is not set", - objs: []client.Object{depl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), cm}, clusterConfig: &bootstrapv1.ClusterConfiguration{ ImageRepository: "globalRepo/sub-path", DNS: bootstrapv1.DNS{ @@ -1186,11 +1162,18 @@ func TestGetCoreDNSInfo(t *testing.T) { }, }, }, - toImage: "globalRepo/sub-path/coredns:1.7.2-foobar.1", + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.7.2", + FromImage: imageSomeFolder162, + ToImage: "globalRepo/sub-path/coredns:1.7.2-foobar.1", + ToImageTag: "1.7.2-foobar.1", + }, }, { name: "uses DNS ImageRepository config if both global and DNS-level are set", - objs: []client.Object{depl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), cm}, clusterConfig: &bootstrapv1.ClusterConfiguration{ ImageRepository: "globalRepo", DNS: bootstrapv1.DNS{ @@ -1200,11 +1183,98 @@ func TestGetCoreDNSInfo(t *testing.T) { }, }, }, - toImage: "dnsRepo/coredns:1.7.2-foobar.1", + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.7.2", + FromImage: imageSomeFolder162, + ToImage: "dnsRepo/coredns:1.7.2-foobar.1", + ToImageTag: "1.7.2-foobar.1", + }, + }, + { + name: "patches ImageRepository to registry.k8s.io if it's set on neither global nor DNS-level and kubernetesVersion >= v1.25", + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), cm}, + clusterConfig: &bootstrapv1.ClusterConfiguration{ + DNS: bootstrapv1.DNS{ + ImageMeta: bootstrapv1.ImageMeta{ + ImageTag: "1.7.2-foobar.1", + }, + }, + }, + kubernetesVersion: semver.MustParse("1.25.0"), + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.7.2", + FromImage: imageSomeFolder162, + ToImage: "registry.k8s.io/some-folder/coredns:1.7.2-foobar.1", + ToImageTag: "1.7.2-foobar.1", + }, + }, + { + name: "rename to coredns/coredns when upgrading to coredns=1.8.0 and kubernetesVersion=1.24.0", + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(image162), cm}, + clusterConfig: &bootstrapv1.ClusterConfiguration{ + DNS: bootstrapv1.DNS{ + ImageMeta: bootstrapv1.ImageMeta{ + ImageTag: "1.8.0", + }, + }, + }, + kubernetesVersion: semver.MustParse("1.24.0"), + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.8.0", + FromImage: image162, + ToImage: "k8s.gcr.io/coredns/coredns:1.8.0", + ToImageTag: "1.8.0", + }, + }, + { + name: "rename to coredns/coredns when upgrading to coredns=1.8.0 and kubernetesVersion=1.26.0", + objs: []client.Object{newCoreDNSInfoDeploymentWithimage("registry.k8s.io/coredns:1.6.2"), cm}, + clusterConfig: &bootstrapv1.ClusterConfiguration{ + DNS: bootstrapv1.DNS{ + ImageMeta: bootstrapv1.ImageMeta{ + ImageTag: "1.8.0", + }, + }, + }, + kubernetesVersion: semver.MustParse("1.24.0"), + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.8.0", + FromImage: "registry.k8s.io/coredns:1.6.2", + ToImage: "registry.k8s.io/coredns/coredns:1.8.0", + ToImageTag: "1.8.0", + }, + }, + { + name: "patches ImageRepository to registry.k8s.io if it's set on neither global nor DNS-level and kubernetesVersion >= v1.25 and rename to coredns/coredns", + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(image162), cm}, + clusterConfig: &bootstrapv1.ClusterConfiguration{ + DNS: bootstrapv1.DNS{ + ImageMeta: bootstrapv1.ImageMeta{ + ImageTag: "1.8.0", + }, + }, + }, + kubernetesVersion: semver.MustParse("1.25.0"), + expectedInfo: coreDNSInfo{ + CurrentMajorMinorPatch: "1.6.2", + FromImageTag: "1.6.2", + TargetMajorMinorPatch: "1.8.0", + FromImage: image162, + ToImage: "registry.k8s.io/coredns/coredns:1.8.0", + ToImageTag: "1.8.0", + }, }, { name: "returns error if unable to find coredns config map", - objs: []client.Object{depl}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162)}, clusterConfig: clusterConfig, expectErr: true, }, @@ -1222,31 +1292,31 @@ func TestGetCoreDNSInfo(t *testing.T) { }, { name: "returns error if unable to find coredns corefile", - objs: []client.Object{depl, emptycm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), emptycm}, clusterConfig: clusterConfig, expectErr: true, }, { name: "returns error if unable to parse the container image", - objs: []client.Object{badContainerDepl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage("k8s.gcr.io/asd:1123/asd:coredns:1.6.1"), cm}, clusterConfig: clusterConfig, expectErr: true, }, { name: "returns error if container image has not tag", - objs: []client.Object{noTagContainerDepl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage("k8s.gcr.io/coredns"), cm}, clusterConfig: clusterConfig, expectErr: true, }, { name: "returns error if unable to semver parse container image", - objs: []client.Object{badSemverContainerDepl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage("k8s.gcr.io/coredns:v1X6.2"), cm}, clusterConfig: clusterConfig, expectErr: true, }, { name: "returns error if unable to semver parse dns image tag", - objs: []client.Object{depl, cm}, + objs: []client.Object{newCoreDNSInfoDeploymentWithimage(imageSomeFolder162), cm}, clusterConfig: badImgTagDNS, expectErr: true, }, @@ -1267,24 +1337,16 @@ func TestGetCoreDNSInfo(t *testing.T) { } } - actualInfo, err := w.getCoreDNSInfo(ctx, tt.clusterConfig) + actualInfo, err := w.getCoreDNSInfo(ctx, tt.clusterConfig, tt.kubernetesVersion) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return } g.Expect(err).ToNot(HaveOccurred()) - expectedInfo := &coreDNSInfo{ - Corefile: expectedCorefile, - Deployment: actualDepl, - CurrentMajorMinorPatch: "1.6.2", - TargetMajorMinorPatch: "1.7.2", - FromImage: expectedImage, - ToImage: tt.toImage, - FromImageTag: "1.6.2", - ToImageTag: "1.7.2-foobar.1", - } + tt.expectedInfo.Corefile = expectedCorefile + tt.expectedInfo.Deployment = actualDepl - g.Expect(actualInfo).To(Equal(expectedInfo)) + g.Expect(actualInfo).To(Equal(&tt.expectedInfo)) }) } }) @@ -1487,3 +1549,29 @@ func (m *fakeMigrator) Migrate(current, to, corefile string, deprecations bool) } return m.migratedCorefile, nil } + +func newCoreDNSInfoDeploymentWithimage(image string) *appsv1.Deployment { + return &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: coreDNSKey, + Namespace: metav1.NamespaceSystem, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Name: coreDNSKey, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: coreDNSKey, + Image: image, + }}, + }, + }, + }, + } +} diff --git a/controlplane/kubeadm/internal/workload_cluster_test.go b/controlplane/kubeadm/internal/workload_cluster_test.go index 7f43d4439c42..63bbea586df2 100644 --- a/controlplane/kubeadm/internal/workload_cluster_test.go +++ b/controlplane/kubeadm/internal/workload_cluster_test.go @@ -34,6 +34,7 @@ import ( clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1" + "sigs.k8s.io/cluster-api/util/version" "sigs.k8s.io/cluster-api/util/yaml" ) @@ -176,6 +177,16 @@ func TestUpdateKubeProxyImageInfo(t *testing.T) { }, }}, }, + { + name: "does update image repository to new default registry for v1.25 updates", + ds: newKubeProxyDSWithImage("k8s.gcr.io/kube-proxy:v1.24.0"), + expectErr: false, + expectImage: "registry.k8s.io/kube-proxy:v1.25.0-alpha.1", + KCP: &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + Version: "v1.25.0-alpha.1", + }}, + }, { name: "returns error if image repository is invalid", ds: newKubeProxyDS(), @@ -218,7 +229,9 @@ func TestUpdateKubeProxyImageInfo(t *testing.T) { w := &Workload{ Client: fakeClient, } - err := w.UpdateKubeProxyImageInfo(ctx, tt.KCP) + kubernetesVersion, err := version.ParseMajorMinorPatchTolerant(tt.KCP.Spec.Version) + gs.Expect(err).ToNot(HaveOccurred()) + err = w.UpdateKubeProxyImageInfo(ctx, tt.KCP, kubernetesVersion) if tt.expectErr { gs.Expect(err).To(HaveOccurred()) } else { diff --git a/test/e2e/data/infrastructure-docker/v1beta1/bases/cluster-with-topology.yaml b/test/e2e/data/infrastructure-docker/v1beta1/bases/cluster-with-topology.yaml index 86dd08459353..30b6e399489f 100644 --- a/test/e2e/data/infrastructure-docker/v1beta1/bases/cluster-with-topology.yaml +++ b/test/e2e/data/infrastructure-docker/v1beta1/bases/cluster-with-topology.yaml @@ -25,9 +25,6 @@ spec: replicas: ${WORKER_MACHINE_COUNT} failureDomain: fd4 variables: - # The imageRepository variable is defaulted by the Cluster webhook. - #- name: imageRepository - # value: k8s.gcr.io - name: etcdImageTag # We set an empty value to use the default tag kubeadm init is using. value: "" diff --git a/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start-runtimesdk.yaml b/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start-runtimesdk.yaml index d880f4cfa10c..933f76af8f8a 100644 --- a/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start-runtimesdk.yaml +++ b/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start-runtimesdk.yaml @@ -39,14 +39,6 @@ spec: openAPIV3Schema: type: string default: kindest - - name: imageRepository - required: true - schema: - openAPIV3Schema: - type: string - default: "k8s.gcr.io" - example: "k8s.gcr.io" - description: "imageRepository sets the container registry to pull images from. If empty, `k8s.gcr.io` will be used by default." - name: etcdImageTag required: true schema: @@ -76,19 +68,6 @@ spec: external: generateExtension: generate-patches.k8s-upgrade-with-runtimesdk validateExtension: validate-topology.k8s-upgrade-with-runtimesdk - - name: imageRepository - description: "Sets the imageRepository used for the KubeadmControlPlane." - definitions: - - selector: - apiVersion: controlplane.cluster.x-k8s.io/v1beta1 - kind: KubeadmControlPlaneTemplate - matchResources: - controlPlane: true - jsonPatches: - - op: add - path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository" - valueFrom: - variable: imageRepository # We have to pin the cgroupDriver to cgroupfs for Kubernetes < v1.24 because kind does not support systemd for those versions, but kubeadm >= 1.21 defaults to systemd. - name: cgroupDriver-controlPlane description: | diff --git a/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start.yaml b/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start.yaml index 2c8c9da1bc70..b5eac232b244 100644 --- a/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start.yaml +++ b/test/e2e/data/infrastructure-docker/v1beta1/clusterclass-quick-start.yaml @@ -51,14 +51,6 @@ spec: openAPIV3Schema: type: string default: kindest - - name: imageRepository - required: true - schema: - openAPIV3Schema: - type: string - default: "k8s.gcr.io" - example: "k8s.gcr.io" - description: "imageRepository sets the container registry to pull images from. If empty, `k8s.gcr.io` will be used by default." - name: etcdImageTag required: true schema: @@ -97,19 +89,6 @@ spec: valueFrom: template: | imageRepository: {{ .lbImageRepository }} - - name: imageRepository - description: "Sets the imageRepository used for the KubeadmControlPlane." - definitions: - - selector: - apiVersion: controlplane.cluster.x-k8s.io/v1beta1 - kind: KubeadmControlPlaneTemplate - matchResources: - controlPlane: true - jsonPatches: - - op: add - path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository" - valueFrom: - variable: imageRepository # We have to pin the cgroupDriver to cgroupfs for Kubernetes < v1.24 because kind does not support systemd for those versions, but kubeadm >= 1.21 defaults to systemd. - name: cgroupDriver-controlPlane description: | diff --git a/test/framework/daemonset_helpers.go b/test/framework/daemonset_helpers.go index 452802ba68c5..97f973c66f08 100644 --- a/test/framework/daemonset_helpers.go +++ b/test/framework/daemonset_helpers.go @@ -19,6 +19,7 @@ package framework import ( "context" + "github.com/blang/semver" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" @@ -38,13 +39,27 @@ type WaitForKubeProxyUpgradeInput struct { func WaitForKubeProxyUpgrade(ctx context.Context, input WaitForKubeProxyUpgradeInput, intervals ...interface{}) { By("Ensuring kube-proxy has the correct image") + parsedVersion, err := semver.ParseTolerant(input.KubernetesVersion) + Expect(err).ToNot(HaveOccurred()) + + // Beginning with kubernetes v1.25, kubernetes images including kube-proxy get published to registry.k8s.io instead of k8s.gcr.io. + // This ensures that the imageRepository setting gets patched to registry.k8s.io when upgrading from v1.24 or lower, + // but only if there was no imageRespository explicitly set at the KubeadmControlPlanes ClusterConfiguration. + // This follows the behavior of `kubeadm upgrade`. + wantKubeProxyRegistry := "registry.k8s.io" + if parsedVersion.LT(semver.Version{Major: 1, Minor: 25, Patch: 0, Pre: []semver.PRVersion{{VersionStr: "alpha"}}}) { + wantKubeProxyRegistry = "k8s.gcr.io" + } + wantKubeProxyImage := wantKubeProxyRegistry + "/kube-proxy:" + containerutil.SemverToOCIImageTag(input.KubernetesVersion) + Eventually(func() (bool, error) { ds := &appsv1.DaemonSet{} if err := input.Getter.Get(ctx, client.ObjectKey{Name: "kube-proxy", Namespace: metav1.NamespaceSystem}, ds); err != nil { return false, err } - if ds.Spec.Template.Spec.Containers[0].Image == "k8s.gcr.io/kube-proxy:"+containerutil.SemverToOCIImageTag(input.KubernetesVersion) { + + if ds.Spec.Template.Spec.Containers[0].Image == wantKubeProxyImage { return true, nil } return false, nil diff --git a/test/infrastructure/docker/templates/cluster-template-development.yaml b/test/infrastructure/docker/templates/cluster-template-development.yaml index 03cdc4bbda75..03a4c8efa8b0 100644 --- a/test/infrastructure/docker/templates/cluster-template-development.yaml +++ b/test/infrastructure/docker/templates/cluster-template-development.yaml @@ -17,7 +17,7 @@ spec: replicas: ${CONTROL_PLANE_MACHINE_COUNT} variables: - name: imageRepository - value: "k8s.gcr.io" + value: "" - name: etcdImageTag value: "" - name: coreDNSImageTag diff --git a/test/infrastructure/docker/templates/clusterclass-quick-start.yaml b/test/infrastructure/docker/templates/clusterclass-quick-start.yaml index b38f1831573e..c2c193c7297a 100644 --- a/test/infrastructure/docker/templates/clusterclass-quick-start.yaml +++ b/test/infrastructure/docker/templates/clusterclass-quick-start.yaml @@ -38,9 +38,9 @@ spec: schema: openAPIV3Schema: type: string - default: "k8s.gcr.io" - example: "k8s.gcr.io" - description: "imageRepository sets the container registry to pull images from. If empty, `k8s.gcr.io` will be used by default." + default: "" + example: "registry.k8s.io" + description: "imageRepository sets the container registry to pull images from. If empty, nothing will be set and the from of kubeadm will be used." - name: etcdImageTag required: true schema: @@ -82,6 +82,7 @@ spec: patches: - name: imageRepository description: "Sets the imageRepository used for the KubeadmControlPlane." + enabledIf: '{{ ne .imageRepository "" }}' definitions: - selector: apiVersion: controlplane.cluster.x-k8s.io/v1beta1