Change:
Is this a BUG REPORT or FEATURE REQUEST?: /kind bug /sig apps What happened: Attempting a on a deployment where the only change between revisions is the addition of a single label fails with . The addition of more than one label will successfully be detected as a Template change and the rollback will occur successfully. Example: The additional label was to the pod template (both and were tested) and a new ReplicaSet with a unique pod-template-hash was generated. revision 1 revision 2 Rollout undo Repeating the above steps but adding an additional label does successfully trigger a successful What you expected to happen: The deployment is able to be successfully rolled back. How to reproduce it (as minimally and precisely as possible): 1) Create a deployment (use example above) 2) Update the deployment by adding a single additional label to the Pod Template 3) Attempt to rollback to the revision without the single additional label Anything else we need to know?: Tested both with and Environment: Kubernetes version (use ): minikube gke Cloud provider or hardware configuration: OS (e.g. from /etc/os-release): client: OSX High Sierra minikube: v0.25.2 / Buildroot 2017.11 gke: Container-Optimized OS from Google
thanks for reporting this! It's a bug in the template comparison function. A fix is underway.

Discussion:
} // EqualIgnoreHash returns true if two given podTemplateSpec are equal, ignoring the diff in value of Labels[pod-template-hash] <del> // We ignore pod-template-hash because the hash result would be different upon podTemplateSpec API changes // (e.g. the addition of a new field will cause the hash code to change) // Note that we assume input podTemplateSpecs contain non-empty labels </del> <ins> // We ignore pod-template-hash because: // 1. The hash result would be different upon podTemplateSpec API changes //    (e.g. the addition of a new field will cause the hash code to change) // 2. The deployment template won't have hash labels </ins> func EqualIgnoreHash(template1, template2 *v1.PodTemplateSpec) bool { t1Copy := template1.DeepCopy() t2Copy := template2.DeepCopy() <del> // First, compare template.Labels (ignoring hash) labels1, labels2 := t1Copy.Labels, t2Copy.Labels if len(labels1) > len(labels2) { labels1, labels2 = labels2, labels1 } // We make sure len(labels2) >= len(labels1) for k, v := range labels2 { if labels1[k] != v && k != extensions.DefaultDeploymentUniqueLabelKey { return false } } // Then, compare the templates without comparing their labels t1Copy.Labels, t2Copy.Labels = nil, nil </del> <ins> // Remove hash labels from template.Labels before comparing delete(t1Copy.Labels, extensions.DefaultDeploymentUniqueLabelKey) delete(t2Copy.Labels, extensions.DefaultDeploymentUniqueLabelKey) </ins> return apiequality.Semantic.DeepEqual(t1Copy, t2Copy) }

true, }, { <ins> "Same spec, the label is different, the former doesn't have pod-template-hash label, same number of labels", generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{"something": "else"}), generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-2"}), false, }, { "Same spec, the label is different, the latter doesn't have pod-template-hash label, same number of labels", generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1"}), generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{"something": "else"}), false, }, { </ins> "Same spec, the label is different, and the pod-template-hash label value is the same", generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1"}), generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}),