Skip to content

Commit 27025af

Browse files
ary1992shafeeqesacumino
authored
[GEP-31] Controller changes to Support Manual InPlaceUpdate strategy (#987)
* Manual Inplace Co-Authored-By: Shafeeque E S <shafeeque.e.s@sap.com> Co-Authored-By: Sonu Kumar Singh <28653770+acumino@users.noreply.github.com> * Minor Nit Co-Authored-By: Shafeeque E S <shafeeque.e.s@sap.com> Co-Authored-By: Sonu Kumar Singh <28653770+acumino@users.noreply.github.com> * Address Review * Address Review * Get MCD for machines without passing context * Add predicate to reconcile MCD when machine update is successful * Enhance few logs * Change is to machineSet --------- Co-authored-by: Shafeeque E S <shafeeque.e.s@sap.com> Co-authored-by: Sonu Kumar Singh <28653770+acumino@users.noreply.github.com> Co-authored-by: Sonu Kumar Singh <sksgkpvks@gmail.com>
1 parent 26533e0 commit 27025af

File tree

5 files changed

+241
-28
lines changed

5 files changed

+241
-28
lines changed

pkg/controller/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ func NewController(
119119

120120
// MachineDeployment Controller Informers
121121
_, _ = machineInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
122+
UpdateFunc: controller.updateMachineToMachineDeployment,
122123
DeleteFunc: controller.deleteMachineDeployment,
123124
})
124125

pkg/controller/deployment.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,32 @@ func (dc *controller) deleteMachineSetToDeployment(obj interface{}) {
222222
dc.enqueueMachineDeployment(d)
223223
}
224224

225+
// updateMachineToMachineDeployment will enqueue the machine deployment if the machine InPlaceUpdate node condition changes to UpdateSuccessful.
226+
func (dc *controller) updateMachineToMachineDeployment(old, cur any) {
227+
oldMachine, ok := old.(*v1alpha1.Machine)
228+
if !ok {
229+
return
230+
}
231+
232+
curMachine, ok := cur.(*v1alpha1.Machine)
233+
if !ok {
234+
return
235+
}
236+
237+
oldMachineCondition := getMachineCondition(oldMachine, v1alpha1.NodeInPlaceUpdate)
238+
currMachineCondition := getMachineCondition(curMachine, v1alpha1.NodeInPlaceUpdate)
239+
240+
oldMachineConditionReasonUpdateSuccessful := oldMachineCondition != nil && oldMachineCondition.Reason == v1alpha1.UpdateSuccessful
241+
currMachineConditionReasonUpdateSuccessful := currMachineCondition != nil && currMachineCondition.Reason == v1alpha1.UpdateSuccessful
242+
243+
if !oldMachineConditionReasonUpdateSuccessful && currMachineConditionReasonUpdateSuccessful {
244+
d := dc.getMachineDeploymentForMachine(curMachine)
245+
if d != nil {
246+
dc.enqueueMachineDeployment(d)
247+
}
248+
}
249+
}
250+
225251
// deleteMachine will enqueue a Recreate Deployment once all of its Machines have stopped running.
226252
func (dc *controller) deleteMachineToMachineDeployment(ctx context.Context, obj interface{}) {
227253
machine, ok := obj.(*v1alpha1.Machine)
@@ -243,7 +269,7 @@ func (dc *controller) deleteMachineToMachineDeployment(ctx context.Context, obj
243269
}
244270
}
245271
klog.V(4).Infof("Machine %s deleted.", machine.Name)
246-
if d := dc.getMachineDeploymentForMachine(ctx, machine); d != nil && d.Spec.Strategy.Type == v1alpha1.RecreateMachineDeploymentStrategyType {
272+
if d := dc.getMachineDeploymentForMachine(machine); d != nil && d.Spec.Strategy.Type == v1alpha1.RecreateMachineDeploymentStrategyType {
247273
// Sync if this Deployment now has no more Machines.
248274
machineSets, err := ListMachineSets(d, IsListFromClient(ctx, dc.controlMachineClient))
249275
if err != nil {
@@ -295,7 +321,7 @@ func (dc *controller) enqueueMachineDeploymentAfter(deployment *v1alpha1.Machine
295321
}
296322

297323
// getDeploymentForMachine returns the deployment managing the given Machine.
298-
func (dc *controller) getMachineDeploymentForMachine(ctx context.Context, machine *v1alpha1.Machine) *v1alpha1.MachineDeployment {
324+
func (dc *controller) getMachineDeploymentForMachine(machine *v1alpha1.Machine) *v1alpha1.MachineDeployment {
299325
// Find the owning machine set
300326
var is *v1alpha1.MachineSet
301327
var err error
@@ -308,7 +334,8 @@ func (dc *controller) getMachineDeploymentForMachine(ctx context.Context, machin
308334
// Not a Machine owned by a machine set.
309335
return nil
310336
}
311-
is, err = dc.controlMachineClient.MachineSets(machine.Namespace).Get(ctx, controllerRef.Name, metav1.GetOptions{})
337+
338+
is, err = dc.machineSetLister.MachineSets(machine.Namespace).Get(controllerRef.Name)
312339
if err != nil || is.UID != controllerRef.UID {
313340
klog.V(4).Infof("Cannot get machineset %q for machine %q: %v", controllerRef.Name, machine.Name, err)
314341
return nil
@@ -546,12 +573,9 @@ func (dc *controller) reconcileClusterMachineDeployment(key string) error {
546573
case v1alpha1.RollingUpdateMachineDeploymentStrategyType:
547574
return dc.rolloutRolling(ctx, d, machineSets, machineMap)
548575
case v1alpha1.InPlaceUpdateMachineDeploymentStrategyType:
549-
if d.Spec.Strategy.InPlaceUpdate.OrchestrationType == v1alpha1.OrchestrationTypeAuto {
550-
return dc.rolloutAutoInPlace(ctx, d, machineSets, machineMap)
551-
}
552-
553-
// TODO(ary1992): Implement Manual InPlace strategy
576+
return dc.rolloutInPlace(ctx, d, machineSets, machineMap)
554577
}
578+
555579
return fmt.Errorf("unexpected deployment strategy type: %s", d.Spec.Strategy.Type)
556580
}
557581

pkg/controller/deployment_inplace.go

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ import (
2525
"k8s.io/utils/integer"
2626
)
2727

28-
// rolloutAutoInPlace implements the logic for rolling a machine set without replacing it.
29-
func (dc *controller) rolloutAutoInPlace(ctx context.Context, d *v1alpha1.MachineDeployment, isList []*v1alpha1.MachineSet, machineMap map[types.UID]*v1alpha1.MachineList) error {
28+
// rolloutInPlace implements the logic for rolling a machine set without replacing its machines.
29+
func (dc *controller) rolloutInPlace(ctx context.Context, d *v1alpha1.MachineDeployment, machineSetList []*v1alpha1.MachineSet, machineMap map[types.UID]*v1alpha1.MachineList) error {
3030
clusterAutoscalerScaleDownAnnotations := make(map[string]string)
3131
clusterAutoscalerScaleDownAnnotations[autoscaler.ClusterAutoscalerScaleDownDisabledAnnotationKey] = autoscaler.ClusterAutoscalerScaleDownDisabledAnnotationValue
3232

3333
// We do this to avoid accidentally deleting the user provided annotations.
3434
clusterAutoscalerScaleDownAnnotations[autoscaler.ClusterAutoscalerScaleDownDisabledAnnotationByMCMKey] = autoscaler.ClusterAutoscalerScaleDownDisabledAnnotationByMCMValue
3535

36-
newMachineSet, oldMachineSets, err := dc.getAllMachineSetsAndSyncRevision(ctx, d, isList, machineMap, true)
36+
newMachineSet, oldMachineSets, err := dc.getAllMachineSetsAndSyncRevision(ctx, d, machineSetList, machineMap, true)
3737
if err != nil {
3838
return err
3939
}
@@ -95,7 +95,7 @@ func (dc *controller) rolloutAutoInPlace(ctx context.Context, d *v1alpha1.Machin
9595
return dc.syncRolloutStatus(ctx, allMachineSets, newMachineSet, d)
9696
}
9797

98-
// prepare old ISs for update
98+
// prepare old machineSets for update
9999
workDone, err := dc.reconcileOldMachineSetsInPlace(ctx, allMachineSets, FilterActiveMachineSets(oldMachineSets), newMachineSet, d)
100100
if err != nil {
101101
return err
@@ -131,13 +131,14 @@ func (dc *controller) syncMachineSets(ctx context.Context, oldMachineSets []*v1a
131131
}
132132

133133
machinesWithUpdateSuccessfulLabel := filterMachinesWithUpdateSuccessfulLabel(newMachines)
134-
klog.V(3).Infof("Found %d machine(s) with label %q=%q in new machine set", len(machinesWithUpdateSuccessfulLabel), v1alpha1.LabelKeyNodeUpdateResult, v1alpha1.LabelValueNodeUpdateSuccessful)
134+
klog.V(3).Infof("Found %d machine(s) with label %q=%q in new machine set %q", len(machinesWithUpdateSuccessfulLabel), v1alpha1.LabelKeyNodeUpdateResult, v1alpha1.LabelValueNodeUpdateSuccessful, newMachineSet.Name)
135135

136136
if len(newMachines) > int(newMachineSet.Spec.Replicas) && len(machinesWithUpdateSuccessfulLabel) > 0 {
137137
// scale up the new machine set to the number of machines with the update successful label.
138138
// This is to ensure that the machines with moved to the new machine set when ownership is transferred is accounted.
139139
scaleUpBy := min(len(machinesWithUpdateSuccessfulLabel), len(newMachines)-int(newMachineSet.Spec.Replicas))
140-
_, _, err := dc.scaleMachineSetAndRecordEvent(ctx, newMachineSet, newMachineSet.Spec.Replicas+int32(scaleUpBy), deployment) // #nosec G115 (CWE-190) -- value already validated
140+
klog.V(3).Infof("scale up the new machine set %s by %d to %d replicas", newMachineSet.Name, scaleUpBy, newMachineSet.Spec.Replicas+int32(scaleUpBy)) // #nosec G115 (CWE-190) -- value already validated
141+
_, _, err := dc.scaleMachineSetAndRecordEvent(ctx, newMachineSet, newMachineSet.Spec.Replicas+int32(scaleUpBy), deployment) // #nosec G115 (CWE-190) -- value already validated
141142
if err != nil {
142143
return err
143144
}
@@ -247,7 +248,7 @@ func (dc *controller) reconcileNewMachineSetInPlace(ctx context.Context, oldMach
247248
return false, nil
248249
}
249250

250-
klog.V(3).Infof("scale up the new machine set %s by %d", newMachineSet.Name, addedNewReplicasCount)
251+
klog.V(3).Infof("scale up the new machine set %s by %d to %d replicas", newMachineSet.Name, addedNewReplicasCount, newMachineSet.Spec.Replicas+addedNewReplicasCount)
251252
scaled, _, err := dc.scaleMachineSetAndRecordEvent(ctx, newMachineSet, newMachineSet.Spec.Replicas+addedNewReplicasCount, deployment)
252253
return scaled, err
253254
}
@@ -273,33 +274,45 @@ func (dc *controller) reconcileOldMachineSetsInPlace(ctx context.Context, allMac
273274
return true, nil
274275
}
275276

277+
// Manual inplace update
278+
if deployment.Spec.Strategy.InPlaceUpdate.OrchestrationType == v1alpha1.OrchestrationTypeManual {
279+
return false, nil
280+
}
281+
276282
allMachinesCount := GetReplicaCountForMachineSets(allMachineSets)
277283
klog.V(3).Infof("New machine set %s has %d available machines.", newMachineSet.Name, newMachineSet.Status.AvailableReplicas)
278284
maxUnavailable := MaxUnavailable(*deployment)
279285

280286
minAvailable := deployment.Spec.Replicas - maxUnavailable
281-
newISUnavailableMachineCount := newMachineSet.Spec.Replicas - newMachineSet.Status.AvailableReplicas
282-
oldISsMachinesUndergoingUpdate, err := dc.getMachinesUndergoingUpdate(oldMachineSets)
287+
newMachineSetUnavailableMachineCount := newMachineSet.Spec.Replicas - newMachineSet.Status.AvailableReplicas
288+
oldMachineSetsMachinesUndergoingUpdate, err := dc.getMachinesUndergoingUpdate(oldMachineSets)
283289
if err != nil {
284290
return false, err
285291
}
286292

287-
klog.V(3).Infof("allMachinesCount:%d, minAvailable:%d, newISUnavailableMachineCount:%d, oldISsMachineInUpdateProcess:%d", allMachinesCount, minAvailable, newISUnavailableMachineCount, oldISsMachinesUndergoingUpdate)
293+
// Machines from old machine sets which are undergoing update will eventually move to new machine set.
294+
// So once the current new machine set replcas + old machine set replicas undergoing update reaches the desired replicas,
295+
// we can stop selecting machines from old machine sets for update.
296+
if oldMachineSetsMachinesUndergoingUpdate+newMachineSet.Spec.Replicas >= deployment.Spec.Replicas {
297+
return false, nil
298+
}
299+
300+
klog.V(3).Infof("allMachinesCount:%d, minAvailable:%d, newMachineSetUnavailableMachineCount:%d, oldISsMachineInUpdateProcess:%d", allMachinesCount, minAvailable, newMachineSetUnavailableMachineCount, oldMachineSetsMachinesUndergoingUpdate)
288301

289302
// maxUpdatePossible is calculated as the total number of machines (allMachinesCount)
290303
// minus the minimum number of machines that must remain available (minAvailable),
291-
// minus the number of machines in the new instance set that are currently unavailable (newISUnavailableMachineCount),
292-
// minus the number of machines in the old instance sets that are undergoing updates (oldISsMachinesUndergoingUpdate).
304+
// minus the number of machines in the new instance set that are currently unavailable (newMachineSetUnavailableMachineCount),
305+
// minus the number of machines in the old instance sets that are undergoing updates (oldMachineSetsMachinesUndergoingUpdate).
293306
// here unavailable machines of old machine sets are not considered as first we want to check if we can select machines for update from old machine sets
294307
// after fulfilling all the constraints.
295-
maxUpdatePossible := allMachinesCount - minAvailable - newISUnavailableMachineCount - oldISsMachinesUndergoingUpdate
308+
maxUpdatePossible := allMachinesCount - minAvailable - newMachineSetUnavailableMachineCount - oldMachineSetsMachinesUndergoingUpdate
296309
if maxUpdatePossible <= 0 {
297310
klog.V(3).Infof("no machines can be selected for update from old machine sets")
298311
return false, nil
299312
}
300313

301314
// prepare machines from old machine sets for update, need to check maxUnavailable to ensure we can select machines for update.
302-
numOfMachinesSelectedForUpdate, err := dc.selectNumOfMachineForUpdate(ctx, allMachineSets, oldMachineSets, newMachineSet, deployment, oldISsMachinesUndergoingUpdate)
315+
numOfMachinesSelectedForUpdate, err := dc.selectNumOfMachineForUpdate(ctx, allMachineSets, oldMachineSets, newMachineSet, deployment, oldMachineSetsMachinesUndergoingUpdate)
303316
if err != nil {
304317
return false, err
305318
}
@@ -354,7 +367,7 @@ func (dc *controller) transferMachinesFromOldToNewMachineSet(ctx context.Context
354367
// update the owner reference of the machine to the new machine set and update the labels
355368
addControllerPatch := fmt.Sprintf(
356369
`{"metadata":{"ownerReferences":[{"apiVersion":"machine.sapcloud.io/v1alpha1","kind":"%s","name":"%s","uid":"%s","controller":true,"blockOwnerDeletion":true}],"labels":%s,"uid":"%s"}}`,
357-
v1alpha1.SchemeGroupVersion.WithKind("MachineSet"),
370+
v1alpha1.SchemeGroupVersion.WithKind("MachineSet").Kind,
358371
newMachineSet.GetName(), newMachineSet.GetUID(), string(labelsJSONBytes), oldMachine.UID)
359372

360373
err = dc.machineControl.PatchMachine(ctx, oldMachine.Namespace, oldMachine.Name, []byte(addControllerPatch))
@@ -379,7 +392,7 @@ func (dc *controller) transferMachinesFromOldToNewMachineSet(ctx context.Context
379392
continue
380393
}
381394

382-
klog.V(3).Infof("%d machine(s) transferred to new machine set. scaling down machine set %s", transferredMachineCount, oldMachineSet.Name)
395+
klog.V(3).Infof("%d machine(s) transferred to new machine set. scaling down machine set %s to %d replicas", transferredMachineCount, oldMachineSet.Name, oldMachineSet.Spec.Replicas-transferredMachineCount)
383396
_, _, err = dc.scaleMachineSetAndRecordEvent(ctx, oldMachineSet, oldMachineSet.Spec.Replicas-transferredMachineCount, deployment)
384397
if err != nil {
385398
klog.Errorf("scale down failed %s", err)
@@ -390,14 +403,14 @@ func (dc *controller) transferMachinesFromOldToNewMachineSet(ctx context.Context
390403
return addedNewReplicasCount, nil
391404
}
392405

393-
func (dc *controller) selectNumOfMachineForUpdate(ctx context.Context, allMachineSets []*v1alpha1.MachineSet, oldMachineSets []*v1alpha1.MachineSet, newMachineSet *v1alpha1.MachineSet, deployment *v1alpha1.MachineDeployment, oldISsMachinesUndergoingUpdate int32) (int32, error) {
406+
func (dc *controller) selectNumOfMachineForUpdate(ctx context.Context, allMachineSets []*v1alpha1.MachineSet, oldMachineSets []*v1alpha1.MachineSet, newMachineSet *v1alpha1.MachineSet, deployment *v1alpha1.MachineDeployment, oldMachineSetsMachinesUndergoingUpdate int32) (int32, error) {
394407
maxUnavailable := MaxUnavailable(*deployment)
395408

396409
// Check if we can pick machines from old ISes for updating to new IS.
397410
minAvailable := deployment.Spec.Replicas - maxUnavailable
398411

399412
// Find the number of available machines.
400-
availableMachineCount := GetAvailableReplicaCountForMachineSets(allMachineSets) - oldISsMachinesUndergoingUpdate
413+
availableMachineCount := GetAvailableReplicaCountForMachineSets(allMachineSets) - oldMachineSetsMachinesUndergoingUpdate
401414
if availableMachineCount <= minAvailable {
402415
// Cannot pick for updating.
403416
return 0, nil

0 commit comments

Comments
 (0)