Skip to content

Commit 44e0cd5

Browse files
authored
Merge pull request #4929 from nojnhuh/aso-autoscale
handle non-native autoscalers for AzureASOManagedMachinePool
2 parents 90b76d3 + 92e6ed0 commit 44e0cd5

File tree

4 files changed

+48
-19
lines changed

4 files changed

+48
-19
lines changed

exp/controllers/azureasomanagedmachinepool_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func (r *AzureASOManagedMachinePoolReconciler) reconcileNormal(ctx context.Conte
209209
return ctrl.Result{Requeue: true}, nil
210210
}
211211

212-
resources, err := mutators.ApplyMutators(ctx, asoManagedMachinePool.Spec.Resources, mutators.SetAgentPoolDefaults(asoManagedMachinePool, machinePool))
212+
resources, err := mutators.ApplyMutators(ctx, asoManagedMachinePool.Spec.Resources, mutators.SetAgentPoolDefaults(r.Client, machinePool))
213213
if err != nil {
214214
return ctrl.Result{}, err
215215
}
@@ -276,7 +276,7 @@ func (r *AzureASOManagedMachinePoolReconciler) reconcileNormal(ctx context.Conte
276276
slices.Sort(providerIDs)
277277
asoManagedMachinePool.Spec.ProviderIDList = providerIDs
278278
asoManagedMachinePool.Status.Replicas = int32(ptr.Deref(agentPool.Status.Count, 0))
279-
if machinePool.Annotations[clusterv1.ReplicasManagedByAnnotation] == infrav1exp.ReplicasManagedByAKS {
279+
if _, autoscaling := machinePool.Annotations[clusterv1.ReplicasManagedByAnnotation]; autoscaling {
280280
machinePool.Spec.Replicas = &asoManagedMachinePool.Status.Replicas
281281
}
282282

exp/mutators/azureasomanagedcontrolplane.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
asocontainerservicev1 "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231001"
2626
asocontainerservicev1hub "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231001/storage"
2727
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
28-
"k8s.io/utils/ptr"
2928
"sigs.k8s.io/cluster-api-provider-azure/azure"
3029
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1alpha1"
3130
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
@@ -270,7 +269,7 @@ func agentPoolsFromManagedMachinePools(ctx context.Context, ctrlClient client.Cl
270269
}
271270

272271
resources, err := ApplyMutators(ctx, asoManagedMachinePool.Spec.Resources,
273-
SetAgentPoolDefaults(ptr.To(asoManagedMachinePool), machinePool),
272+
SetAgentPoolDefaults(ctrlClient, machinePool),
274273
)
275274
if err != nil {
276275
return nil, err

exp/mutators/azureasomanagedmachinepool.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ import (
2727
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
2828
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2929
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
30+
"sigs.k8s.io/controller-runtime/pkg/client"
3031
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3132
)
3233

3334
// ErrNoManagedClustersAgentPoolDefined describes an AzureASOManagedMachinePool without a ManagedClustersAgentPool.
3435
var ErrNoManagedClustersAgentPoolDefined = fmt.Errorf("no %s ManagedClustersAgentPools defined in AzureASOManagedMachinePool spec.resources", asocontainerservicev1.GroupVersion.Group)
3536

3637
// SetAgentPoolDefaults propagates config from a MachinePool to an AzureASOManagedMachinePool's defined ManagedClustersAgentPool.
37-
func SetAgentPoolDefaults(asoManagedMachinePool *infrav1exp.AzureASOManagedMachinePool, machinePool *expv1.MachinePool) ResourcesMutator {
38+
func SetAgentPoolDefaults(ctrlClient client.Client, machinePool *expv1.MachinePool) ResourcesMutator {
3839
return func(ctx context.Context, us []*unstructured.Unstructured) error {
3940
ctx, _, done := tele.StartSpanWithLogger(ctx, "mutators.SetAgentPoolDefaults")
4041
defer done()
@@ -61,7 +62,7 @@ func SetAgentPoolDefaults(asoManagedMachinePool *infrav1exp.AzureASOManagedMachi
6162
return err
6263
}
6364

64-
if err := setAgentPoolCount(ctx, machinePool, agentPoolPath, agentPool); err != nil {
65+
if err := setAgentPoolCount(ctx, ctrlClient, machinePool, agentPoolPath, agentPool); err != nil {
6566
return err
6667
}
6768

@@ -126,15 +127,28 @@ func reconcileAutoscaling(agentPool *unstructured.Unstructured, machinePool *exp
126127
return nil
127128
}
128129

129-
func setAgentPoolCount(ctx context.Context, machinePool *expv1.MachinePool, agentPoolPath string, agentPool *unstructured.Unstructured) error {
130-
_, log, done := tele.StartSpanWithLogger(ctx, "mutators.setAgentPoolOrchestratorVersion")
130+
func setAgentPoolCount(ctx context.Context, ctrlClient client.Client, machinePool *expv1.MachinePool, agentPoolPath string, agentPool *unstructured.Unstructured) error {
131+
_, log, done := tele.StartSpanWithLogger(ctx, "mutators.setAgentPoolCount")
131132
defer done()
132133

133-
autoscaling := machinePool.Annotations[clusterv1.ReplicasManagedByAnnotation] == infrav1exp.ReplicasManagedByAKS
134-
if machinePool.Spec.Replicas == nil || autoscaling {
134+
if machinePool.Spec.Replicas == nil {
135135
return nil
136136
}
137137

138+
// When managed by any autoscaler, CAPZ should not provide any spec.count to the ManagedClustersAgentPool
139+
// to prevent ASO from overwriting the autoscaler's opinion of the replica count.
140+
// The MachinePool's spec.replicas is used to seed an initial value as required by AKS.
141+
if _, autoscaling := machinePool.Annotations[clusterv1.ReplicasManagedByAnnotation]; autoscaling {
142+
existingAgentPool := &asocontainerservicev1.ManagedClustersAgentPool{}
143+
err := ctrlClient.Get(ctx, client.ObjectKey{Namespace: machinePool.GetNamespace(), Name: agentPool.GetName()}, existingAgentPool)
144+
if client.IgnoreNotFound(err) != nil {
145+
return err
146+
}
147+
if err == nil && existingAgentPool.Status.Count != nil {
148+
return nil
149+
}
150+
}
151+
138152
countPath := []string{"spec", "count"}
139153
capiCount := int64(*machinePool.Spec.Replicas)
140154
userCount, countFound, err := unstructured.NestedInt64(agentPool.UnstructuredContent(), countPath...)

exp/mutators/azureasomanagedmachinepool_test.go

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import (
3131
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1alpha1"
3232
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3333
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
35+
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
3436
)
3537

3638
func TestSetAgentPoolDefaults(t *testing.T) {
@@ -93,7 +95,7 @@ func TestSetAgentPoolDefaults(t *testing.T) {
9395
t.Run(test.name, func(t *testing.T) {
9496
g := NewGomegaWithT(t)
9597

96-
mutator := SetAgentPoolDefaults(test.asoManagedMachinePool, test.machinePool)
98+
mutator := SetAgentPoolDefaults(nil, test.machinePool)
9799
actual, err := ApplyMutators(ctx, test.asoManagedMachinePool.Spec.Resources, mutator)
98100
if test.expectedErr != nil {
99101
g.Expect(err).To(MatchError(test.expectedErr))
@@ -351,11 +353,12 @@ func TestSetAgentPoolCount(t *testing.T) {
351353
ctx := context.Background()
352354

353355
tests := []struct {
354-
name string
355-
machinePool *expv1.MachinePool
356-
agentPool *asocontainerservicev1.ManagedClustersAgentPool
357-
expected *asocontainerservicev1.ManagedClustersAgentPool
358-
expectedErr error
356+
name string
357+
machinePool *expv1.MachinePool
358+
agentPool *asocontainerservicev1.ManagedClustersAgentPool
359+
existingAgentPool *asocontainerservicev1.ManagedClustersAgentPool
360+
expected *asocontainerservicev1.ManagedClustersAgentPool
361+
expectedErr error
359362
}{
360363
{
361364
name: "no CAPI opinion",
@@ -389,12 +392,17 @@ func TestSetAgentPoolCount(t *testing.T) {
389392
},
390393
agentPool: &asocontainerservicev1.ManagedClustersAgentPool{
391394
Spec: asocontainerservicev1.ManagedClusters_AgentPool_Spec{
395+
Count: nil,
396+
},
397+
},
398+
existingAgentPool: &asocontainerservicev1.ManagedClustersAgentPool{
399+
Status: asocontainerservicev1.ManagedClusters_AgentPool_STATUS{
392400
Count: ptr.To(2),
393401
},
394402
},
395403
expected: &asocontainerservicev1.ManagedClustersAgentPool{
396404
Spec: asocontainerservicev1.ManagedClusters_AgentPool_Spec{
397-
Count: ptr.To(2),
405+
Count: nil,
398406
},
399407
},
400408
},
@@ -407,7 +415,7 @@ func TestSetAgentPoolCount(t *testing.T) {
407415
},
408416
agentPool: &asocontainerservicev1.ManagedClustersAgentPool{
409417
Spec: asocontainerservicev1.ManagedClusters_AgentPool_Spec{
410-
OrchestratorVersion: nil,
418+
Count: nil,
411419
},
412420
},
413421
expected: &asocontainerservicev1.ManagedClustersAgentPool{
@@ -467,10 +475,18 @@ func TestSetAgentPoolCount(t *testing.T) {
467475
t.Run(test.name, func(t *testing.T) {
468476
g := NewGomegaWithT(t)
469477

478+
var c client.Client
479+
if test.existingAgentPool != nil {
480+
c = fakeclient.NewClientBuilder().
481+
WithScheme(s).
482+
WithObjects(test.existingAgentPool).
483+
Build()
484+
}
485+
470486
before := test.agentPool.DeepCopy()
471487
uap := apUnstructured(g, test.agentPool)
472488

473-
err := setAgentPoolCount(ctx, test.machinePool, "", uap)
489+
err := setAgentPoolCount(ctx, c, test.machinePool, "", uap)
474490
g.Expect(s.Convert(uap, test.agentPool, nil)).To(Succeed())
475491
if test.expectedErr != nil {
476492
g.Expect(err).To(MatchError(test.expectedErr))

0 commit comments

Comments
 (0)