diff --git a/examples/05-advanced-nodegroups.yaml b/examples/05-advanced-nodegroups.yaml index d84e9b1806..754c4a36f8 100644 --- a/examples/05-advanced-nodegroups.yaml +++ b/examples/05-advanced-nodegroups.yaml @@ -1,5 +1,5 @@ # An advanced example of ClusterConfig object with customised nodegroups: ---- +--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig @@ -42,6 +42,17 @@ nodeGroups: nodegroup-type: very-special-science-workloads classicLoadBalancerNames: - ng3-classic-load-balancer + asgMetricsCollection: + - granularity: 1Minute + metrics: + - GroupMinSize + - GroupMaxSize + - GroupDesiredCapacity + - GroupInServiceInstances + - GroupPendingInstances + - GroupStandbyInstances + - GroupTerminatingInstances + - GroupTotalInstances taints: special: "true:NoSchedule" privateNetworking: true diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 60aa18c6cf..0126657197 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -619,6 +619,8 @@ type NodeGroup struct { MinSize *int `json:"minSize,omitempty"` // +optional MaxSize *int `json:"maxSize,omitempty"` + // +optional + ASGMetricsCollection []MetricsCollection `json:"asgMetricsCollection,omitempty"` // +optional EBSOptimized *bool `json:"ebsOptimized,omitempty"` @@ -787,6 +789,15 @@ type ( } ) +// MetricsCollection used by the scaling config +// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-metricscollection.html +type MetricsCollection struct { + // +required + Granularity string `json:"granularity"` + // +optional + Metrics []string `json:"metrics,omitempty"` +} + // ScalingConfig defines the scaling config type ScalingConfig struct { // +optional diff --git a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go index 363dbacdd9..7435ffadb4 100644 --- a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go +++ b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go @@ -590,6 +590,27 @@ func (in *ManagedNodeGroup) DeepCopy() *ManagedNodeGroup { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetricsCollection) DeepCopyInto(out *MetricsCollection) { + *out = *in + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsCollection. +func (in *MetricsCollection) DeepCopy() *MetricsCollection { + if in == nil { + return nil + } + out := new(MetricsCollection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Network) DeepCopyInto(out *Network) { *out = *in @@ -650,6 +671,13 @@ func (in *NodeGroup) DeepCopyInto(out *NodeGroup) { *out = new(int) **out = **in } + if in.ASGMetricsCollection != nil { + in, out := &in.ASGMetricsCollection, &out.ASGMetricsCollection + *out = make([]MetricsCollection, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.EBSOptimized != nil { in, out := &in.EBSOptimized, &out.EBSOptimized *out = new(bool) diff --git a/pkg/cfn/builder/api_test.go b/pkg/cfn/builder/api_test.go index 2df9add3be..9079bf7bca 100644 --- a/pkg/cfn/builder/api_test.go +++ b/pkg/cfn/builder/api_test.go @@ -73,6 +73,7 @@ type Properties struct { VPCZoneIdentifier interface{} LoadBalancerNames []string + MetricsCollection []map[string]interface{} TargetGroupARNs []string DesiredCapacity, MinSize, MaxSize string @@ -811,7 +812,15 @@ var _ = Describe("CloudFormation template builder API", func() { Context("NodeGroupAutoScaling", func() { cfg, ng := newClusterConfigAndNodegroup(true) - + ng.ASGMetricsCollection = []api.MetricsCollection{ + { + Granularity: "1Minute", + Metrics: []string{ + "GroupMinSize", + "GroupMaxSize", + }, + }, + } ng.ClassicLoadBalancerNames = []string{"clb-1", "clb-2"} ng.TargetGroupARNs = []string{"tg-arn-1", "tg-arn-2"} @@ -916,6 +925,21 @@ var _ = Describe("CloudFormation template builder API", func() { Expect(ng.Properties.LoadBalancerNames).To(Equal([]string{"clb-1", "clb-2"})) }) + It("should have metrics collections set", func() { + Expect(ngTemplate.Resources).To(HaveKey("NodeGroup")) + ng := ngTemplate.Resources["NodeGroup"] + Expect(ng).ToNot(BeNil()) + Expect(ng.Properties).ToNot(BeNil()) + + Expect(ng.Properties.MetricsCollection).To(HaveLen(1)) + var metricsCollection map[string]interface{} = ng.Properties.MetricsCollection[0] + Expect(metricsCollection).To(HaveKey("Granularity")) + Expect(metricsCollection).To(HaveKey("Metrics")) + Expect(metricsCollection["Granularity"]).To(Equal("1Minute")) + Expect(metricsCollection["Metrics"]).To(ContainElement("GroupMinSize")) + Expect(metricsCollection["Metrics"]).To(ContainElement("GroupMaxSize")) + }) + It("should have target groups ARNs set", func() { Expect(ngTemplate.Resources).To(HaveKey("NodeGroup")) ng := ngTemplate.Resources["NodeGroup"] diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index cc799cebcc..9df4c76dac 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -274,6 +274,9 @@ func nodeGroupResource(launchTemplateName *gfn.Value, vpcZoneIdentifier interfac if ng.MaxSize != nil { ngProps["MaxSize"] = fmt.Sprintf("%d", *ng.MaxSize) } + if len(ng.ASGMetricsCollection) > 0 { + ngProps["MetricsCollection"] = metricsCollectionResource(ng.ASGMetricsCollection) + } if len(ng.ClassicLoadBalancerNames) > 0 { ngProps["LoadBalancerNames"] = ng.ClassicLoadBalancerNames } @@ -345,3 +348,18 @@ func mixedInstancesPolicy(launchTemplateName *gfn.Value, ng *api.NodeGroup) *map return &policy } + +func metricsCollectionResource(asgMetricsCollection []api.MetricsCollection) []map[string]interface{} { + var metricsCollections []map[string]interface{} + for _, m := range asgMetricsCollection { + newCollection := make(map[string]interface{}) + + var metrics []string + metrics = append(metrics, m.Metrics...) + newCollection["Metrics"] = metrics + newCollection["Granularity"] = m.Granularity + + metricsCollections = append(metricsCollections, newCollection) + } + return metricsCollections +} diff --git a/userdocs/src/usage/eks-managed-nodes.md b/userdocs/src/usage/eks-managed-nodes.md index c051371b7a..eb76abcf23 100644 --- a/userdocs/src/usage/eks-managed-nodes.md +++ b/userdocs/src/usage/eks-managed-nodes.md @@ -179,6 +179,7 @@ the provisioned Autoscaling Group like in unmanaged nodegroups. - Control over the node bootstrapping process and customization of the kubelet are not supported. This includes the following fields: `classicLoadBalancerNames`, `maxPodsPerNode`, `taints`, `targetGroupARNs`, `preBootstrapCommands`, `overrideBootstrapCommand`, `clusterDNS` and `kubeletExtraConfig`. +- No support for enabling metrics on AutoScalingGroups using `asgMetricsCollection` ## Note for eksctl versions below 0.12.0 - For clusters upgraded from EKS 1.13 to EKS 1.14, managed nodegroups will not be able to communicate with unmanaged diff --git a/userdocs/src/usage/managing-nodegroups.md b/userdocs/src/usage/managing-nodegroups.md index e1d05a7d4e..6827c61d11 100644 --- a/userdocs/src/usage/managing-nodegroups.md +++ b/userdocs/src/usage/managing-nodegroups.md @@ -77,6 +77,17 @@ nodeGroups: classicLoadBalancerNames: - dev-clb-1 - dev-clb-2 + asgMetricsCollection: + - granularity: 1Minute + metrics: + - GroupMinSize + - GroupMaxSize + - GroupDesiredCapacity + - GroupInServiceInstances + - GroupPendingInstances + - GroupStandbyInstances + - GroupTerminatingInstances + - GroupTotalInstances - name: ng-2-api labels: { role: api } instanceType: m5.2xlarge diff --git a/userdocs/src/usage/schema.md b/userdocs/src/usage/schema.md index 2b4194a38b..279fa2207e 100755 --- a/userdocs/src/usage/schema.md +++ b/userdocs/src/usage/schema.md @@ -353,6 +353,18 @@ ManagedNodeGroup: - ScalingConfig - privateNetworking type: object +MetricsCollection: + additionalProperties: false + properties: + granularity: + type: string + metrics: + items: + type: string + type: array + required: + - granularity + type: object Network: additionalProperties: false properties: @@ -369,6 +381,11 @@ NodeGroup: type: string amiFamily: type: string + asgMetricsCollection: + items: + $ref: '#/definitions/MetricsCollection' + $schema: http://json-schema.org/draft-04/schema# + type: array availabilityZones: items: type: string