Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure CoreDNS running when Corefile migration doesn't support current version #88811

Merged
merged 1 commit into from Mar 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 63 additions & 26 deletions cmd/kubeadm/app/phases/addons/dns/dns.go
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should setCorefile() be after this too? Just in case this fails?

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