Skip to content

Commit 23e54dc

Browse files
authored
Merge pull request kubernetes#77610 from tedyu/rev-limit
Impose length limit when concatenating revision history
2 parents c2847e8 + 9418aff commit 23e54dc

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

pkg/controller/deployment/sync.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ func (dc *DeploymentController) getAllReplicaSetsAndSyncRevision(d *apps.Deploym
124124
return newRS, allOldRSs, nil
125125
}
126126

127+
const (
128+
// limit revision history length to 100 element (~2000 chars)
129+
maxRevHistoryLengthInChars = 2000
130+
)
131+
127132
// Returns a replica set that matches the intent of the given deployment. Returns nil if the new replica set doesn't exist yet.
128133
// 1. Get existing new RS (the RS that the given deployment targets, whose pod template is the same as deployment's).
129134
// 2. If there's existing new RS, update its revision number if it's smaller than (maxOldRevision + 1), where maxOldRevision is the max revision number among all old RSes.
@@ -145,7 +150,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *apps.Deployment, rsList, old
145150
rsCopy := existingNewRS.DeepCopy()
146151

147152
// Set existing new replica set's annotation
148-
annotationsUpdated := deploymentutil.SetNewReplicaSetAnnotations(d, rsCopy, newRevision, true)
153+
annotationsUpdated := deploymentutil.SetNewReplicaSetAnnotations(d, rsCopy, newRevision, true, maxRevHistoryLengthInChars)
149154
minReadySecondsNeedsUpdate := rsCopy.Spec.MinReadySeconds != d.Spec.MinReadySeconds
150155
if annotationsUpdated || minReadySecondsNeedsUpdate {
151156
rsCopy.Spec.MinReadySeconds = d.Spec.MinReadySeconds
@@ -209,7 +214,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *apps.Deployment, rsList, old
209214

210215
*(newRS.Spec.Replicas) = newReplicasCount
211216
// Set new replica set's annotation
212-
deploymentutil.SetNewReplicaSetAnnotations(d, &newRS, newRevision, false)
217+
deploymentutil.SetNewReplicaSetAnnotations(d, &newRS, newRevision, false, maxRevHistoryLengthInChars)
213218
// Create the new ReplicaSet. If it already exists, then we need to check for possible
214219
// hash collisions. If there is any other error, we need to report it in the status of
215220
// the Deployment.

pkg/controller/deployment/util/deployment_util.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func Revision(obj runtime.Object) (int64, error) {
227227

228228
// SetNewReplicaSetAnnotations sets new replica set's annotations appropriately by updating its revision and
229229
// copying required deployment annotations to it; it returns true if replica set's annotation is changed.
230-
func SetNewReplicaSetAnnotations(deployment *apps.Deployment, newRS *apps.ReplicaSet, newRevision string, exists bool) bool {
230+
func SetNewReplicaSetAnnotations(deployment *apps.Deployment, newRS *apps.ReplicaSet, newRevision string, exists bool, revHistoryLimitInChars int) bool {
231231
// First, copy deployment's annotations (except for apply and revision annotations)
232232
annotationChanged := copyDeploymentAnnotationsToReplicaSet(deployment, newRS)
233233
// Then, update replica set's revision annotation
@@ -261,14 +261,25 @@ func SetNewReplicaSetAnnotations(deployment *apps.Deployment, newRS *apps.Replic
261261
// If a revision annotation already existed and this replica set was updated with a new revision
262262
// then that means we are rolling back to this replica set. We need to preserve the old revisions
263263
// for historical information.
264-
if ok && annotationChanged {
264+
if ok && oldRevisionInt < newRevisionInt {
265265
revisionHistoryAnnotation := newRS.Annotations[RevisionHistoryAnnotation]
266266
oldRevisions := strings.Split(revisionHistoryAnnotation, ",")
267267
if len(oldRevisions[0]) == 0 {
268268
newRS.Annotations[RevisionHistoryAnnotation] = oldRevision
269269
} else {
270-
oldRevisions = append(oldRevisions, oldRevision)
271-
newRS.Annotations[RevisionHistoryAnnotation] = strings.Join(oldRevisions, ",")
270+
totalLen := len(revisionHistoryAnnotation) + len(oldRevision) + 1
271+
// index for the starting position in oldRevisions
272+
start := 0
273+
for totalLen > revHistoryLimitInChars && start < len(oldRevisions) {
274+
totalLen = totalLen - len(oldRevisions[start]) - 1
275+
start++
276+
}
277+
if totalLen <= revHistoryLimitInChars {
278+
oldRevisions = append(oldRevisions[start:], oldRevision)
279+
newRS.Annotations[RevisionHistoryAnnotation] = strings.Join(oldRevisions, ",")
280+
} else {
281+
klog.Warningf("Not appending revision due to length limit of %v reached", revHistoryLimitInChars)
282+
}
272283
}
273284
}
274285
// If the new replica set is about to be created, we need to add replica annotations to it.

pkg/controller/deployment/util/deployment_util_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,13 +1274,19 @@ func TestAnnotationUtils(t *testing.T) {
12741274

12751275
//Test Case 1: Check if anotations are copied properly from deployment to RS
12761276
t.Run("SetNewReplicaSetAnnotations", func(t *testing.T) {
1277-
//Try to set the increment revision from 1 through 20
1278-
for i := 0; i < 20; i++ {
1277+
//Try to set the increment revision from 11 through 20
1278+
for i := 10; i < 20; i++ {
12791279

12801280
nextRevision := fmt.Sprintf("%d", i+1)
1281-
SetNewReplicaSetAnnotations(&tDeployment, &tRS, nextRevision, true)
1281+
SetNewReplicaSetAnnotations(&tDeployment, &tRS, nextRevision, true, 5)
12821282
//Now the ReplicaSets Revision Annotation should be i+1
12831283

1284+
if i >= 12 {
1285+
expectedHistoryAnnotation := fmt.Sprintf("%d,%d", i-1, i)
1286+
if tRS.Annotations[RevisionHistoryAnnotation] != expectedHistoryAnnotation {
1287+
t.Errorf("Revision History Expected=%s Obtained=%s", expectedHistoryAnnotation, tRS.Annotations[RevisionHistoryAnnotation])
1288+
}
1289+
}
12841290
if tRS.Annotations[RevisionAnnotation] != nextRevision {
12851291
t.Errorf("Revision Expected=%s Obtained=%s", nextRevision, tRS.Annotations[RevisionAnnotation])
12861292
}

0 commit comments

Comments
 (0)