Change:
What happened: Coredns failed to start in 1.17 deployment when it tried to retain a backed up Corefile with error message: Caddyfile via flag: open /etc/coredns/Corefile: no such file or directory What you expected to happen: Coredns starts normally with the backed-up Corefile How to reproduce it (as minimally and precisely as possible): Deploy a k8s 1.17 cluster and trigger coredns Corefile migration and make it fail. In our case, this was triggered in a three master -setup with 'old' method of running 'kubeadm init' for each master. Also the core-dns docker image used was tagged with '1.6.7-1', apparently causing the corefile migration version check to fail Anything else we need to know?: This seems to be caused by Both 'key' and 'path' are set to 'Corefile-backup' when this function is called. Should the 'path' always stay as 'Corefile' because that is where the container expects to find the config file? Environment: Kubernetes version (use ): Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"", GitTreeState:"clean", BuildDate:"2020-02-16T17:51:57Z", GoVersion:"go1.13.6", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"", GitTreeState:"clean", BuildDate:"2020-02-16T17:47:13Z", GoVersion:"go1.13.6", Compiler:"gc", Platform:"linux/amd64"} Cloud provider or hardware configuration: Custom deployment in Openstack environment OS (e.g: ): NAME="SLES" VERSION="15-SP1" VERSIONID="15.1" PRETTYNAME="SUSE Linux Enterprise Server 15 SP1" Kernel (e.g. ): 12.14-197.29-default Install tools: kubeadm Network plugin and version (if this is a network-related bug): Others:
/sig cluster-lifecycle
/assign
/area kubeadm

Discussion:
return errors.Wrap(err, "unable to fetch CoreDNS current installed version and ConfigMap.") } <del> var hasCoreDNSMigrationFailed bool if IsCoreDNSConfigMapMigrationRequired(corefile) { </del> <ins> canMigrateCorefile, err := isCoreDNSVersionSupported(client) if err != nil { return err } corefileMigrationRequired, err := isCoreDNSConfigMapMigrationRequired(corefile, currentInstalledCoreDNSVersion) if err != nil { return err } if !canMigrateCorefile { klog.Warningf("the CoreDNS Configuration will not be migrated due to unsupported version of CoreDNS. " + "The existing CoreDNS Corefile configuration and deployment has been retained.") } if corefileMigrationRequired && canMigrateCorefile { </ins> if err := migrateCoreDNSCorefile(client, coreDNSConfigMap, corefile, currentInstalledCoreDNSVersion); err != nil { // Errors in Corefile Migration is verified during preflight checks. This part will be executed when a user has chosen // to ignore preflight check errors. <del> hasCoreDNSMigrationFailed = true </del> <ins> canMigrateCorefile = false </ins> 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

} // Create the deployment for CoreDNS or retain it in case the CoreDNS migration has failed during upgrade <del> if hasCoreDNSMigrationFailed { </del> <ins> if !canMigrateCorefile { </ins> if err := apiclient.CreateOrRetainDeployment(client, coreDNSDeployment, kubeadmconstants.CoreDNSDeploymentName); err != nil { return err }

return nil } <del> // IsCoreDNSConfigMapMigrationRequired checks if a migration of the CoreDNS ConfigMap is required. func IsCoreDNSConfigMapMigrationRequired(corefile string) bool { </del> <ins> // isCoreDNSConfigMapMigrationRequired checks if a migration of the CoreDNS ConfigMap is required. func isCoreDNSConfigMapMigrationRequired(corefile, currentInstalledCoreDNSVersion string) (bool, error) { var isMigrationRequired bool </ins> if corefile == "" || migration.Default("", corefile) { <del> return false </del> <ins> return isMigrationRequired, nil } deprecated, err := migration.Deprecated(currentInstalledCoreDNSVersion, kubeadmconstants.CoreDNSVersion, corefile) if err != nil { return isMigrationRequired, errors.Wrap(err, "unable to get list of changes to the configuration.") </ins> } <del> return true } func migrateCoreDNSCorefile(client clientset.Interface, cm *v1.ConfigMap, corefile, currentInstalledCoreDNSVersion string) error { // Take a copy of the Corefile data as `Corefile-backup` and update the ConfigMap // Also point the CoreDNS deployment to the `Corefile-backup` data. </del> <ins> // Check if there are any plugins/options which needs to be removed or is a new default for _, dep := range deprecated { if dep.Severity == "removed" || dep.Severity == "newDefault" { isMigrationRequired = true } } </ins> <del> if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Update(context.TODO(), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name:      kubeadmconstants.CoreDNSConfigMap, Namespace: metav1.NamespaceSystem, }, Data: map[string]string{ "Corefile":        corefile, "Corefile-backup": corefile, </del> <ins> return isMigrationRequired, nil } func isCoreDNSVersionSupported(client clientset.Interface) (bool, error) { isValidVersion := true coreDNSPodList, err := client.CoreV1().Pods(metav1.NamespaceSystem).List( context.TODO(), metav1.ListOptions{ LabelSelector: "k8s-app=kube-dns", </ins> }, <del> }, metav1.UpdateOptions{}); err != nil { return errors.Wrap(err, "unable to update the CoreDNS ConfigMap with backup Corefile") </del> <ins> ) if err != nil { return false, errors.Wrap(err, "unable to list CoreDNS pods") </ins> } <del> if err := patchCoreDNSDeployment(client, "Corefile-backup"); err != nil { return err </del> <ins> for _, pod := range coreDNSPodList.Items { imageID := strings.Split(pod.Status.ContainerStatuses[0].ImageID, ":") if !migration.Released(imageID[2]) { isValidVersion = false } </ins> } <ins> return isValidVersion, nil } func migrateCoreDNSCorefile(client clientset.Interface, cm *v1.ConfigMap, corefile, currentInstalledCoreDNSVersion string) error { </ins> // Since the current configuration present is not the default version, try and migrate it. updatedCorefile, err := migration.Migrate(currentInstalledCoreDNSVersion, kubeadmconstants.CoreDNSVersion, corefile, false) if err != nil { return errors.Wrap(err, "unable to migrate CoreDNS ConfigMap") } <ins> // Take a copy of the existing Corefile data as `Corefile-backup` and update the ConfigMap </ins> if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Update(context.TODO(), &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name:      kubeadmconstants.CoreDNSConfigMap,

}, metav1.UpdateOptions{}); err != nil { return errors.Wrap(err, "unable to update the CoreDNS ConfigMap") } <ins> // Point the CoreDNS deployment to the `Corefile-backup` data. if err := setCorefile(client, "Corefile-backup"); err != nil { return err } </ins> fmt.Println("[addons] Migrating CoreDNS Corefile") changes, err := migration.Deprecated(currentInstalledCoreDNSVersion, kubeadmconstants.CoreDNSVersion, corefile) if err != nil {

return coreDNSConfigMap, corefile, currentCoreDNSversion, nil } <del> func patchCoreDNSDeployment(client clientset.Interface, coreDNSCorefileName string) error { </del> <ins> func setCorefile(client clientset.Interface, coreDNSCorefileName string) error { </ins> dnsDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), kubeadmconstants.CoreDNSDeploymentName, metav1.GetOptions{}) if err != nil { return err } <del> patch := fmt.Sprintf(`{"spec":{"template":{"spec":{"volumes":[{"name": "config-volume", "configMap":{"name": "coredns", "items":[{"key": "%s", "path": "%s"}]}}]}}}}`, coreDNSCorefileName, coreDNSCorefileName) </del> <ins> patch := fmt.Sprintf(`{"spec":{"template":{"spec":{"volumes":[{"name": "config-volume", "configMap":{"name": "coredns", "items":[{"key": "%s", "path": "Corefile"}]}}]}}}}`, coreDNSCorefileName) </ins> if _, err := client.AppsV1().Deployments(dnsDeployment.ObjectMeta.Namespace).Patch(context.TODO(), dnsDeployment.Name, types.StrategicMergePatchType, []byte(patch), metav1.PatchOptions{}); err != nil { return errors.Wrap(err, "unable to patch the CoreDNS deployment")