Skip to content

Commit a6b53c8

Browse files
committed
feat: patch the cluster-autoscaler annotations
1 parent 699f50f commit a6b53c8

File tree

17 files changed

+177
-63
lines changed

17 files changed

+177
-63
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ To create an example cluster:
7373

7474
```shell
7575
clusterctl generate cluster docker-quick-start-helm-addon-cilium \
76-
--from examples/capi-quick-start/docker-cluster-cilium-helm-addon.yaml \
76+
--from examples/capi-quick-start/docker-cluster-calico-crs.yaml \
7777
--kubernetes-version v1.29.1 \
7878
--worker-machine-count 1 | \
7979
kubectl apply --server-side -f -

api/v1alpha1/node_types.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import (
1010
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
1111
)
1212

13-
//+kubebuilder:object:root=true
13+
// +kubebuilder:object:root=true
1414

1515
// NodeConfig is the Schema for the workerconfigs API.
1616
type NodeConfig struct {
1717
metav1.TypeMeta `json:",inline"`
1818
metav1.ObjectMeta `json:"metadata,omitempty"`
1919

20-
//+optional
20+
// +optional
2121
Spec NodeConfigSpec `json:"spec,omitempty"`
2222
}
2323

@@ -29,6 +29,8 @@ type NodeConfigSpec struct {
2929
AWS *AWSNodeSpec `json:"aws,omitempty"`
3030
// +optional
3131
Docker *DockerNodeSpec `json:"docker,omitempty"`
32+
33+
GenericNodeConfig `json:",inline"`
3234
}
3335

3436
func (s NodeConfigSpec) VariableSchema() clusterv1.VariableSchema {
@@ -54,14 +56,42 @@ func (s NodeConfigSpec) VariableSchema() clusterv1.VariableSchema {
5456
return nodeConfigProps
5557
}
5658

57-
type GenericNodeConfig struct{}
59+
type GenericNodeConfig struct {
60+
// +optional
61+
ClusterAutoscaler *ClusterAutoscalerNodeConfig `json:"clusterAutoscaler,omitempty"`
62+
}
63+
64+
type ClusterAutoscalerNodeConfig struct {
65+
MinimumSize int32 `json:"minimumSize"`
66+
MaximumSize int32 `json:"maximumSize"`
67+
}
68+
69+
func (ClusterAutoscalerNodeConfig) VariableSchema() clusterv1.VariableSchema {
70+
return clusterv1.VariableSchema{
71+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
72+
Type: "object",
73+
Properties: map[string]clusterv1.JSONSchemaProps{
74+
"minimumSize": {
75+
Description: "Minimum number of Machines the cluster-autoscaler can scale down to.",
76+
Type: "integer",
77+
},
78+
"maximumSize": {
79+
Description: "Maximum number of Machines the cluster-autoscaler can scale up to.",
80+
Type: "integer",
81+
},
82+
},
83+
},
84+
}
85+
}
5886

5987
func (GenericNodeConfig) VariableSchema() clusterv1.VariableSchema {
6088
return clusterv1.VariableSchema{
6189
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
6290
Description: "Node configuration",
6391
Type: "object",
64-
Properties: map[string]clusterv1.JSONSchemaProps{},
92+
Properties: map[string]clusterv1.JSONSchemaProps{
93+
"clusterAutoscaler": ClusterAutoscalerNodeConfig{}.VariableSchema().OpenAPIV3Schema,
94+
},
6595
},
6696
}
6797
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/pkg/capi/clustertopology/patches/selectors/selectors.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ func WorkersKubeadmConfigTemplateSelector() clusterv1.PatchSelector {
3434
}
3535
}
3636

37+
func MachineDeploymentSelector() clusterv1.PatchSelector {
38+
return clusterv1.PatchSelector{
39+
APIVersion: clusterv1.GroupVersion.String(),
40+
Kind: "MachineDeployment",
41+
}
42+
}
43+
3744
// InfrastructureCluster selector matches against infrastructure clusters.
3845
// Passing in the API version (not the API group) is required because different providers could support different API
3946
// versions. This also allows for a patch to select multiple infrastructure versions for the same provider.

docs/content/addons/cluster-autoscaler.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ spec:
2929
workers:
3030
machineDeployments:
3131
- class: default-worker
32-
metadata:
33-
annotations:
34-
# Set the following annotations to configure the Cluster Autoscaler
35-
# The initial MachineDeployment will have 1 Machine
36-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "3"
37-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
3832
name: md-0
33+
variables:
34+
- name: workerConfig
35+
value:
36+
clusterAutoscaler:
37+
minimumSize: 1
38+
maximumSize: 3
3939
# Remove the replicas field, otherwise the topology controller will revert back the aytoscaler's changes
4040
```
4141

examples/capi-quick-start/aws-cluster-calico-crs.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,5 @@ spec:
5353
workers:
5454
machineDeployments:
5555
- class: default-worker
56-
metadata:
57-
annotations:
58-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "${WORKER_MACHINE_COUNT}"
59-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "${WORKER_MACHINE_COUNT}"
6056
name: md-0
57+
replicas: ${WORKER_MACHINE_COUNT}

examples/capi-quick-start/aws-cluster-cilium-crs.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,5 @@ spec:
5353
workers:
5454
machineDeployments:
5555
- class: default-worker
56-
metadata:
57-
annotations:
58-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "${WORKER_MACHINE_COUNT}"
59-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "${WORKER_MACHINE_COUNT}"
6056
name: md-0
57+
replicas: ${WORKER_MACHINE_COUNT}

examples/capi-quick-start/docker-cluster-calico-crs.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,5 @@ spec:
3434
workers:
3535
machineDeployments:
3636
- class: default-worker
37-
metadata:
38-
annotations:
39-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "${WORKER_MACHINE_COUNT}"
40-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "${WORKER_MACHINE_COUNT}"
4137
name: md-0
38+
replicas: ${WORKER_MACHINE_COUNT}

examples/capi-quick-start/docker-cluster-cilium-crs.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,5 @@ spec:
3434
workers:
3535
machineDeployments:
3636
- class: default-worker
37-
metadata:
38-
annotations:
39-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "${WORKER_MACHINE_COUNT}"
40-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "${WORKER_MACHINE_COUNT}"
4137
name: md-0
38+
replicas: ${WORKER_MACHINE_COUNT}

hack/examples/bases/aws/calico/crs/kustomization.yaml.tmpl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ patches:
3232
path: "/spec/topology/variables/0/value/addons/clusterAutoscaler"
3333
value:
3434
strategy: ClusterResourceSet
35-
- op: "remove"
36-
path: "/spec/topology/workers/machineDeployments/0/replicas"
37-
- op: "add"
38-
path: "/spec/topology/workers/machineDeployments/0/metadata"
39-
value:
40-
annotations:
41-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "$${WORKER_MACHINE_COUNT}"
42-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "$${WORKER_MACHINE_COUNT}"
4335

4436

4537
# Delete all ClusterClass related resources to prevent duplicate resources because we use the same resources definition

hack/examples/bases/aws/cilium/crs/kustomization.yaml.tmpl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ patches:
3232
path: "/spec/topology/variables/0/value/addons/clusterAutoscaler"
3333
value:
3434
strategy: ClusterResourceSet
35-
- op: "remove"
36-
path: "/spec/topology/workers/machineDeployments/0/replicas"
37-
- op: "add"
38-
path: "/spec/topology/workers/machineDeployments/0/metadata"
39-
value:
40-
annotations:
41-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "$${WORKER_MACHINE_COUNT}"
42-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "$${WORKER_MACHINE_COUNT}"
4335

4436

4537
# Delete all ClusterClass related resources to prevent duplicate resources because we use the same resources definition

hack/examples/bases/docker/calico/crs/kustomization.yaml.tmpl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,3 @@ patches:
3232
path: "/spec/topology/variables/0/value/addons/clusterAutoscaler"
3333
value:
3434
strategy: ClusterResourceSet
35-
- op: "remove"
36-
path: "/spec/topology/workers/machineDeployments/0/replicas"
37-
- op: "add"
38-
path: "/spec/topology/workers/machineDeployments/0/metadata"
39-
value:
40-
annotations:
41-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "$${WORKER_MACHINE_COUNT}"
42-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "$${WORKER_MACHINE_COUNT}"

hack/examples/bases/docker/cilium/crs/kustomization.yaml.tmpl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,3 @@ patches:
3232
path: "/spec/topology/variables/0/value/addons/clusterAutoscaler"
3333
value:
3434
strategy: ClusterResourceSet
35-
- op: "remove"
36-
path: "/spec/topology/workers/machineDeployments/0/replicas"
37-
- op: "add"
38-
path: "/spec/topology/workers/machineDeployments/0/metadata"
39-
value:
40-
annotations:
41-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "$${WORKER_MACHINE_COUNT}"
42-
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "$${WORKER_MACHINE_COUNT}"

hack/examples/sync.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,3 @@ sed -i'' 's/${AMI_LOOKUP_ORG}/"${AMI_LOOKUP_ORG}"/' "${EXAMPLE_CLUSTERS_DIR}"/*.
111111

112112
# TODO Remove once CAPA templates default to using external cloud provider.
113113
sed -i'' 's/cloud-provider:\ aws/cloud-provider:\ external/g' "${EXAMPLE_CLUSTERCLASSES_DIR}/aws-cluster-class.yaml"
114-
115-
# TODO Remove once kustomize supports retaining quotes in what will be numeric values.
116-
#shellcheck disable=SC2016
117-
sed -i'' 's/size\: ${WORKER_MACHINE_COUNT}/size\: "${WORKER_MACHINE_COUNT}"/' "${EXAMPLE_CLUSTERS_DIR}"/*.yaml

pkg/handlers/aws/mutation/metapatch_handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/aws/mutation/region"
1818
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/aws/mutation/securitygroups"
1919
genericmutation "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation"
20+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation/clusterautoscaler"
2021
)
2122

2223
// MetaPatchHandler returns a meta patch handler for mutating CAPA clusters.
@@ -48,6 +49,7 @@ func MetaWorkerPatchHandler() handlers.Named {
4849
instancetype.NewWorkerPatch(),
4950
ami.NewWorkerPatch(),
5051
securitygroups.NewWorkerPatch(),
52+
clusterautoscaler.NewWorkerPatch(),
5153
}
5254

5355
return mutation.NewMetaGeneratePatchesHandler(

pkg/handlers/docker/mutation/metapatch_handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
1111
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/docker/mutation/customimage"
1212
genericmutation "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation"
13+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation/clusterautoscaler"
1314
)
1415

1516
// MetaPatchHandler returns a meta patch handler for mutating CAPD clusters.
@@ -31,6 +32,7 @@ func MetaPatchHandler(mgr manager.Manager) handlers.Named {
3132
func MetaWorkerPatchHandler() handlers.Named {
3233
patchHandlers := []mutation.MetaMutator{
3334
customimage.NewWorkerPatch(),
35+
clusterautoscaler.NewWorkerPatch(),
3436
}
3537

3638
return mutation.NewMetaGeneratePatchesHandler(
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package clusterautoscaler
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
12+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
13+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
14+
ctrl "sigs.k8s.io/controller-runtime"
15+
"sigs.k8s.io/controller-runtime/pkg/client"
16+
17+
"github.com/d2iq-labs/capi-runtime-extensions/api/v1alpha1"
18+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches"
19+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches/selectors"
20+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
21+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/workerconfig"
22+
)
23+
24+
const (
25+
// VariableName is the external patch variable name.
26+
VariableName = "clusterAutoscaler"
27+
)
28+
29+
type clusterAuotscalerPatchHandler struct {
30+
variableName string
31+
variableFieldPath []string
32+
}
33+
34+
func NewWorkerPatch() *clusterAuotscalerPatchHandler {
35+
return newClusterAutoscalerPatchHandler(workerconfig.MetaVariableName, VariableName)
36+
}
37+
38+
func newClusterAutoscalerPatchHandler(
39+
variableName string,
40+
variableFieldPath ...string,
41+
) *clusterAuotscalerPatchHandler {
42+
return &clusterAuotscalerPatchHandler{
43+
variableName: variableName,
44+
variableFieldPath: variableFieldPath,
45+
}
46+
}
47+
48+
func (h *clusterAuotscalerPatchHandler) Mutate(
49+
ctx context.Context,
50+
obj *unstructured.Unstructured,
51+
vars map[string]apiextensionsv1.JSON,
52+
holderRef runtimehooksv1.HolderReference,
53+
_ client.ObjectKey,
54+
) error {
55+
log := ctrl.LoggerFrom(ctx).WithValues(
56+
"holderRef", holderRef,
57+
)
58+
59+
clusterAutoscaler, found, err := variables.Get[v1alpha1.ClusterAutoscalerNodeConfig](
60+
vars,
61+
h.variableName,
62+
h.variableFieldPath...,
63+
)
64+
if err != nil {
65+
return err
66+
}
67+
if !found {
68+
log.V(5).Info("clusterAutoscaler variable not defined")
69+
return nil
70+
}
71+
log.V(5).Info("clusterAutoscaler variable defined")
72+
73+
log.V(5).Info("clusterAutoscaler variable defined")
74+
log = log.WithValues(
75+
"variableName",
76+
h.variableName,
77+
"variableFieldPath",
78+
h.variableFieldPath,
79+
"variableValue",
80+
clusterAutoscaler,
81+
)
82+
83+
return patches.MutateIfApplicable(
84+
obj, vars, &holderRef, selectors.MachineDeploymentSelector(), log,
85+
func(obj *clusterv1.MachineDeployment) error {
86+
log.WithValues(
87+
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
88+
"patchedObjectName", client.ObjectKeyFromObject(obj),
89+
).Info("setting annotations for cluster-autoscaler in MachineDeployment")
90+
91+
if obj.Annotations == nil {
92+
obj.Annotations = map[string]string{}
93+
}
94+
obj.Annotations[clusterv1.AutoscalerMinSizeAnnotation] = fmt.Sprint(clusterAutoscaler.MinimumSize)
95+
obj.Annotations[clusterv1.AutoscalerMaxSizeAnnotation] = fmt.Sprint(clusterAutoscaler.MaximumSize)
96+
97+
return nil
98+
},
99+
)
100+
}

0 commit comments

Comments
 (0)