From b099403fcf56d54b39bb8b6d27874d1f1a8d14eb Mon Sep 17 00:00:00 2001 From: Mahmoud Saada Date: Mon, 20 Apr 2020 09:02:12 -0400 Subject: [PATCH] add support for metrics collection in scaling config add name to humans.txt reset go.mod make metrics optional add cloudformation mapping regenerate fix if statement apply pr review changes apply pr review changes WIP update schema and generated deepcopy add tests and update docs cleanup test comments --- examples/05-advanced-nodegroups.yaml | 13 ++++++++- pkg/apis/eksctl.io/v1alpha5/types.go | 11 ++++++++ .../v1alpha5/zz_generated.deepcopy.go | 28 +++++++++++++++++++ pkg/cfn/builder/api_test.go | 26 ++++++++++++++++- pkg/cfn/builder/nodegroup.go | 18 ++++++++++++ userdocs/src/usage/eks-managed-nodes.md | 1 + userdocs/src/usage/managing-nodegroups.md | 11 ++++++++ userdocs/src/usage/schema.md | 17 +++++++++++ 8 files changed, 123 insertions(+), 2 deletions(-) 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