mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Deployment: Remove Overlap and SelectorUpdate annotations.
These are not used anymore since ControllerRef now protects against fighting between controllers with overlapping selectors.
This commit is contained in:
parent
94b3c216a1
commit
cec3899b96
@ -2382,10 +2382,6 @@ run_deployment_tests() {
|
||||
# Check that trying to watch the status of a superseded revision returns an error
|
||||
! kubectl rollout status deployment/nginx --revision=3
|
||||
cat hack/testdata/deployment-revision1.yaml | $SED "s/name: nginx$/name: nginx2/" | kubectl create -f - "${kube_flags[@]}"
|
||||
# Newest deployment should be marked as overlapping
|
||||
kubectl get deployment nginx2 -o yaml "${kube_flags[@]}" | grep "deployment.kubernetes.io/error-selector-overlapping-with"
|
||||
# Oldest deployment should not be marked as overlapping
|
||||
! kubectl get deployment nginx -o yaml "${kube_flags[@]}" | grep "deployment.kubernetes.io/error-selector-overlapping-with"
|
||||
# Deletion of both deployments should not be blocked
|
||||
kubectl delete deployment nginx2 "${kube_flags[@]}"
|
||||
# Clean up
|
||||
|
@ -67,14 +67,6 @@ const (
|
||||
RollbackTemplateUnchanged = "DeploymentRollbackTemplateUnchanged"
|
||||
// RollbackDone is the done rollback event reason
|
||||
RollbackDone = "DeploymentRollback"
|
||||
// OverlapAnnotation marks deployments with overlapping selector with other deployments
|
||||
// TODO: Delete this annotation when we gracefully handle overlapping selectors.
|
||||
// See https://github.com/kubernetes/kubernetes/issues/2210
|
||||
OverlapAnnotation = "deployment.kubernetes.io/error-selector-overlapping-with"
|
||||
// SelectorUpdateAnnotation marks the last time deployment selector update
|
||||
// TODO: Delete this annotation when we gracefully handle overlapping selectors.
|
||||
// See https://github.com/kubernetes/kubernetes/issues/2210
|
||||
SelectorUpdateAnnotation = "deployment.kubernetes.io/selector-updated-at"
|
||||
|
||||
// Reasons for deployment conditions
|
||||
//
|
||||
@ -295,8 +287,6 @@ var annotationsToSkip = map[string]bool{
|
||||
RevisionHistoryAnnotation: true,
|
||||
DesiredReplicasAnnotation: true,
|
||||
MaxReplicasAnnotation: true,
|
||||
OverlapAnnotation: true,
|
||||
SelectorUpdateAnnotation: true,
|
||||
}
|
||||
|
||||
// skipCopyAnnotation returns true if we should skip copying the annotation with the given annotation key
|
||||
@ -1020,59 +1010,3 @@ func DeploymentDeepCopy(deployment *extensions.Deployment) (*extensions.Deployme
|
||||
}
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
// SelectorUpdatedBefore returns true if the former deployment's selector
|
||||
// is updated before the latter, false otherwise.
|
||||
func SelectorUpdatedBefore(d1, d2 *extensions.Deployment) bool {
|
||||
t1, t2 := LastSelectorUpdate(d1), LastSelectorUpdate(d2)
|
||||
return t1.Before(t2)
|
||||
}
|
||||
|
||||
// LastSelectorUpdate returns the last time given deployment's selector is updated
|
||||
func LastSelectorUpdate(d *extensions.Deployment) metav1.Time {
|
||||
t := d.Annotations[SelectorUpdateAnnotation]
|
||||
if len(t) > 0 {
|
||||
parsedTime, err := time.Parse(time.RFC3339, t)
|
||||
// If failed to parse the time, use creation timestamp instead
|
||||
if err != nil {
|
||||
return d.CreationTimestamp
|
||||
}
|
||||
return metav1.Time{Time: parsedTime}
|
||||
}
|
||||
// If it's never updated, use creation timestamp instead
|
||||
return d.CreationTimestamp
|
||||
}
|
||||
|
||||
// BySelectorLastUpdateTime sorts a list of deployments by the last update time of their selector,
|
||||
// first using their creation timestamp and then their names as a tie breaker.
|
||||
type BySelectorLastUpdateTime []*extensions.Deployment
|
||||
|
||||
func (o BySelectorLastUpdateTime) Len() int { return len(o) }
|
||||
func (o BySelectorLastUpdateTime) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||
func (o BySelectorLastUpdateTime) Less(i, j int) bool {
|
||||
ti, tj := LastSelectorUpdate(o[i]), LastSelectorUpdate(o[j])
|
||||
if ti.Equal(tj) {
|
||||
if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) {
|
||||
return o[i].Name < o[j].Name
|
||||
}
|
||||
return o[i].CreationTimestamp.Before(o[j].CreationTimestamp)
|
||||
}
|
||||
return ti.Before(tj)
|
||||
}
|
||||
|
||||
// OverlapsWith returns true when two given deployments are different and overlap with each other
|
||||
func OverlapsWith(current, other *extensions.Deployment) (bool, error) {
|
||||
if current.UID == other.UID {
|
||||
return false, nil
|
||||
}
|
||||
currentSelector, err := metav1.LabelSelectorAsSelector(current.Spec.Selector)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("deployment %s/%s has invalid label selector: %v", current.Namespace, current.Name, err)
|
||||
}
|
||||
otherSelector, err := metav1.LabelSelectorAsSelector(other.Spec.Selector)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("deployment %s/%s has invalid label selector: %v", other.Namespace, other.Name, err)
|
||||
}
|
||||
return (!currentSelector.Empty() && currentSelector.Matches(labels.Set(other.Spec.Template.Labels))) ||
|
||||
(!otherSelector.Empty() && otherSelector.Matches(labels.Set(current.Spec.Template.Labels))), nil
|
||||
}
|
||||
|
@ -1189,111 +1189,3 @@ func TestDeploymentTimedOut(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectorUpdatedBefore(t *testing.T) {
|
||||
now := metav1.Now()
|
||||
later := metav1.Time{Time: now.Add(time.Minute)}
|
||||
selectorUpdated := metav1.Time{Time: later.Add(time.Minute)}
|
||||
selectorUpdatedLater := metav1.Time{Time: selectorUpdated.Add(time.Minute)}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
d1 extensions.Deployment
|
||||
creationTimestamp1 *metav1.Time
|
||||
selectorUpdated1 *metav1.Time
|
||||
|
||||
d2 extensions.Deployment
|
||||
creationTimestamp2 *metav1.Time
|
||||
selectorUpdated2 *metav1.Time
|
||||
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "d1 created before d2",
|
||||
|
||||
d1: generateDeployment("foo"),
|
||||
creationTimestamp1: &now,
|
||||
|
||||
d2: generateDeployment("bar"),
|
||||
creationTimestamp2: &later,
|
||||
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "d1 created after d2",
|
||||
|
||||
d1: generateDeployment("foo"),
|
||||
creationTimestamp1: &later,
|
||||
|
||||
d2: generateDeployment("bar"),
|
||||
creationTimestamp2: &now,
|
||||
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// Think of the following scenario:
|
||||
// d1 is created first, d2 is created after and its selector overlaps
|
||||
// with d1. d2 is marked as overlapping correctly. If d1's selector is
|
||||
// updated and continues to overlap with the selector of d2 then d1 is
|
||||
// now marked overlapping and d2 is cleaned up. Proved by the following
|
||||
// test case. Callers of SelectorUpdatedBefore should first check for
|
||||
// the existence of the overlapping annotation in any of the two deployments
|
||||
// prior to comparing their timestamps and as a matter of fact this is
|
||||
// now handled in `(dc *DeploymentController) handleOverlap`.
|
||||
name: "d1 created before d2 but updated its selector afterwards",
|
||||
|
||||
d1: generateDeployment("foo"),
|
||||
creationTimestamp1: &now,
|
||||
selectorUpdated1: &selectorUpdated,
|
||||
|
||||
d2: generateDeployment("bar"),
|
||||
creationTimestamp2: &later,
|
||||
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "d1 selector is older than d2",
|
||||
|
||||
d1: generateDeployment("foo"),
|
||||
selectorUpdated1: &selectorUpdated,
|
||||
|
||||
d2: generateDeployment("bar"),
|
||||
selectorUpdated2: &selectorUpdatedLater,
|
||||
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "d1 selector is younger than d2",
|
||||
|
||||
d1: generateDeployment("foo"),
|
||||
selectorUpdated1: &selectorUpdatedLater,
|
||||
|
||||
d2: generateDeployment("bar"),
|
||||
selectorUpdated2: &selectorUpdated,
|
||||
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Logf("running scenario %q", test.name)
|
||||
|
||||
if test.creationTimestamp1 != nil {
|
||||
test.d1.CreationTimestamp = *test.creationTimestamp1
|
||||
}
|
||||
if test.creationTimestamp2 != nil {
|
||||
test.d2.CreationTimestamp = *test.creationTimestamp2
|
||||
}
|
||||
if test.selectorUpdated1 != nil {
|
||||
test.d1.Annotations[SelectorUpdateAnnotation] = test.selectorUpdated1.Format(time.RFC3339)
|
||||
}
|
||||
if test.selectorUpdated2 != nil {
|
||||
test.d2.Annotations[SelectorUpdateAnnotation] = test.selectorUpdated2.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
if got := SelectorUpdatedBefore(&test.d1, &test.d2); got != test.expected {
|
||||
t.Errorf("expected d1 selector to be updated before d2: %t, got: %t", test.expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,11 +441,6 @@ func (reaper *DeploymentReaper) Stop(namespace, name string, timeout time.Durati
|
||||
return err
|
||||
}
|
||||
|
||||
// Do not cascade deletion for overlapping deployments.
|
||||
if len(deployment.Annotations[deploymentutil.OverlapAnnotation]) > 0 {
|
||||
return deployments.Delete(name, nil)
|
||||
}
|
||||
|
||||
// Stop all replica sets.
|
||||
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
||||
if err != nil {
|
||||
|
@ -2439,10 +2439,6 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting
|
||||
}
|
||||
w.Write(LEVEL_0, "NewReplicaSet:\t%s\n", printReplicaSetsByLabels(newRSs))
|
||||
}
|
||||
overlapWith := d.Annotations[deploymentutil.OverlapAnnotation]
|
||||
if len(overlapWith) > 0 {
|
||||
w.Write(LEVEL_0, "!!!WARNING!!! This deployment has overlapping label selector with deployment %q and won't behave as expected. Please fix it before continue.\n", overlapWith)
|
||||
}
|
||||
if describerSettings.ShowEvents {
|
||||
events, err := dd.Core().Events(namespace).Search(api.Scheme, d)
|
||||
if err == nil && events != nil {
|
||||
|
@ -20,7 +20,6 @@ go_library(
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/extensions/validation:go_default_library",
|
||||
"//pkg/controller/deployment/util:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
|
@ -19,9 +19,7 @@ package deployment
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -34,7 +32,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/validation"
|
||||
"k8s.io/kubernetes/pkg/controller/deployment/util"
|
||||
)
|
||||
|
||||
// deploymentStrategy implements behavior for Deployments.
|
||||
@ -93,15 +90,6 @@ func (deploymentStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, o
|
||||
!reflect.DeepEqual(newDeployment.Annotations, oldDeployment.Annotations) {
|
||||
newDeployment.Generation = oldDeployment.Generation + 1
|
||||
}
|
||||
|
||||
// Records timestamp on selector updates in annotation
|
||||
if !reflect.DeepEqual(newDeployment.Spec.Selector, oldDeployment.Spec.Selector) {
|
||||
if newDeployment.Annotations == nil {
|
||||
newDeployment.Annotations = make(map[string]string)
|
||||
}
|
||||
now := metav1.Now()
|
||||
newDeployment.Annotations[util.SelectorUpdateAnnotation] = now.Format(time.RFC3339)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
|
Loading…
Reference in New Issue
Block a user