Skip to content

Commit

Permalink
Merge pull request #88811 from rajansandeep/invalidmigrationfail
Browse files Browse the repository at this point in the history
Ensure CoreDNS running when Corefile migration doesn't support current version
  • Loading branch information
k8s-ci-robot committed Mar 18, 2020
2 parents c539094 + fcd229e commit be2f9e7
Showing 1 changed file with 63 additions and 26 deletions.
89 changes: 63 additions & 26 deletions cmd/kubeadm/app/phases/addons/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,26 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien
return errors.Wrap(err, "unable to fetch CoreDNS current installed version and ConfigMap.")
}

var hasCoreDNSMigrationFailed bool
if IsCoreDNSConfigMapMigrationRequired(corefile) {
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 {
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.
hasCoreDNSMigrationFailed = true
canMigrateCorefile = false
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
Expand Down Expand Up @@ -326,7 +340,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien
}

// Create the deployment for CoreDNS or retain it in case the CoreDNS migration has failed during upgrade
if hasCoreDNSMigrationFailed {
if !canMigrateCorefile {
if err := apiclient.CreateOrRetainDeployment(client, coreDNSDeployment, kubeadmconstants.CoreDNSDeploymentName); err != nil {
return err
}
Expand Down Expand Up @@ -362,40 +376,57 @@ func createDNSService(dnsService *v1.Service, serviceBytes []byte, client client
return nil
}

// IsCoreDNSConfigMapMigrationRequired checks if a migration of the CoreDNS ConfigMap is required.
func IsCoreDNSConfigMapMigrationRequired(corefile string) bool {
// isCoreDNSConfigMapMigrationRequired checks if a migration of the CoreDNS ConfigMap is required.
func isCoreDNSConfigMapMigrationRequired(corefile, currentInstalledCoreDNSVersion string) (bool, error) {
var isMigrationRequired bool
if corefile == "" || migration.Default("", corefile) {
return false
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.")
}
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.
// 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
}
}

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,
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",
},
}, metav1.UpdateOptions{}); err != nil {
return errors.Wrap(err, "unable to update the CoreDNS ConfigMap with backup Corefile")
)
if err != nil {
return false, errors.Wrap(err, "unable to list CoreDNS pods")
}
if err := patchCoreDNSDeployment(client, "Corefile-backup"); err != nil {
return err

for _, pod := range coreDNSPodList.Items {
imageID := strings.Split(pod.Status.ContainerStatuses[0].ImageID, ":")
if !migration.Released(imageID[2]) {
isValidVersion = false
}
}

return isValidVersion, nil
}

func migrateCoreDNSCorefile(client clientset.Interface, cm *v1.ConfigMap, corefile, currentInstalledCoreDNSVersion string) error {
// 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")
}

// Take a copy of the existing Corefile data as `Corefile-backup` and update the ConfigMap
if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Update(context.TODO(), &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: kubeadmconstants.CoreDNSConfigMap,
Expand All @@ -408,6 +439,12 @@ func migrateCoreDNSCorefile(client clientset.Interface, cm *v1.ConfigMap, corefi
}, metav1.UpdateOptions{}); err != nil {
return errors.Wrap(err, "unable to update the CoreDNS ConfigMap")
}

// Point the CoreDNS deployment to the `Corefile-backup` data.
if err := setCorefile(client, "Corefile-backup"); err != nil {
return err
}

fmt.Println("[addons] Migrating CoreDNS Corefile")
changes, err := migration.Deprecated(currentInstalledCoreDNSVersion, kubeadmconstants.CoreDNSVersion, corefile)
if err != nil {
Expand Down Expand Up @@ -445,12 +482,12 @@ func GetCoreDNSInfo(client clientset.Interface) (*v1.ConfigMap, string, string,
return coreDNSConfigMap, corefile, currentCoreDNSversion, nil
}

func patchCoreDNSDeployment(client clientset.Interface, coreDNSCorefileName string) error {
func setCorefile(client clientset.Interface, coreDNSCorefileName string) error {
dnsDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), kubeadmconstants.CoreDNSDeploymentName, metav1.GetOptions{})
if err != nil {
return err
}
patch := fmt.Sprintf(`{"spec":{"template":{"spec":{"volumes":[{"name": "config-volume", "configMap":{"name": "coredns", "items":[{"key": "%s", "path": "%s"}]}}]}}}}`, coreDNSCorefileName, coreDNSCorefileName)
patch := fmt.Sprintf(`{"spec":{"template":{"spec":{"volumes":[{"name": "config-volume", "configMap":{"name": "coredns", "items":[{"key": "%s", "path": "Corefile"}]}}]}}}}`, coreDNSCorefileName)

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")
Expand Down

0 comments on commit be2f9e7

Please sign in to comment.