diff --git a/cmd/kubeadm/app/phases/addons/dns/dns.go b/cmd/kubeadm/app/phases/addons/dns/dns.go index 39e8cf9e401..814a993dbbc 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -236,9 +236,17 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien if err != nil { return errors.Wrap(err, "unable to fetch CoreDNS current installed version and ConfigMap.") } + + var hasCoreDNSMigrationFailed bool if IsCoreDNSConfigMapMigrationRequired(corefile) { if err := migrateCoreDNSCorefile(client, coreDNSConfigMap, corefile, currentInstalledCoreDNSVersion); err != nil { - return err + // Errors in Corefile Migration is verified during preflight checks. This part will be executed when a user has chosen + // to ignore preflight check errors. + hasCoreDNSMigrationFailed = true + klog.Warningf("the CoreDNS Configuration was not migrated: %v. The existing CoreDNS Corefile configuration has been retained.", err) + if err := apiclient.CreateOrRetainConfigMap(client, coreDNSConfigMap, kubeadmconstants.CoreDNSConfigMap); err != nil { + return err + } } } else { if err := apiclient.CreateOrUpdateConfigMap(client, coreDNSConfigMap); err != nil { @@ -281,9 +289,16 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien return errors.Wrapf(err, "%s Deployment", unableToDecodeCoreDNS) } - // Create the Deployment for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateDeployment(client, coreDNSDeployment); err != nil { - return err + // Create the deployment for CoreDNS or retain it in case the CoreDNS migration has failed during upgrade + if hasCoreDNSMigrationFailed { + if err := apiclient.CreateOrRetainDeployment(client, coreDNSDeployment, kubeadmconstants.CoreDNSDeploymentName); err != nil { + return err + } + } else { + // Create the Deployment for CoreDNS or update it in case it already exists + if err := apiclient.CreateOrUpdateDeployment(client, coreDNSDeployment); err != nil { + return err + } } coreDNSService := &v1.Service{} diff --git a/cmd/kubeadm/app/phases/upgrade/preflight.go b/cmd/kubeadm/app/phases/upgrade/preflight.go index 0720b06a14f..e7b50c93fcb 100644 --- a/cmd/kubeadm/app/phases/upgrade/preflight.go +++ b/cmd/kubeadm/app/phases/upgrade/preflight.go @@ -108,7 +108,7 @@ func checkMigration(client clientset.Interface) error { _, err = migration.Migrate(currentInstalledCoreDNSversion, kubeadmconstants.CoreDNSVersion, corefile, false) if err != nil { - return err + return errors.Wrap(err, "CoreDNS will not be upgraded") } return nil } diff --git a/cmd/kubeadm/app/util/apiclient/idempotency.go b/cmd/kubeadm/app/util/apiclient/idempotency.go index 40900ee52e5..4ae951db3c5 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency.go @@ -147,6 +147,21 @@ func CreateOrUpdateDeployment(client clientset.Interface, deploy *apps.Deploymen return nil } +// CreateOrRetainDeployment creates a Deployment if the target resource doesn't exist. If the resource exists already, this function will retain the resource instead. +func CreateOrRetainDeployment(client clientset.Interface, deploy *apps.Deployment, deployName string) error { + if _, err := client.AppsV1().Deployments(deploy.ObjectMeta.Namespace).Get(deployName, metav1.GetOptions{}); err != nil { + if !apierrors.IsNotFound(err) { + return nil + } + if _, err := client.AppsV1().Deployments(deploy.ObjectMeta.Namespace).Create(deploy); err != nil { + if !apierrors.IsAlreadyExists(err) { + return errors.Wrap(err, "unable to create deployment") + } + } + } + return nil +} + // CreateOrUpdateDaemonSet creates a DaemonSet if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. func CreateOrUpdateDaemonSet(client clientset.Interface, ds *apps.DaemonSet) error { if _, err := client.AppsV1().DaemonSets(ds.ObjectMeta.Namespace).Create(ds); err != nil {