@@ -143,10 +143,11 @@ func (r *AWSMachineReconciler) getObjectStoreService(scope scope.S3Scope) servic
143143 return s3 .NewService (scope )
144144}
145145
146- // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines,verbs=get;list;watch;update;patch;delete
147- // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines/status,verbs=get;update;patch
148146// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=*,verbs=get;list;watch
149- // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
147+ // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines,verbs=create;get;list;watch;update;patch;delete
148+ // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines/status,verbs=get;update;patch
149+ // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines,verbs=get;list;watch;delete
150+ // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines/status,verbs=get;list;watch
150151// +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch
151152// +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch
152153// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
@@ -459,6 +460,7 @@ func (r *AWSMachineReconciler) findInstance(machineScope *scope.MachineScope, ec
459460 return instance , nil
460461}
461462
463+ //nolint:gocyclo
462464func (r * AWSMachineReconciler ) reconcileNormal (_ context.Context , machineScope * scope.MachineScope , clusterScope cloud.ClusterScoper , ec2Scope scope.EC2Scope , elbScope scope.ELBScope , objectStoreScope scope.S3Scope ) (ctrl.Result , error ) {
463465 machineScope .Trace ("Reconciling AWSMachine" )
464466
@@ -482,7 +484,7 @@ func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope *
482484 }
483485
484486 // Make sure bootstrap data is available and populated.
485- if machineScope .Machine .Spec .Bootstrap .DataSecretName == nil {
487+ if ! machineScope . IsMachinePoolMachine () && machineScope .Machine .Spec .Bootstrap .DataSecretName == nil {
486488 machineScope .Info ("Bootstrap data secret reference is not yet available" )
487489 conditions .MarkFalse (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .WaitingForBootstrapDataReason , clusterv1 .ConditionSeverityInfo , "" )
488490 return ctrl.Result {}, nil
@@ -497,6 +499,12 @@ func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope *
497499 conditions .MarkUnknown (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .InstanceNotFoundReason , err .Error ())
498500 return ctrl.Result {}, err
499501 }
502+ if instance == nil && machineScope .IsMachinePoolMachine () {
503+ err = errors .New ("no instance found for machine pool" )
504+ machineScope .Error (err , "unable to find instance" )
505+ conditions .MarkUnknown (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .InstanceNotFoundReason , err .Error ())
506+ return ctrl.Result {}, err
507+ }
500508
501509 // If the AWSMachine doesn't have our finalizer, add it.
502510 if controllerutil .AddFinalizer (machineScope .AWSMachine , infrav1 .MachineFinalizer ) {
@@ -586,9 +594,18 @@ func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope *
586594 conditions .MarkTrue (machineScope .AWSMachine , infrav1 .InstanceReadyCondition )
587595 case infrav1 .InstanceStateShuttingDown , infrav1 .InstanceStateTerminated :
588596 machineScope .SetNotReady ()
589- machineScope .Info ("Unexpected EC2 instance termination" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
590- r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "InstanceUnexpectedTermination" , "Unexpected EC2 instance termination" )
591- conditions .MarkFalse (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .InstanceTerminatedReason , clusterv1 .ConditionSeverityError , "" )
597+
598+ if machineScope .IsMachinePoolMachine () {
599+ // In an auto-scaling group, instance termination is perfectly normal on scale-down
600+ // and therefore should not be reported as error.
601+ machineScope .Info ("EC2 instance of machine pool was terminated" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
602+ r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeNormal , infrav1 .InstanceTerminatedReason , "EC2 instance termination" )
603+ conditions .MarkFalse (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .InstanceTerminatedReason , clusterv1 .ConditionSeverityInfo , "" )
604+ } else {
605+ machineScope .Info ("Unexpected EC2 instance termination" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
606+ r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "InstanceUnexpectedTermination" , "Unexpected EC2 instance termination" )
607+ conditions .MarkFalse (machineScope .AWSMachine , infrav1 .InstanceReadyCondition , infrav1 .InstanceTerminatedReason , clusterv1 .ConditionSeverityError , "" )
608+ }
592609 default :
593610 machineScope .SetNotReady ()
594611 machineScope .Info ("EC2 instance state is undefined" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
@@ -599,14 +616,18 @@ func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope *
599616 }
600617
601618 // reconcile the deletion of the bootstrap data secret now that we have updated instance state
602- if deleteSecretErr := r .deleteBootstrapData (machineScope , clusterScope , objectStoreScope ); deleteSecretErr != nil {
603- r .Log .Error (deleteSecretErr , "unable to delete secrets" )
604- return ctrl.Result {}, deleteSecretErr
605- }
619+ if ! machineScope .IsMachinePoolMachine () {
620+ if deleteSecretErr := r .deleteBootstrapData (machineScope , clusterScope , objectStoreScope ); deleteSecretErr != nil {
621+ r .Log .Error (deleteSecretErr , "unable to delete secrets" )
622+ return ctrl.Result {}, deleteSecretErr
623+ }
606624
607- if instance .State == infrav1 .InstanceStateTerminated {
608- machineScope .SetFailureReason (capierrors .UpdateMachineError )
609- machineScope .SetFailureMessage (errors .Errorf ("EC2 instance state %q is unexpected" , instance .State ))
625+ // For machine pool machines, it is expected that the ASG terminates instances at any time,
626+ // so no error is logged for those.
627+ if instance .State == infrav1 .InstanceStateTerminated {
628+ machineScope .SetFailureReason (capierrors .UpdateMachineError )
629+ machineScope .SetFailureMessage (errors .Errorf ("EC2 instance state %q is unexpected" , instance .State ))
630+ }
610631 }
611632
612633 // tasks that can take place during all known instance states
@@ -876,9 +897,13 @@ func getIgnitionVersion(scope *scope.MachineScope) string {
876897}
877898
878899func (r * AWSMachineReconciler ) deleteBootstrapData (machineScope * scope.MachineScope , clusterScope cloud.ClusterScoper , objectStoreScope scope.S3Scope ) error {
879- _ , userDataFormat , err := machineScope .GetRawBootstrapDataWithFormat ()
880- if client .IgnoreNotFound (err ) != nil {
881- return errors .Wrap (err , "failed to get raw userdata" )
900+ var userDataFormat string
901+ var err error
902+ if machineScope .Machine .Spec .Bootstrap .DataSecretName != nil {
903+ _ , userDataFormat , err = machineScope .GetRawBootstrapDataWithFormat ()
904+ if client .IgnoreNotFound (err ) != nil {
905+ return errors .Wrap (err , "failed to get raw userdata" )
906+ }
882907 }
883908
884909 if machineScope .UseSecretsManager (userDataFormat ) {
0 commit comments