Skip to content

Commit

Permalink
Fix CoreDNS upgrade from v1.20 to v1.21
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziopandini committed Apr 14, 2021
1 parent 768695b commit c3d4051
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 14 deletions.
26 changes: 17 additions & 9 deletions controlplane/kubeadm/internal/workload_cluster_coredns.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package internal
import (
"context"
"fmt"
"strings"

"github.com/blang/semver"
"sigs.k8s.io/cluster-api/util/version"

"github.com/coredns/corefile-migration/migration"
Expand Down Expand Up @@ -156,12 +158,12 @@ func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv
}

// Handle imageRepository.
toImageRepository := fmt.Sprintf("%s/%s", parsedImage.Repository, parsedImage.Name)
toImageRepository := parsedImage.Repository
if clusterConfig.ImageRepository != "" {
toImageRepository = fmt.Sprintf("%s/%s", clusterConfig.ImageRepository, coreDNSKey)
toImageRepository = strings.TrimSuffix(clusterConfig.ImageRepository, "/")
}
if clusterConfig.DNS.ImageRepository != "" {
toImageRepository = fmt.Sprintf("%s/%s", clusterConfig.DNS.ImageRepository, coreDNSKey)
toImageRepository = strings.TrimSuffix(clusterConfig.DNS.ImageRepository, "/")
}

// Handle imageTag.
Expand All @@ -181,15 +183,21 @@ func (w *Workload) getCoreDNSInfo(ctx context.Context, clusterConfig *bootstrapv
return nil, err
}

// Handle the renaming of the upstream image from "k8s.gcr.io/coredns" to "k8s.gcr.io/coredns/coredns"
toImageName := parsedImage.Name
if toImageRepository == "k8s.gcr.io" && toImageName == "coredns" && targetMajorMinorPatch.GTE(semver.MustParse("1.8.0")) {
toImageName = "coredns/coredns"
}

return &coreDNSInfo{
Corefile: corefile,
Deployment: deployment,
CurrentMajorMinorPatch: currentMajorMinorPatch,
TargetMajorMinorPatch: targetMajorMinorPatch,
CurrentMajorMinorPatch: currentMajorMinorPatch.String(),
TargetMajorMinorPatch: targetMajorMinorPatch.String(),
FromImageTag: parsedImage.Tag,
ToImageTag: toImageTag,
FromImage: container.Image,
ToImage: fmt.Sprintf("%s:%s", toImageRepository, toImageTag),
ToImage: fmt.Sprintf("%s/%s:%s", toImageRepository, toImageName, toImageTag),
}, nil
}

Expand Down Expand Up @@ -298,12 +306,12 @@ func patchCoreDNSDeploymentImage(deployment *appsv1.Deployment, image string) {
}
}

func extractImageVersion(tag string) (string, error) {
func extractImageVersion(tag string) (semver.Version, error) {
ver, err := version.ParseMajorMinorPatchTolerant(tag)
if err != nil {
return "", err
return semver.Version{}, err
}
return fmt.Sprintf("%d.%d.%d", ver.Major, ver.Minor, ver.Patch), nil
return ver, nil
}

// validateCoreDNSImageTag returns error if the versions don't meet requirements.
Expand Down
116 changes: 111 additions & 5 deletions controlplane/kubeadm/internal/workload_cluster_coredns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestUpdateCoreDNS(t *testing.T) {
"BadCoreFileKey": "",
},
}
expectedImage := "k8s.gcr.io/some-folder/coredns:1.6.2"

depl := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
Expand All @@ -82,7 +82,7 @@ func TestUpdateCoreDNS(t *testing.T) {
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: coreDNSKey,
Image: expectedImage,
Image: "k8s.gcr.io/some-folder/coredns:1.6.2",
}},
},
},
Expand All @@ -92,6 +92,12 @@ func TestUpdateCoreDNS(t *testing.T) {
},
}

deplWithImage := func(image string) *appsv1.Deployment {
d := depl.DeepCopy()
d.Spec.Template.Spec.Containers[0].Image = image
return d
}

expectedCorefile := "coredns-core-file"
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -125,6 +131,7 @@ kind: ClusterConfiguration
objs []client.Object
expectErr bool
expectUpdates bool
expectImage string
}{
{
name: "returns early without error if skip core dns annotation is present",
Expand Down Expand Up @@ -282,6 +289,105 @@ kind: ClusterConfiguration
objs: []client.Object{depl, cm, kubeadmCM},
expectErr: false,
expectUpdates: true,
expectImage: "k8s.gcr.io/some-repo/coredns:1.7.2",
},
{
name: "kubeadm defaults, upgrade from Kubernetes v1.18.x to v1.19.y (from k8s.gcr.io/coredns:1.6.7 to k8s.gcr.io/coredns:1.7.0)",
kcp: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{
KubeadmConfigSpec: cabpkv1.KubeadmConfigSpec{
ClusterConfiguration: &bootstrapv1.ClusterConfiguration{
DNS: bootstrapv1.DNS{
Type: bootstrapv1.CoreDNS,
ImageMeta: bootstrapv1.ImageMeta{
ImageRepository: "k8s.gcr.io",
ImageTag: "1.7.0",
},
},
},
},
},
},
migrator: &fakeMigrator{
migratedCorefile: "updated-core-file",
},
objs: []client.Object{deplWithImage("k8s.gcr.io/coredns:1.6.7"), cm, kubeadmCM},
expectErr: false,
expectUpdates: true,
expectImage: "k8s.gcr.io/coredns:1.7.0",
},
{
name: "kubeadm defaults, upgrade from Kubernetes v1.19.x to v1.20.y (stay on k8s.gcr.io/coredns:1.7.0)",
kcp: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{
KubeadmConfigSpec: cabpkv1.KubeadmConfigSpec{
ClusterConfiguration: &bootstrapv1.ClusterConfiguration{
DNS: bootstrapv1.DNS{
Type: bootstrapv1.CoreDNS,
ImageMeta: bootstrapv1.ImageMeta{
ImageRepository: "k8s.gcr.io",
ImageTag: "1.7.0",
},
},
},
},
},
},
migrator: &fakeMigrator{
migratedCorefile: "updated-core-file",
},
objs: []client.Object{deplWithImage("k8s.gcr.io/coredns:1.7.0"), cm, kubeadmCM},
expectErr: false,
expectUpdates: false,
},
{
name: "kubeadm defaults, upgrade from Kubernetes v1.20.x to v1.21.y (from k8s.gcr.io/coredns:1.7.0 to k8s.gcr.io/coredns/coredns:v1.8.0)",
kcp: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{
KubeadmConfigSpec: cabpkv1.KubeadmConfigSpec{
ClusterConfiguration: &bootstrapv1.ClusterConfiguration{
DNS: bootstrapv1.DNS{
Type: bootstrapv1.CoreDNS,
ImageMeta: bootstrapv1.ImageMeta{
ImageRepository: "k8s.gcr.io",
ImageTag: "v1.8.0", // NOTE: ImageTags requires the v prefix
},
},
},
},
},
},
migrator: &fakeMigrator{
migratedCorefile: "updated-core-file",
},
objs: []client.Object{deplWithImage("k8s.gcr.io/coredns:1.7.0"), cm, kubeadmCM},
expectErr: false,
expectUpdates: true,
expectImage: "k8s.gcr.io/coredns/coredns:v1.8.0", // NOTE: ImageName has coredns/coredns
},
{
name: "kubeadm defaults, upgrade from Kubernetes v1.21.x to v1.22.y (stay on k8s.gcr.io/coredns/coredns:v1.8.0)",
kcp: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{
KubeadmConfigSpec: cabpkv1.KubeadmConfigSpec{
ClusterConfiguration: &bootstrapv1.ClusterConfiguration{
DNS: bootstrapv1.DNS{
Type: bootstrapv1.CoreDNS,
ImageMeta: bootstrapv1.ImageMeta{
ImageRepository: "k8s.gcr.io",
ImageTag: "v1.8.0", // NOTE: ImageTags requires the v prefix
},
},
},
},
},
},
migrator: &fakeMigrator{
migratedCorefile: "updated-core-file",
},
objs: []client.Object{deplWithImage("k8s.gcr.io/coredns/coredns:v1.8.0"), cm, kubeadmCM},
expectErr: false,
expectUpdates: false,
},
}

Expand Down Expand Up @@ -336,8 +442,8 @@ kind: ClusterConfiguration
// assert kubeadmConfigMap
var expectedKubeadmConfigMap corev1.ConfigMap
g.Expect(testEnv.Get(ctx, ctrlclient.ObjectKey{Name: kubeadmConfigKey, Namespace: metav1.NamespaceSystem}, &expectedKubeadmConfigMap)).To(Succeed())
g.Expect(expectedKubeadmConfigMap.Data).To(HaveKeyWithValue("ClusterConfiguration", ContainSubstring("1.7.2")))
g.Expect(expectedKubeadmConfigMap.Data).To(HaveKeyWithValue("ClusterConfiguration", ContainSubstring("k8s.gcr.io/some-repo")))
g.Expect(expectedKubeadmConfigMap.Data).To(HaveKeyWithValue("ClusterConfiguration", ContainSubstring(tt.kcp.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageTag)))
g.Expect(expectedKubeadmConfigMap.Data).To(HaveKeyWithValue("ClusterConfiguration", ContainSubstring(tt.kcp.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageRepository)))

// assert CoreDNS corefile
var expectedConfigMap corev1.ConfigMap
Expand All @@ -351,7 +457,7 @@ kind: ClusterConfiguration
g.Eventually(func() string {
g.Expect(testEnv.Get(ctx, ctrlclient.ObjectKey{Name: coreDNSKey, Namespace: metav1.NamespaceSystem}, &actualDeployment)).To(Succeed())
return actualDeployment.Spec.Template.Spec.Containers[0].Image
}, "5s").Should(Equal("k8s.gcr.io/some-repo/coredns:1.7.2"))
}, "5s").Should(Equal(tt.expectImage))
}
})
}
Expand Down

0 comments on commit c3d4051

Please sign in to comment.