Skip to content

Commit d450bb6

Browse files
author
jwcesign
authored
Merge pull request #55 from helen-frank/debug-together
fix: support alibabacloudlinux2, alibabacloudlinux3 image provider, fix and remove launchtemplate provider
2 parents fe94239 + 2ee1e24 commit d450bb6

File tree

20 files changed

+446
-714
lines changed

20 files changed

+446
-714
lines changed

cmd/controller/main.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ func main() {
6161
op.PricingProvider,
6262
op.VSwitchProvider,
6363
op.SecurityGroupProvider,
64-
op.LaunchTemplateProvider,
6564
op.ImageProvider,
6665
)...).
6766
Start(ctx, cloudProvider)

config/components/crds/karpenter.k8s.alicloud_ecsnodeclasses.yaml

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.16.3
6+
controller-gen.kubebuilder.io/version: v0.16.4
77
name: ecsnodeclasses.karpenter.k8s.alicloud
88
spec:
99
group: karpenter.k8s.alicloud
@@ -58,58 +58,34 @@ spec:
5858
description: |-
5959
Alias specifies which ACK image to select.
6060
Each alias consists of a family and an image version, specified as "family@version".
61-
Valid families include: aliyun3.
61+
Valid families include: AlibabaCloudLinux3,AlibabaCloudLinux2
6262
Currently only supports version pinning to the latest image release, with that images version format (ex: "aliyun3@latest").
6363
Setting the version to latest will result in drift when a new Image is released. This is **not** recommended for production environments.
6464
maxLength: 30
6565
type: string
6666
x-kubernetes-validations:
6767
- message: '''alias'' is improperly formatted, must match the
68-
format ''family@version'''
69-
rule: self.matches('^[a-zA-Z0-9]*@.*$')
68+
format ''family'''
69+
rule: self.matches('^[a-zA-Z0-9]*$')
7070
- message: 'family is not supported, must be one of the following:
71-
''aliyun3'''
72-
rule: self.find('^[^@]+') in ['aliyun3']
71+
''AlibabaCloudLinux3,AlibabaCloudLinux2'''
72+
rule: self.find('^[^@]+') in ['AlibabaCloudLinux3', 'AlibabaCloudLinux2']
7373
id:
7474
description: ID is the image id in ECS
7575
type: string
76-
name:
77-
description: |-
78-
Name is the image name in ECS.
79-
This value is the name field, which is different from the name tag.
80-
type: string
81-
owner:
82-
description: |-
83-
Owner is the image source.
84-
Default is system | self | public. If specified, only one of the following: "self", "system", "share", "public", and "marketplace"
85-
type: string
86-
tags:
87-
additionalProperties:
88-
type: string
89-
description: |-
90-
Tags is a map of key/value tags used to select vswitches
91-
Specifying '*' for a value selects all values for a given tag key.
92-
maxProperties: 20
93-
type: object
94-
x-kubernetes-validations:
95-
- message: empty tag keys aren't supported
96-
rule: self.all(k, k != '')
9776
type: object
9877
maxItems: 30
9978
minItems: 1
10079
type: array
10180
x-kubernetes-validations:
102-
- message: expected at least one, got none, ['tags', 'id', 'name',
103-
'alias']
104-
rule: self.all(x, has(x.tags) || has(x.id) || has(x.name) || has(x.alias))
81+
- message: expected at least one, got none, ['id', 'alias']
82+
rule: self.all(x, has(x.id) || has(x.alias))
10583
- message: '''id'' is mutually exclusive, cannot be set with a combination
10684
of other fields in imageSelectorTerms'
107-
rule: '!self.exists(x, has(x.id) && (has(x.alias) || has(x.tags)
108-
|| has(x.name) || has(x.owner)))'
85+
rule: '!self.exists(x, has(x.id) && (has(x.alias)))'
10986
- message: '''alias'' is mutually exclusive, cannot be set with a
11087
combination of other fields in imageSelectorTerms'
111-
rule: '!self.exists(x, has(x.alias) && (has(x.id) || has(x.tags)
112-
|| has(x.name) || has(x.owner)))'
88+
rule: '!self.exists(x, has(x.alias) && (has(x.id)))'
11389
- message: '''alias'' is mutually exclusive, cannot be set with a
11490
combination of other imageSelectorTerms'
11591
rule: '!(self.exists(x, has(x.alias)) && self.size() != 1)'

examples/nodepool/ecsnodeclass.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ spec:
1010
- tags:
1111
karpenter.sh/discovery: "cluster-demonstration" # replace with your cluster name
1212
imageSelectorTerms:
13-
- alias: aliyun3@latest
13+
- alias: AlibabaCloudLinux3

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ require (
113113
k8s.io/cloud-provider v0.30.3 // indirect
114114
k8s.io/component-base v0.30.3 // indirect
115115
k8s.io/csi-translation-lib v0.30.3 // indirect
116-
k8s.io/klog v1.0.0
116+
k8s.io/klog v1.0.0 // indirect
117117
k8s.io/klog/v2 v2.130.1
118118
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
119119
knative.dev/pkg v0.0.0-20231010144348-ca8c009405dd

pkg/apis/v1alpha1/ecsnodeclass.go

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package v1alpha1
1818

1919
import (
2020
"fmt"
21-
"log"
22-
"strings"
2321

2422
"github.com/mitchellh/hashstructure/v2"
2523
"github.com/samber/lo"
@@ -45,9 +43,9 @@ type ECSNodeClassSpec struct {
4543
// +required
4644
SecurityGroupSelectorTerms []SecurityGroupSelectorTerm `json:"securityGroupSelectorTerms" hash:"ignore"`
4745
// ImageSelectorTerms is a list of or image selector terms. The terms are ORed.
48-
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['tags', 'id', 'name', 'alias']",rule="self.all(x, has(x.tags) || has(x.id) || has(x.name) || has(x.alias))"
49-
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in imageSelectorTerms",rule="!self.exists(x, has(x.id) && (has(x.alias) || has(x.tags) || has(x.name) || has(x.owner)))"
50-
// +kubebuilder:validation:XValidation:message="'alias' is mutually exclusive, cannot be set with a combination of other fields in imageSelectorTerms",rule="!self.exists(x, has(x.alias) && (has(x.id) || has(x.tags) || has(x.name) || has(x.owner)))"
46+
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['id', 'alias']",rule="self.all(x, has(x.id) || has(x.alias))"
47+
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in imageSelectorTerms",rule="!self.exists(x, has(x.id) && (has(x.alias)))"
48+
// +kubebuilder:validation:XValidation:message="'alias' is mutually exclusive, cannot be set with a combination of other fields in imageSelectorTerms",rule="!self.exists(x, has(x.alias) && (has(x.id)))"
5149
// +kubebuilder:validation:XValidation:message="'alias' is mutually exclusive, cannot be set with a combination of other imageSelectorTerms",rule="!(self.exists(x, has(x.alias)) && self.size() != 1)"
5250
// +kubebuilder:validation:MinItems:=1
5351
// +kubebuilder:validation:MaxItems:=30
@@ -117,31 +115,17 @@ type SecurityGroupSelectorTerm struct {
117115
type ImageSelectorTerm struct {
118116
// Alias specifies which ACK image to select.
119117
// Each alias consists of a family and an image version, specified as "family@version".
120-
// Valid families include: aliyun3.
118+
// Valid families include: AlibabaCloudLinux3,AlibabaCloudLinux2
121119
// Currently only supports version pinning to the latest image release, with that images version format (ex: "aliyun3@latest").
122120
// Setting the version to latest will result in drift when a new Image is released. This is **not** recommended for production environments.
123-
// +kubebuilder:validation:XValidation:message="'alias' is improperly formatted, must match the format 'family@version'",rule="self.matches('^[a-zA-Z0-9]*@.*$')"
124-
// +kubebuilder:validation:XValidation:message="family is not supported, must be one of the following: 'aliyun3'",rule="self.find('^[^@]+') in ['aliyun3']"
121+
// +kubebuilder:validation:XValidation:message="'alias' is improperly formatted, must match the format 'family'",rule="self.matches('^[a-zA-Z0-9]*$')"
122+
// +kubebuilder:validation:XValidation:message="family is not supported, must be one of the following: 'AlibabaCloudLinux3,AlibabaCloudLinux2'",rule="self.find('^[^@]+') in ['AlibabaCloudLinux3', 'AlibabaCloudLinux2']"
125123
// +kubebuilder:validation:MaxLength=30
126124
// +optional
127125
Alias string `json:"alias,omitempty"`
128-
// Tags is a map of key/value tags used to select vswitches
129-
// Specifying '*' for a value selects all values for a given tag key.
130-
// +kubebuilder:validation:XValidation:message="empty tag keys aren't supported",rule="self.all(k, k != '')"
131-
// +kubebuilder:validation:MaxProperties:=20
132-
// +optional
133-
Tags map[string]string `json:"tags,omitempty"`
134126
// ID is the image id in ECS
135127
// +optional
136128
ID string `json:"id,omitempty"`
137-
// Name is the image name in ECS.
138-
// This value is the name field, which is different from the name tag.
139-
// +optional
140-
Name string `json:"name,omitempty"`
141-
// Owner is the image source.
142-
// Default is system | self | public. If specified, only one of the following: "self", "system", "share", "public", and "marketplace"
143-
// +optional
144-
Owner string `json:"owner,omitempty"`
145129
}
146130

147131
// KubeletConfiguration defines args to be used when configuring kubelet on provisioned nodes.
@@ -298,25 +282,5 @@ type ECSNodeClassList struct {
298282
}
299283

300284
func ImageFamilyFromAlias(alias string) string {
301-
components := strings.Split(alias, "@")
302-
if len(components) != 2 {
303-
log.Fatalf("failed to parse image alias %q, invalid format", alias)
304-
}
305-
family, ok := lo.Find([]string{
306-
ImageFamilyAliyun3,
307-
}, func(family string) bool {
308-
return strings.ToLower(family) == components[0]
309-
})
310-
if !ok {
311-
log.Fatalf("%q is an invalid alias family", components[0])
312-
}
313-
return family
314-
}
315-
316-
func ImageVersionFromAlias(alias string) string {
317-
components := strings.Split(alias, "@")
318-
if len(components) != 2 {
319-
log.Fatalf("failed to parse image alias %q, invalid format", alias)
320-
}
321-
return components[1]
285+
return alias
322286
}

pkg/apis/v1alpha1/labels.go

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,12 @@ var (
7777
regexp.MustCompile(fmt.Sprintf("^%s$", regexp.QuoteMeta(LabelNodeClass))),
7878
regexp.MustCompile(fmt.Sprintf("^%s$", regexp.QuoteMeta(TagNodeClaim))),
7979
}
80-
AMIFamilyBottlerocket = "Bottlerocket"
81-
AMIFamilyAL2 = "AL2"
82-
ImageFamilyAliyun3 = "Aliyun3"
83-
AMIFamilyUbuntu = "Ubuntu"
84-
AMIFamilyWindows2019 = "Windows2019"
85-
AMIFamilyWindows2022 = "Windows2022"
86-
ImageFamilyCustom = "Custom"
87-
Windows2019 = "2019"
88-
Windows2022 = "2022"
89-
WindowsCore = "Core"
90-
Windows2019Build = "10.0.17763"
91-
Windows2022Build = "10.0.20348"
92-
ResourceNVIDIAGPU corev1.ResourceName = "nvidia.com/gpu"
93-
ResourceAMDGPU corev1.ResourceName = "amd.com/gpu"
94-
ResourceAWSNeuron corev1.ResourceName = "alicloud.amazon.com/neuron"
95-
ResourceHabanaGaudi corev1.ResourceName = "habana.ai/gaudi"
96-
ResourceAWSPodENI corev1.ResourceName = "vpc.amazonalicloud.com/pod-eni"
97-
ResourcePrivateIPv4Address corev1.ResourceName = "vpc.amazonalicloud.com/PrivateIPv4Address"
98-
ResourceEFA corev1.ResourceName = "vpc.amazonalicloud.com/efa"
80+
ImageFamilyAlibabaCloudLinux3 = "AlibabaCloudLinux3"
81+
ImageFamilyAlibabaCloudLinux2 = "AlibabaCloudLinux2"
82+
ImageFamilyCustom = "Custom"
83+
ResourceNVIDIAGPU corev1.ResourceName = "nvidia.com/gpu"
84+
ResourceAMDGPU corev1.ResourceName = "amd.com/gpu"
85+
ResourcePrivateIPv4Address corev1.ResourceName = "vpc.alibabacloud.com/PrivateIPv4Address"
9986

10087
ECSClusterNameTagKey = "ecs:ecs-cluster-name"
10188

pkg/apis/v1alpha1/zz_generated.deepcopy.go

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controllers/controllers.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/imagefamily"
3737
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/instance"
3838
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/instancetype"
39-
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/launchtemplate"
4039
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/pricing"
4140
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/securitygroup"
4241
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/vswitch"
@@ -48,12 +47,12 @@ func NewControllers(ctx context.Context, mgr manager.Manager, clk clock.Clock,
4847
instanceProvider instance.Provider, instanceTypeProvider instancetype.Provider,
4948
pricingProvider pricing.Provider,
5049
vSwitchProvider vswitch.Provider, securitygroupProvider securitygroup.Provider,
51-
launchTemplateProvider launchtemplate.Provider, imageProvider imagefamily.Provider) []controller.Controller {
50+
imageProvider imagefamily.Provider) []controller.Controller {
5251

5352
controllers := []controller.Controller{
5453
nodeclasshash.NewController(kubeClient),
5554
nodeclaasstatus.NewController(kubeClient, vSwitchProvider, securitygroupProvider, imageProvider),
56-
nodeclasstermination.NewController(kubeClient, recorder, launchTemplateProvider),
55+
nodeclasstermination.NewController(kubeClient, recorder),
5756
controllerspricing.NewController(pricingProvider),
5857
nodeclaimgarbagecollection.NewController(kubeClient, cloudProvider),
5958
nodeclaimtagging.NewController(kubeClient, instanceProvider),

pkg/controllers/nodeclass/termination/controller.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,17 @@ import (
4141
"sigs.k8s.io/karpenter/pkg/operator/injection"
4242

4343
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/apis/v1alpha1"
44-
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/launchtemplate"
4544
)
4645

4746
type Controller struct {
4847
kubeClient client.Client
4948
recorder events.Recorder
50-
51-
launchTemplateProvider launchtemplate.Provider
5249
}
5350

54-
func NewController(kubeClient client.Client, recorder events.Recorder, launchTemplateProvider launchtemplate.Provider) *Controller {
51+
func NewController(kubeClient client.Client, recorder events.Recorder) *Controller {
5552
return &Controller{
56-
kubeClient: kubeClient,
57-
recorder: recorder,
58-
launchTemplateProvider: launchTemplateProvider,
53+
kubeClient: kubeClient,
54+
recorder: recorder,
5955
}
6056
}
6157

@@ -81,9 +77,6 @@ func (c *Controller) finalize(ctx context.Context, nodeClass *v1alpha1.ECSNodeCl
8177
c.recorder.Publish(WaitingOnNodeClaimTerminationEvent(nodeClass, lo.Map(nodeClaimList.Items, func(nc karpv1.NodeClaim, _ int) string { return nc.Name })))
8278
return reconcile.Result{RequeueAfter: time.Minute * 10}, nil // periodically fire the event
8379
}
84-
if err := c.launchTemplateProvider.DeleteAll(ctx, nodeClass); err != nil {
85-
return reconcile.Result{}, fmt.Errorf("deleting launch templates, %w", err)
86-
}
8780
controllerutil.RemoveFinalizer(nodeClass, v1alpha1.TerminationFinalizer)
8881
if !equality.Semantic.DeepEqual(stored, nodeClass) {
8982
if err := c.kubeClient.Patch(ctx, nodeClass, client.MergeFromWithOptions(stored, client.MergeFromWithOptimisticLock{})); err != nil {

pkg/operator/operator.go

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/imagefamily"
3131
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/instance"
3232
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/instancetype"
33-
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/launchtemplate"
3433
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/pricing"
3534
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/securitygroup"
3635
"github.com/cloudpilot-ai/karpenter-provider-alicloud/pkg/providers/version"
@@ -42,15 +41,14 @@ import (
4241
type Operator struct {
4342
*operator.Operator
4443

45-
InstanceProvider instance.Provider
46-
PricingProvider pricing.Provider
47-
VSwitchProvider vswitch.Provider
48-
SecurityGroupProvider securitygroup.Provider
49-
ImageProvider imagefamily.Provider
50-
ImageResolver imagefamily.Resolver
51-
LaunchTemplateProvider launchtemplate.Provider
52-
VersionProvider version.Provider
53-
InstanceTypeProvider instancetype.Provider
44+
InstanceProvider instance.Provider
45+
PricingProvider pricing.Provider
46+
VSwitchProvider vswitch.Provider
47+
SecurityGroupProvider securitygroup.Provider
48+
ImageProvider imagefamily.Provider
49+
ImageResolver imagefamily.Resolver
50+
VersionProvider version.Provider
51+
InstanceTypeProvider instancetype.Provider
5452
}
5553

5654
func NewOperator(ctx context.Context, operator *operator.Operator) (context.Context, *Operator) {
@@ -80,28 +78,16 @@ func NewOperator(ctx context.Context, operator *operator.Operator) (context.Cont
8078
versionProvider := version.NewDefaultProvider(operator.KubernetesInterface, cache.New(alicache.KubernetesVersionTTL, alicache.DefaultCleanupInterval))
8179
vSwitchProvider := vswitch.NewDefaultProvider(vpcClient, cache.New(alicache.DefaultTTL, alicache.DefaultCleanupInterval), cache.New(alicache.AvailableIPAddressTTL, alicache.DefaultCleanupInterval))
8280
securityGroupProvider := securitygroup.NewDefaultProvider(region, ecsClient, cache.New(alicache.DefaultTTL, alicache.DefaultCleanupInterval))
83-
imageProvider := imagefamily.NewDefaultProvider(region, versionProvider, ecsClient, cache.New(alicache.DefaultTTL, alicache.DefaultCleanupInterval))
81+
imageProvider := imagefamily.NewDefaultProvider(region, ecsClient, cache.New(alicache.DefaultTTL, alicache.DefaultCleanupInterval))
8482
imageResolver := imagefamily.NewDefaultResolver(region, ecsClient, cache.New(alicache.InstanceTypeAvailableDiskTTL, alicache.DefaultCleanupInterval))
85-
launchTemplateProvider := launchtemplate.NewDefaultProvider(
86-
ctx,
87-
cache.New(alicache.LaunchTemplateTTL, alicache.DefaultCleanupInterval),
88-
region,
89-
ecsClient,
90-
imageResolver,
91-
securityGroupProvider,
92-
vSwitchProvider,
93-
nil,
94-
operator.Elected(),
95-
nil,
96-
"",
97-
)
9883

9984
instanceProvider := instance.NewDefaultProvider(
10085
ctx,
10186
region,
87+
"",
10288
ecsClient,
89+
imageResolver,
10390
vSwitchProvider,
104-
launchTemplateProvider,
10591
)
10692

10793
unavailableOfferingsCache := alicache.NewUnavailableOfferings()
@@ -114,14 +100,13 @@ func NewOperator(ctx context.Context, operator *operator.Operator) (context.Cont
114100
return ctx, &Operator{
115101
Operator: operator,
116102

117-
InstanceProvider: instanceProvider,
118-
PricingProvider: pricingProvider,
119-
VSwitchProvider: vSwitchProvider,
120-
SecurityGroupProvider: securityGroupProvider,
121-
ImageProvider: imageProvider,
122-
ImageResolver: imageResolver,
123-
VersionProvider: versionProvider,
124-
LaunchTemplateProvider: launchTemplateProvider,
125-
InstanceTypeProvider: instanceTypeProvider,
103+
InstanceProvider: instanceProvider,
104+
PricingProvider: pricingProvider,
105+
VSwitchProvider: vSwitchProvider,
106+
SecurityGroupProvider: securityGroupProvider,
107+
ImageProvider: imageProvider,
108+
ImageResolver: imageResolver,
109+
VersionProvider: versionProvider,
110+
InstanceTypeProvider: instanceTypeProvider,
126111
}
127112
}

0 commit comments

Comments
 (0)