Skip to content

Commit bfa3f0c

Browse files
committed
Mimic upstream ec2nodeclass
1 parent ee253c1 commit bfa3f0c

9 files changed

+2383
-413
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Create karpenter custom resources in workload clusters.
13+
1014
## [0.20.0] - 2025-06-23
1115

1216
### Changed

api/v1alpha1/ec2nodeclass.go

Lines changed: 451 additions & 0 deletions
Large diffs are not rendered by default.

api/v1alpha1/karpentermachinepool_types.go

Lines changed: 0 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -17,286 +17,12 @@ limitations under the License.
1717
package v1alpha1
1818

1919
import (
20-
v1 "k8s.io/api/core/v1"
21-
"k8s.io/apimachinery/pkg/api/resource"
2220
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2321
capi "sigs.k8s.io/cluster-api/api/v1beta1"
2422
)
2523

26-
// NodePoolSpec defines the configuration for a Karpenter NodePool
27-
type NodePoolSpec struct {
28-
// Template contains the template of possibilities for the provisioning logic to launch a NodeClaim with.
29-
// NodeClaims launched from this NodePool will often be further constrained than the template specifies.
30-
// +required
31-
Template NodeClaimTemplate `json:"template"`
32-
33-
// Disruption contains the parameters that relate to Karpenter's disruption logic
34-
// +kubebuilder:default:={consolidateAfter: "0s"}
35-
// +optional
36-
Disruption Disruption `json:"disruption"`
37-
38-
// Limits define a set of bounds for provisioning capacity.
39-
// +optional
40-
Limits Limits `json:"limits,omitempty"`
41-
42-
// Weight is the priority given to the nodepool during scheduling. A higher
43-
// numerical weight indicates that this nodepool will be ordered
44-
// ahead of other nodepools with lower weights. A nodepool with no weight
45-
// will be treated as if it is a nodepool with a weight of 0.
46-
// +kubebuilder:validation:Minimum:=1
47-
// +kubebuilder:validation:Maximum:=100
48-
// +optional
49-
Weight *int32 `json:"weight,omitempty"`
50-
}
51-
52-
type NodeClaimTemplate struct {
53-
ObjectMeta `json:"metadata,omitempty"`
54-
// +required
55-
Spec NodeClaimTemplateSpec `json:"spec"`
56-
}
57-
58-
type ObjectMeta struct {
59-
// Map of string keys and values that can be used to organize and categorize
60-
// (scope and select) objects. May match selectors of replication controllers
61-
// and services.
62-
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
63-
// +optional
64-
Labels map[string]string `json:"labels,omitempty"`
65-
66-
// Annotations is an unstructured key value map stored with a resource that may be
67-
// set by external tools to store and retrieve arbitrary metadata. They are not
68-
// queryable and should be preserved when modifying objects.
69-
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
70-
// +optional
71-
Annotations map[string]string `json:"annotations,omitempty"`
72-
}
73-
74-
// NodeClaimTemplateSpec describes the desired state of the NodeClaim in the Nodepool
75-
// NodeClaimTemplateSpec is used in the NodePool's NodeClaimTemplate, with the resource requests omitted since
76-
// users are not able to set resource requests in the NodePool.
77-
type NodeClaimTemplateSpec struct {
78-
// Taints will be applied to the NodeClaim's node.
79-
// +optional
80-
Taints []v1.Taint `json:"taints,omitempty"`
81-
// StartupTaints are taints that are applied to nodes upon startup which are expected to be removed automatically
82-
// within a short period of time, typically by a DaemonSet that tolerates the taint. These are commonly used by
83-
// daemonsets to allow initialization and enforce startup ordering. StartupTaints are ignored for provisioning
84-
// purposes in that pods are not required to tolerate a StartupTaint in order to have nodes provisioned for them.
85-
// +optional
86-
StartupTaints []v1.Taint `json:"startupTaints,omitempty"`
87-
// Requirements are layered with GetLabels and applied to every node.
88-
// +kubebuilder:validation:XValidation:message="requirements with operator 'In' must have a value defined",rule="self.all(x, x.operator == 'In' ? x.values.size() != 0 : true)"
89-
// +kubebuilder:validation:XValidation:message="requirements operator 'Gt' or 'Lt' must have a single positive integer value",rule="self.all(x, (x.operator == 'Gt' || x.operator == 'Lt') ? (x.values.size() == 1 && int(x.values[0]) >= 0) : true)"
90-
// +kubebuilder:validation:XValidation:message="requirements with 'minValues' must have at least that many values specified in the 'values' field",rule="self.all(x, (x.operator == 'In' && has(x.minValues)) ? x.values.size() >= x.minValues : true)"
91-
// +kubebuilder:validation:MaxItems:=100
92-
// +required
93-
Requirements []NodeSelectorRequirementWithMinValues `json:"requirements" hash:"ignore"`
94-
// TerminationGracePeriod is the maximum duration the controller will wait before forcefully deleting the pods on a node, measured from when deletion is first initiated.
95-
//
96-
// Warning: this feature takes precedence over a Pod's terminationGracePeriodSeconds value, and bypasses any blocked PDBs or the karpenter.sh/do-not-disrupt annotation.
97-
//
98-
// This field is intended to be used by cluster administrators to enforce that nodes can be cycled within a given time period.
99-
// When set, drifted nodes will begin draining even if there are pods blocking eviction. Draining will respect PDBs and the do-not-disrupt annotation until the TGP is reached.
100-
//
101-
// Karpenter will preemptively delete pods so their terminationGracePeriodSeconds align with the node's terminationGracePeriod.
102-
// If a pod would be terminated without being granted its full terminationGracePeriodSeconds prior to the node timeout,
103-
// that pod will be deleted at T = node timeout - pod terminationGracePeriodSeconds.
104-
//
105-
// The feature can also be used to allow maximum time limits for long-running jobs which can delay node termination with preStop hooks.
106-
// If left undefined, the controller will wait indefinitely for pods to be drained.
107-
// +kubebuilder:validation:Pattern=`^([0-9]+(s|m|h))+$`
108-
// +kubebuilder:validation:Type="string"
109-
// +optional
110-
TerminationGracePeriod *metav1.Duration `json:"terminationGracePeriod,omitempty"`
111-
// ExpireAfter is the duration the controller will wait
112-
// before terminating a node, measured from when the node is created. This
113-
// is useful to implement features like eventually consistent node upgrade,
114-
// memory leak protection, and disruption testing.
115-
// +kubebuilder:default:="720h"
116-
// +kubebuilder:validation:Pattern=`^(([0-9]+(s|m|h))+|Never)$`
117-
// +kubebuilder:validation:Type="string"
118-
// +kubebuilder:validation:Schemaless
119-
// +optional
120-
ExpireAfter NillableDuration `json:"expireAfter,omitempty"`
121-
}
122-
123-
// A node selector requirement with min values is a selector that contains values, a key, an operator that relates the key and values
124-
// and minValues that represent the requirement to have at least that many values.
125-
type NodeSelectorRequirementWithMinValues struct {
126-
v1.NodeSelectorRequirement `json:",inline"`
127-
// This field is ALPHA and can be dropped or replaced at any time
128-
// MinValues is the minimum number of unique values required to define the flexibility of the specific requirement.
129-
// +kubebuilder:validation:Minimum:=1
130-
// +kubebuilder:validation:Maximum:=50
131-
// +optional
132-
MinValues *int `json:"minValues,omitempty"`
133-
}
134-
135-
type NodeClassReference struct {
136-
// Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"
137-
// +kubebuilder:validation:XValidation:rule="self != ''",message="kind may not be empty"
138-
// +required
139-
Kind string `json:"kind"`
140-
// Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names
141-
// +kubebuilder:validation:XValidation:rule="self != ''",message="name may not be empty"
142-
// +required
143-
Name string `json:"name"`
144-
// API version of the referent
145-
// +kubebuilder:validation:XValidation:rule="self != ''",message="group may not be empty"
146-
// +kubebuilder:validation:Pattern=`^[^/]*$`
147-
// +required
148-
Group string `json:"group"`
149-
}
150-
151-
type Limits v1.ResourceList
152-
153-
type ConsolidationPolicy string
154-
155-
const (
156-
ConsolidationPolicyWhenEmpty ConsolidationPolicy = "WhenEmpty"
157-
ConsolidationPolicyWhenEmptyOrUnderutilized ConsolidationPolicy = "WhenEmptyOrUnderutilized"
158-
)
159-
160-
// DisruptionReason defines valid reasons for disruption budgets.
161-
// +kubebuilder:validation:Enum={Underutilized,Empty,Drifted}
162-
type DisruptionReason string
163-
164-
// Budget defines when Karpenter will restrict the
165-
// number of Node Claims that can be terminating simultaneously.
166-
type Budget struct {
167-
// Reasons is a list of disruption methods that this budget applies to. If Reasons is not set, this budget applies to all methods.
168-
// Otherwise, this will apply to each reason defined.
169-
// allowed reasons are Underutilized, Empty, and Drifted.
170-
// +optional
171-
Reasons []DisruptionReason `json:"reasons,omitempty"`
172-
// Nodes dictates the maximum number of NodeClaims owned by this NodePool
173-
// that can be terminating at once. This is calculated by counting nodes that
174-
// have a deletion timestamp set, or are actively being deleted by Karpenter.
175-
// This field is required when specifying a budget.
176-
// This cannot be of type intstr.IntOrString since kubebuilder doesn't support pattern
177-
// checking for int nodes for IntOrString nodes.
178-
// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/55efe4be40394a288216dab63156b0a64fb82929/pkg/crd/markers/validation.go#L379-L388
179-
// +kubebuilder:validation:Pattern:="^((100|[0-9]{1,2})%|[0-9]+)$"
180-
// +kubebuilder:default:="10%"
181-
Nodes string `json:"nodes" hash:"ignore"`
182-
// Schedule specifies when a budget begins being active, following
183-
// the upstream cronjob syntax. If omitted, the budget is always active.
184-
// Timezones are not supported.
185-
// This field is required if Duration is set.
186-
// +kubebuilder:validation:Pattern:=`^(@(annually|yearly|monthly|weekly|daily|midnight|hourly))|((.+)\s(.+)\s(.+)\s(.+)\s(.+))$`
187-
// +optional
188-
Schedule *string `json:"schedule,omitempty" hash:"ignore"`
189-
// Duration determines how long a Budget is active since each Schedule hit.
190-
// Only minutes and hours are accepted, as cron does not work in seconds.
191-
// If omitted, the budget is always active.
192-
// This is required if Schedule is set.
193-
// This regex has an optional 0s at the end since the duration.String() always adds
194-
// a 0s at the end.
195-
// +kubebuilder:validation:Pattern=`^((([0-9]+(h|m))|([0-9]+h[0-9]+m))(0s)?)$`
196-
// +kubebuilder:validation:Type="string"
197-
// +optional
198-
Duration *metav1.Duration `json:"duration,omitempty" hash:"ignore"`
199-
}
200-
201-
type Disruption struct {
202-
// ConsolidateAfter is the duration the controller will wait
203-
// before attempting to terminate nodes that are underutilized.
204-
// Refer to ConsolidationPolicy for how underutilization is considered.
205-
// +kubebuilder:validation:Pattern=`^(([0-9]+(s|m|h))+|Never)$`
206-
// +kubebuilder:validation:Type="string"
207-
// +kubebuilder:validation:Schemaless
208-
// +required
209-
ConsolidateAfter NillableDuration `json:"consolidateAfter"`
210-
// ConsolidationPolicy describes which nodes Karpenter can disrupt through its consolidation
211-
// algorithm. This policy defaults to "WhenEmptyOrUnderutilized" if not specified
212-
// +kubebuilder:default:="WhenEmptyOrUnderutilized"
213-
// +kubebuilder:validation:Enum:={WhenEmpty,WhenEmptyOrUnderutilized}
214-
// +optional
215-
ConsolidationPolicy ConsolidationPolicy `json:"consolidationPolicy,omitempty"`
216-
// Budgets is a list of Budgets.
217-
// If there are multiple active budgets, Karpenter uses
218-
// the most restrictive value. If left undefined,
219-
// this will default to one budget with a value to 10%.
220-
// +kubebuilder:validation:XValidation:message="'schedule' must be set with 'duration'",rule="self.all(x, has(x.schedule) == has(x.duration))"
221-
// +kubebuilder:default:={{nodes: "10%"}}
222-
// +kubebuilder:validation:MaxItems=50
223-
// +optional
224-
Budgets []Budget `json:"budgets,omitempty" hash:"ignore"`
225-
}
226-
227-
// ConsolidateUnderSpec defines when to consolidate under
228-
type ConsolidateUnderSpec struct {
229-
// CPUUtilization specifies the CPU utilization threshold
230-
// +optional
231-
CPUUtilization *string `json:"cpuUtilization,omitempty"`
232-
233-
// MemoryUtilization specifies the memory utilization threshold
234-
// +optional
235-
MemoryUtilization *string `json:"memoryUtilization,omitempty"`
236-
}
237-
238-
// LimitsSpec defines the limits for a NodePool
239-
type LimitsSpec struct {
240-
// CPU specifies the CPU limit
241-
// +optional
242-
CPU *resource.Quantity `json:"cpu,omitempty"`
243-
244-
// Memory specifies the memory limit
245-
// +optional
246-
Memory *resource.Quantity `json:"memory,omitempty"`
247-
}
248-
249-
// RequirementSpec defines a requirement for a NodePool
250-
type RequirementSpec struct {
251-
// Key specifies the requirement key
252-
Key string `json:"key"`
253-
254-
// Operator specifies the requirement operator
255-
Operator string `json:"operator"`
256-
257-
// Values specifies the requirement values
258-
// +optional
259-
Values []string `json:"values,omitempty"`
260-
}
261-
262-
// TaintSpec defines a taint for a NodePool
263-
type TaintSpec struct {
264-
// Key specifies the taint key
265-
Key string `json:"key"`
266-
267-
// Value specifies the taint value
268-
// +optional
269-
Value *string `json:"value,omitempty"`
270-
271-
// Effect specifies the taint effect
272-
Effect string `json:"effect"`
273-
}
274-
275-
// EC2NodeClassSpec defines the configuration for a Karpenter EC2NodeClass
276-
type EC2NodeClassSpec struct {
277-
// Name is the ami name in EC2.
278-
// This value is the name field, which is different from the name tag.
279-
AMIName string `json:"amiName,omitempty"`
280-
// Owner is the owner for the ami.
281-
// You can specify a combination of AWS account IDs, "self", "amazon", and "aws-marketplace"
282-
AMIOwner string `json:"amiOwner,omitempty"`
283-
284-
// SecurityGroups specifies the security groups to use
285-
// +optional
286-
SecurityGroups map[string]string `json:"securityGroups,omitempty"`
287-
288-
// Subnets specifies the subnets to use
289-
// +optional
290-
Subnets map[string]string `json:"subnets,omitempty"`
291-
}
292-
29324
// KarpenterMachinePoolSpec defines the desired state of KarpenterMachinePool.
29425
type KarpenterMachinePoolSpec struct {
295-
// The name or the Amazon Resource Name (ARN) of the instance profile associated
296-
// with the IAM role for the instance. The instance profile contains the IAM
297-
// role.
298-
IamInstanceProfile string `json:"iamInstanceProfile,omitempty"`
299-
30026
// NodePool specifies the configuration for the Karpenter NodePool
30127
// +optional
30228
NodePool *NodePoolSpec `json:"nodePool,omitempty"`

0 commit comments

Comments
 (0)