AWSTemplateFormatVersion: 2010-09-09 Description: Deploys EKS nodes into an existing VPC (qs-1p7nknoid). Metadata: AutoInstance: NodeInstanceType: InstanceFilters: - [[PV], '!=', SupportedVirtualizationTypes] AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network configuration Parameters: - VPCID - Subnet1ID - Subnet2ID - Subnet3ID - HttpProxy - Label: default: Amazon EKS basic node group configuration Parameters: - EKSClusterName - KubernetesVersion - CreateNodeGroup - NodeGroupName - NodeGroupType - OndemandPercentage - KeyPairName - NodeSecurityGroupId - Label: default: Node group size configuration Parameters: - NumberOfNodes - MaxNumberOfNodes - Label: default: Node group instance configuration Parameters: - NodeInstanceFamily - NodeInstanceType - NodeInstanceType2 - NodeInstanceType3 - NodeInstanceType4 - NodeGroupOS - CustomAmiId - NodeVolumeSize - Labels - Label: default: Launch template configuration Parameters: - LaunchTemplateId - LaunchTemplateVersion - Label: default: Windows node group configuration Parameters: - WindowsVersion - WindowsEdition - Label: default: Advanced node group configuration Parameters: - Taints - EC2MetadataPutResponseHopLimit - EC2MetadataHttpTokens - MaxNodesUnavailable - MaxNodesUnavailablePercentage ParameterLabels: KeyPairName: default: SSH key name NodeSecurityGroupId: default: Security group ID NodeGroupOS: default: Operating system VPCID: default: VPC ID Subnet1ID: default: Subnet 1 ID Subnet2ID: default: Subnet 2 ID Subnet3ID: default: Subnet 3 ID EKSClusterName: default: EKS cluster name KubernetesVersion: default: Kubernetes version NodeGroupType: default: Type OndemandPercentage: default: On-demand percentage NodeInstanceFamily: default: Instance family NodeInstanceType: default: Instance type 1 NodeInstanceType2: default: Instance type 2 NodeInstanceType3: default: Instance type 3 NodeInstanceType4: default: Instance type 4 NumberOfNodes: default: Number of nodes MaxNumberOfNodes: default: Maximum number of nodes NodeGroupName: default: Node group name NodeVolumeSize: default: Node volume size CustomAmiId: default: Custom AMI id HttpProxy: default: HTTP proxy CreateNodeGroup: default: Create node group WindowsVersion: default: Version WindowsEdition: default: Edition LaunchTemplateId: default: ID LaunchTemplateVersion: default: Version Labels: default: Labels Taints: default: Taints EC2MetadataPutResponseHopLimit: defaults: Amazon EC2 metadata put response hop limit EC2MetadataHttpTokens: defaults: Amazon EC2 metadata HTTP tokens MaxNodesUnavailable: default: Max nodes unavailable MaxNodesUnavailablePercentage: default: Max nodes unavailable percentage Parameters: KeyPairName: Description: >- Name of an existing EC2 key pair. All instances will launch with this key pair. Ignored if "Custom launch template" is provided. If left blank, no keypair will be associsated with the nodes. Type: String Default: '' NodeGroupOS: Type: String Description: >- The Linux distribution for the AMI to be used for the node instances. Ignored if "Custom launch template" is provided. AllowedValues: [Amazon Linux 2, Bottlerocket, Windows] Default: Amazon Linux 2 CustomAmiId: Type: String Description: >- (Optional) If an AMI id is specified here it will be used in stead of the ami determined from the OS/region. Default: '' VPCID: Type: AWS::EC2::VPC::Id Description: >- ID of your existing VPC (example: vpc-0343606e). Subnet1ID: Type: AWS::EC2::Subnet::Id Description: >- ID of subnet 1 for the node group (example: subnet-a0246123). Subnet2ID: Type: String Description: >- (Optional) ID of subnet 2 for the node group (example: subnet-b1f432cd). Must be in the same VPC as "Subnet 1 ID". Default: '' Subnet3ID: Type: String Description: >- (Optional) ID of subnet 3 for the node group (example: subnet-b1f4a2cd). Must be in the same VPC as "Subnet 1 ID". Default: '' NodeInstanceType: Type: String Description: Type of EC2 instance for the node instances. AllowedValues: [ a1.medium, a1.large, a1.xlarge, a1.2xlarge, a1.4xlarge, a1.metal, c1.medium, c1.xlarge, c3.large, c3.xlarge, c3.2xlarge, c3.4xlarge, c3.8xlarge, c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, c5.large, c5.xlarge, c5.2xlarge, c5.4xlarge, c5.9xlarge, c5.12xlarge, c5.18xlarge, c5.24xlarge, c5.metal, c5a.large, c5a.xlarge, c5a.2xlarge, c5a.4xlarge, c5a.8xlarge, c5a.12xlarge, c5a.16xlarge, c5a.24xlarge, c5ad.large, c5ad.xlarge, c5ad.2xlarge, c5ad.4xlarge, c5ad.8xlarge, c5ad.12xlarge, c5ad.16xlarge, c5ad.24xlarge, c5d.large, c5d.xlarge, c5d.2xlarge, c5d.4xlarge, c5d.9xlarge, c5d.12xlarge, c5d.18xlarge, c5d.24xlarge, c5d.metal, c5n.large, c5n.xlarge, c5n.2xlarge, c5n.4xlarge, c5n.9xlarge, c5n.18xlarge, c5n.metal, c6a.large, c6a.xlarge, c6a.2xlarge, c6a.4xlarge, c6a.8xlarge, c6a.12xlarge, c6a.16xlarge, c6a.24xlarge, c6a.32xlarge, c6a.48xlarge, c6a.metal, c6g.medium, c6g.large, c6g.xlarge, c6g.2xlarge, c6g.4xlarge, c6g.8xlarge, c6g.12xlarge, c6g.16xlarge, c6g.metal, c6gd.medium, c6gd.large, c6gd.xlarge, c6gd.2xlarge, c6gd.4xlarge, c6gd.8xlarge, c6gd.12xlarge, c6gd.16xlarge, c6gd.metal, c6gn.medium, c6gn.large, c6gn.xlarge, c6gn.2xlarge, c6gn.4xlarge, c6gn.8xlarge, c6gn.12xlarge, c6gn.16xlarge, c6i.large, c6i.xlarge, c6i.2xlarge, c6i.4xlarge, c6i.8xlarge, c6i.12xlarge, c6i.16xlarge, c6i.24xlarge, c6i.32xlarge, c6i.metal, c6id.large, c6id.xlarge, c6id.2xlarge, c6id.4xlarge, c6id.8xlarge, c6id.12xlarge, c6id.16xlarge, c6id.24xlarge, c6id.32xlarge, c6id.metal, c7g.medium, c7g.large, c7g.xlarge, c7g.2xlarge, c7g.4xlarge, c7g.8xlarge, c7g.12xlarge, c7g.16xlarge, cc1.4xlarge, cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, d2.xlarge, d2.2xlarge, d2.4xlarge, d2.8xlarge, d3.xlarge, d3.2xlarge, d3.4xlarge, d3.8xlarge, d3en.xlarge, d3en.2xlarge, d3en.4xlarge, d3en.6xlarge, d3en.8xlarge, d3en.12xlarge, dl1.24xlarge, f1.2xlarge, f1.4xlarge, f1.16xlarge, g2.2xlarge, g2.8xlarge, g3.4xlarge, g3.8xlarge, g3.16xlarge, g3s.xlarge, g4ad.xlarge, g4ad.2xlarge, g4ad.4xlarge, g4ad.8xlarge, g4ad.16xlarge, g4dn.xlarge, g4dn.2xlarge, g4dn.4xlarge, g4dn.8xlarge, g4dn.12xlarge, g4dn.16xlarge, g4dn.metal, g5.xlarge, g5.2xlarge, g5.4xlarge, g5.8xlarge, g5.12xlarge, g5.16xlarge, g5.24xlarge, g5.48xlarge, g5g.xlarge, g5g.2xlarge, g5g.4xlarge, g5g.8xlarge, g5g.16xlarge, g5g.metal, h1.2xlarge, h1.4xlarge, h1.8xlarge, h1.16xlarge, hi1.4xlarge, hpc6a.48xlarge, hpc6id.32xlarge, hs1.8xlarge, i2.xlarge, i2.2xlarge, i2.4xlarge, i2.8xlarge, i3.large, i3.xlarge, i3.2xlarge, i3.4xlarge, i3.8xlarge, i3.16xlarge, i3.metal, i3en.large, i3en.xlarge, i3en.2xlarge, i3en.3xlarge, i3en.6xlarge, i3en.12xlarge, i3en.24xlarge, i3en.metal, i4i.large, i4i.xlarge, i4i.2xlarge, i4i.4xlarge, i4i.8xlarge, i4i.16xlarge, i4i.32xlarge, i4i.metal, im4gn.large, im4gn.xlarge, im4gn.2xlarge, im4gn.4xlarge, im4gn.8xlarge, im4gn.16xlarge, inf1.xlarge, inf1.2xlarge, inf1.6xlarge, inf1.24xlarge, is4gen.medium, is4gen.large, is4gen.xlarge, is4gen.2xlarge, is4gen.4xlarge, is4gen.8xlarge, m1.small, m1.medium, m1.large, m1.xlarge, m2.xlarge, m2.2xlarge, m2.4xlarge, m3.medium, m3.large, m3.xlarge, m3.2xlarge, m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge, m4.16xlarge, m5.large, m5.xlarge, m5.2xlarge, m5.4xlarge, m5.8xlarge, m5.12xlarge, m5.16xlarge, m5.24xlarge, m5.metal, m5a.large, m5a.xlarge, m5a.2xlarge, m5a.4xlarge, m5a.8xlarge, m5a.12xlarge, m5a.16xlarge, m5a.24xlarge, m5ad.large, m5ad.xlarge, m5ad.2xlarge, m5ad.4xlarge, m5ad.8xlarge, m5ad.12xlarge, m5ad.16xlarge, m5ad.24xlarge, m5d.large, m5d.xlarge, m5d.2xlarge, m5d.4xlarge, m5d.8xlarge, m5d.12xlarge, m5d.16xlarge, m5d.24xlarge, m5d.metal, m5dn.large, m5dn.xlarge, m5dn.2xlarge, m5dn.4xlarge, m5dn.8xlarge, m5dn.12xlarge, m5dn.16xlarge, m5dn.24xlarge, m5dn.metal, m5n.large, m5n.xlarge, m5n.2xlarge, m5n.4xlarge, m5n.8xlarge, m5n.12xlarge, m5n.16xlarge, m5n.24xlarge, m5n.metal, m5zn.large, m5zn.xlarge, m5zn.2xlarge, m5zn.3xlarge, m5zn.6xlarge, m5zn.12xlarge, m5zn.metal, m6a.large, m6a.xlarge, m6a.2xlarge, m6a.4xlarge, m6a.8xlarge, m6a.12xlarge, m6a.16xlarge, m6a.24xlarge, m6a.32xlarge, m6a.48xlarge, m6a.metal, m6g.medium, m6g.large, m6g.xlarge, m6g.2xlarge, m6g.4xlarge, m6g.8xlarge, m6g.12xlarge, m6g.16xlarge, m6g.metal, m6gd.medium, m6gd.large, m6gd.xlarge, m6gd.2xlarge, m6gd.4xlarge, m6gd.8xlarge, m6gd.12xlarge, m6gd.16xlarge, m6gd.metal, m6i.large, m6i.xlarge, m6i.2xlarge, m6i.4xlarge, m6i.8xlarge, m6i.12xlarge, m6i.16xlarge, m6i.24xlarge, m6i.32xlarge, m6i.metal, m6id.large, m6id.xlarge, m6id.2xlarge, m6id.4xlarge, m6id.8xlarge, m6id.12xlarge, m6id.16xlarge, m6id.24xlarge, m6id.32xlarge, m6id.metal, # mac1.metal, p2.xlarge, p2.8xlarge, p2.16xlarge, p3.2xlarge, p3.8xlarge, p3.16xlarge, p3dn.24xlarge, p4d.24xlarge, p4de.24xlarge, r3.large, r3.xlarge, r3.2xlarge, r3.4xlarge, r3.8xlarge, r4.large, r4.xlarge, r4.2xlarge, r4.4xlarge, r4.8xlarge, r4.16xlarge, r5.large, r5.xlarge, r5.2xlarge, r5.4xlarge, r5.8xlarge, r5.12xlarge, r5.16xlarge, r5.24xlarge, r5.metal, r5a.large, r5a.xlarge, r5a.2xlarge, r5a.4xlarge, r5a.8xlarge, r5a.12xlarge, r5a.16xlarge, r5a.24xlarge, r5ad.large, r5ad.xlarge, r5ad.2xlarge, r5ad.4xlarge, r5ad.8xlarge, r5ad.12xlarge, r5ad.16xlarge, r5ad.24xlarge, r5b.large, r5b.xlarge, r5b.2xlarge, r5b.4xlarge, r5b.8xlarge, r5b.12xlarge, r5b.16xlarge, r5b.24xlarge, r5b.metal, r5d.large, r5d.xlarge, r5d.2xlarge, r5d.4xlarge, r5d.8xlarge, r5d.12xlarge, r5d.16xlarge, r5d.24xlarge, r5d.metal, r5dn.large, r5dn.xlarge, r5dn.2xlarge, r5dn.4xlarge, r5dn.8xlarge, r5dn.12xlarge, r5dn.16xlarge, r5dn.24xlarge, r5dn.metal, r5n.large, r5n.xlarge, r5n.2xlarge, r5n.4xlarge, r5n.8xlarge, r5n.12xlarge, r5n.16xlarge, r5n.24xlarge, r5n.metal, r6a.large, r6a.xlarge, r6a.2xlarge, r6a.4xlarge, r6a.8xlarge, r6a.12xlarge, r6a.16xlarge, r6a.24xlarge, r6a.32xlarge, r6a.48xlarge, r6a.metal, r6ad.large, r6ad.xlarge, r6ad.2xlarge, r6ad.4xlarge, r6ad.8xlarge, r6ad.12xlarge, r6ad.16xlarge, r6ad.24xlarge, r6ad.32xlarge, r6ad.48xlarge, r6ad.metal, r6g.medium, r6g.large, r6g.xlarge, r6g.2xlarge, r6g.4xlarge, r6g.8xlarge, r6g.12xlarge, r6g.16xlarge, r6g.metal, r6gd.medium, r6gd.large, r6gd.xlarge, r6gd.2xlarge, r6gd.4xlarge, r6gd.8xlarge, r6gd.12xlarge, r6gd.16xlarge, r6gd.metal, r6i.large, r6i.xlarge, r6i.2xlarge, r6i.4xlarge, r6i.8xlarge, r6i.12xlarge, r6i.16xlarge, r6i.24xlarge, r6i.32xlarge, r6i.metal, r6id.large, r6id.xlarge, r6id.2xlarge, r6id.4xlarge, r6id.8xlarge, r6id.12xlarge, r6id.16xlarge, r6id.24xlarge, r6id.32xlarge, r6id.metal, t1.micro, t2.nano, t2.micro, t2.small, t2.medium, t2.large, t2.xlarge, t2.2xlarge, t3.nano, t3.micro, t3.small, t3.medium, t3.large, t3.xlarge, t3.2xlarge, t3a.nano, t3a.micro, t3a.small, t3a.medium, t3a.large, t3a.xlarge, t3a.2xlarge, t4g.nano, t4g.micro, t4g.small, t4g.medium, t4g.large, t4g.xlarge, t4g.2xlarge, u-6tb1.56xlarge, u-6tb1.112xlarge, u-6tb1.metal, u-9tb1.112xlarge, u-9tb1.metal, u-12tb1.112xlarge, u-12tb1.metal, u-18tb1.metal, u-24tb1.metal, vt1.3xlarge, vt1.6xlarge, vt1.24xlarge, x1.16xlarge, x1.32xlarge, x1e.xlarge, x1e.2xlarge, x1e.4xlarge, x1e.8xlarge, x1e.16xlarge, x1e.32xlarge, x2gd.medium, x2gd.large, x2gd.xlarge, x2gd.2xlarge, x2gd.4xlarge, x2gd.8xlarge, x2gd.12xlarge, x2gd.16xlarge, x2gd.metal, x2idn.16xlarge, x2idn.24xlarge, x2idn.32xlarge, x2idn.metal, x2iedn.xlarge, x2iedn.2xlarge, x2iedn.4xlarge, x2iedn.8xlarge, x2iedn.16xlarge, x2iedn.24xlarge, x2iedn.32xlarge, x2iedn.metal, x2iezn.2xlarge, x2iezn.4xlarge, x2iezn.6xlarge, x2iezn.8xlarge, x2iezn.12xlarge, x2iezn.metal, z1d.large, z1d.xlarge, z1d.2xlarge, z1d.3xlarge, z1d.6xlarge, z1d.12xlarge, z1d.metal ] ConstraintDescription: Must be a valid EC2 instance type Default: t3.medium NodeInstanceType2: Type: String Description: >- (Optional) Only applies if "Node group type" is set to "Unmanaged". 2nd type of EC2 instance for the node instances. Default: '' NodeInstanceType3: Type: String Description: >- (Optional) Only applies if "Node group type" is set to "Unmanaged". 3rd type of EC2 instance for the node instances. Default: '' NodeInstanceType4: Type: String Description: >- (Optional) Only applies if "Node group type" is set to "Unmanaged". 4th type of EC2 instance for the node instances. Default: '' NumberOfNodes: Type: Number Description: Number of EKS node instances. Default: 3 MaxNumberOfNodes: Type: String Description: >- (Optional) The maximum number of Amazon EKS node instances, if left blank will be set to the same value as NumberOfNodes. Default: '' NodeGroupName: Type: String Description: Name for EKS node group. Default: Default NodeVolumeSize: Type: String Description: Size for node volumes. Default: 20 EKSClusterName: Type: String Description: Name of the EKS cluster to join. KubernetesVersion: Type: String Description: Kubernetes control plane version. AllowedValues: [1.24, 1.23, 1.22] Default: 1.24 HttpProxy: Type: String Description: >- (Optional) Specify the host name for an HTTP proxy to use for outbound internet access. Default: '' NodeGroupType: Type: String Description: >- Choose "Unmanaged" to create an auto-scaling group without using the EKS managed node groups feature. AllowedValues: [Managed, Unmanaged] Default: Managed NodeInstanceFamily: Type: String Description: >- Choose "ARM" to use an ARM based AMI, choose "GPU" to use an AMI that supports GPU and Inferentia based instance types. Ignored if "Custom launch template" is provided. AllowedValues: [Standard, ARM, GPU] Default: Standard LaunchTemplateId: Type: String Description: >- (Optional) ID of an existing launch template to use when creating the node group. Default: '' LaunchTemplateVersion: Type: String Description: >- Must be specified if "Launch template ID" is provided. Cannot be "$Latest" or "$Default". This valiue sets the launch template version for the node group to use. Default: '' Labels: Type: String Description: >- (Optional) Comma separated list of = pairs representing node labels to assign to the node group. Ignored if "Custom launch template" is provided. Default: '' Taints: Type: String Description: >- (Optional) Comma separated list of =: representing node taints to assign to the node group. Ignored if "Custom launch template" is provided. Default: '' NodeSecurityGroupId: Type: String Description: >- (Optional) Provide the id of a Security Group to use for this node group. If not specified, the cluster Security Group will be used. Default: '' OndemandPercentage: Type: Number Description: >- Only applies if "Node group type" is set to "Unmanaged". Set the percentage of on-demand instances and spot instances. With the default of 100, the percentages are 100% for on demand instances and 0% for spot instances. Default: 100 CreateNodeGroup: Type: String Description: >- If 'No' the stack will create just the Security Group skipping the node group. This is useful if you manage the node group with third party integration, such as Spot.io. AllowedValues: ['Yes', 'No'] Default: 'Yes' WindowsEdition: Type: String Description: The edition of Windows AMI to use for Windows Nodegroups. AllowedValues: [Core, Full] Default: Core WindowsVersion: Type: String Description: The version of windows to use for Windows Nodegroups. AllowedValues: [2022] Default: 2022 EC2MetadataPutResponseHopLimit: Type: String Description: >- The desired HTTP PUT response hop limit for instance metadata requests. The larger the number, the further instance metadata requests can travel. Default: 2 EC2MetadataHttpTokens: Type: String Description: >- If set to "optional" pods will be able to use the node's IAM instance profile. If set to "required" amd "EC2MetadataPutResponseHopLimit" is set to 1, pods will not be able to access the nodes IAM role. If set to "required" amd "EC2MetadataPutResponseHopLimit" is set greater than 1 pods must send a signed token header with any instance metadata retrieval requests. AllowedValues: [optional, required] Default: required MaxNodesUnavailable: Type: Number Description: >- The maximum number of nodes unavailable at once during a version update. Nodes will be updated in parallel. If the "max nodes unavailable percentage" parameter is set to a value greater than 0, this parameter is ignored. MinValue: 1 MaxValue: 100 Default: 1 MaxNodesUnavailablePercentage: Type: Number Description: >- The maximum percentage of nodes unavailable during a version update. This percentage of nodes will be updated in parallel. If set to 0, this parameter is ignored. MinValue: 0 MaxValue: 100 Default: 0 Conditions: IsAL2: !Equals [!Ref NodeGroupOS, Amazon Linux 2] IsWindows: !Equals [!Ref NodeGroupOS, Windows] IsManaged: !Equals [!Ref NodeGroupType, Managed] IsUnmanaged: !Equals [!Ref NodeGroupType, Unmanaged] IsArm: !Equals [!Ref NodeInstanceFamily, ARM] IsGpu: !Equals [!Ref NodeInstanceFamily, GPU] UseClusterNodeSecurityGroup: !Equals [!Ref NodeSecurityGroupId, ''] MaxNodesDefined: !Not [!Equals [!Ref MaxNumberOfNodes, '']] 1Type: !Equals [!Ref NodeInstanceType2, ''] 2Type: !Not [!Equals [!Ref NodeInstanceType2, '']] 3Type: !Not [!Equals [!Ref NodeInstanceType3, '']] 4Type: !Not [!Equals [!Ref NodeInstanceType4, '']] CreateLaunchTemplate: !Equals [!Ref LaunchTemplateId, ''] 3AZDeployment: !Not [!Equals [!Ref Subnet3ID, '']] 2AZDeployment: !Not [!Equals [!Ref Subnet2ID, '']] IsSingleInstance: !Equals [!Ref NumberOfNodes, 1] EnableProxy: !Not [!Equals [!Ref HttpProxy, '']] AddExtraArgs: !Or [!Not [!Equals [!Ref Labels, '']], !Not [!Equals [!Ref Taints, '']]] AddLabels: !Not [!Equals [!Ref Labels, '']] AddTaints: !Not [!Equals [!Ref Taints, '']] IsBottlerocket: !Equals [!Ref NodeGroupOS, Bottlerocket] UseCustomAmi: !Not [!Equals [!Ref CustomAmiId, '']] CreateNodeGroup: !Equals [!Ref CreateNodeGroup, 'Yes'] CreateManagedNodeGroup: !And [!Condition IsManaged, !Condition CreateNodeGroup] CreateUnmanagedNodeGroup: !And [!Condition IsUnmanaged, !Condition CreateNodeGroup] UseKeyPair: !Not [!Equals [!Ref KeyPairName, '']] UseMaxNodesUnavailablePercentage: !Not [!Equals [!Ref MaxNodesUnavailablePercentage, 0]] UseMaxNodesUnavailable: !And - !Not [!Condition UseMaxNodesUnavailablePercentage] - !Not [!Equals [!Ref MaxNodesUnavailable, 0]] Resources: GetVpcCidr: Type: Custom::ResourceReader Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub >- ec2 describe-vpcs --vpc-id ${VPCID} --query 'Vpcs[0].{CidrBlock: CidrBlock}' IdField: CidrBlock GetNodeRoleArn: Type: Custom::ResourceReader Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub - iam get-role --role-name ${NodeInstanceRoleName} --query 'Role' - NodeInstanceRoleName: !Sub - eks-quickstart-${Suffix} - Suffix: !If [IsManaged, ManagedNodeInstance, UnmanagedNodeInstance] IdField: Arn GetNodeInstanceProfileArn: Type: Custom::ResourceReader Condition: IsUnmanaged Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub - >- iam list-instance-profiles --query 'InstanceProfiles[].{role: Roles[0].RoleName, arn: Arn}[?role==`${NodeInstanceRoleName}`] | [0]' - NodeInstanceRoleName: !Sub - eks-quickstart-${Suffix} - Suffix: !If [IsManaged, ManagedNodeInstance, UnmanagedNodeInstance] IdField: arn GetClusterEndpoint: Type: Custom::ResourceReader Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub >- eks describe-cluster --name ${EKSClusterName} --query '{Endpoint: cluster.endpoint, CaData: cluster.certificateAuthority.data}' IdField: Endpoint GetClusterNodeSecurityGroup: Type: Custom::ResourceReader Condition: UseClusterNodeSecurityGroup Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub >- eks describe-cluster --name ${EKSClusterName} --query '{SGID: cluster.resourcesVpcConfig.clusterSecurityGroupId}' IdField: SGID CleanupNodeSecurityGroupDependencies: Type: Custom::CleanupSecurityGroupDependencies Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-CleanupSecurityGroupDependencies SecurityGroups: [!If [UseClusterNodeSecurityGroup, !Ref GetClusterNodeSecurityGroup, !Ref NodeSecurityGroupId]] GetManagedASG: Type: Custom::ResourceReader Condition: CreateManagedNodeGroup DependsOn: ManagedNodeGroup Properties: ServiceToken: !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader AwsCliCommand: !Sub >- autoscaling describe-auto-scaling-groups --query 'AutoScalingGroups[? Tags[? Key==`eks:cluster-name` && Value==`${EKSClusterName}`] && Tags[? Key==`eks:nodegroup-name` && Value==`${ManagedNodeGroup.NodegroupName}`]] | [0] | {Id: AutoScalingGroupName}' IdField: Id UnmanagedASG: Type: AWS::AutoScaling::AutoScalingGroup Condition: CreateUnmanagedNodeGroup DependsOn: [CleanupNodeSecurityGroupDependencies] Properties: DesiredCapacity: !Ref NumberOfNodes MaxSize: !If [MaxNodesDefined, !Ref MaxNumberOfNodes, !Ref NumberOfNodes] MinSize: !Ref NumberOfNodes Tags: - Key: !Sub kubernetes.io/cluster/${EKSClusterName} Value: owned PropagateAtLaunch: true - Key: k8s.io/cluster-autoscaler/enabled Value: 'true' PropagateAtLaunch: true - Key: !Sub k8s.io/cluster-autoscaler/${EKSClusterName} Value: owned PropagateAtLaunch: true VPCZoneIdentifier: !If - 3AZDeployment - [!Ref Subnet1ID, !Ref Subnet2ID, !Ref Subnet3ID] - !If [2AZDeployment, [!Ref Subnet1ID, !Ref Subnet2ID], [!Ref Subnet1ID]] MixedInstancesPolicy: LaunchTemplate: LaunchTemplateSpecification: LaunchTemplateId: !If [CreateLaunchTemplate, !Ref NodeLaunchTemplate, !Ref LaunchTemplateId] Version: !If [CreateLaunchTemplate, !GetAtt NodeLaunchTemplate.LatestVersionNumber, !Ref LaunchTemplateVersion] Overrides: !If - 1Type - !Ref AWS::NoValue - - InstanceType: !Ref NodeInstanceType - InstanceType: !If [2Type, !Ref NodeInstanceType2, !Ref AWS::NoValue] - InstanceType: !If [3Type, !Ref NodeInstanceType3, !Ref AWS::NoValue] - InstanceType: !If [4Type, !Ref NodeInstanceType4, !Ref AWS::NoValue] InstancesDistribution: OnDemandPercentageAboveBaseCapacity: !Ref OndemandPercentage SpotInstancePools: !If [1Type, 1, !If [2Type, 2, !If [3Type, 3, 4]]] CreationPolicy: ResourceSignal: !If [IsBottlerocket, !Ref AWS::NoValue, { Count: !Ref NumberOfNodes, Timeout: PT15M }] UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: !If [IsSingleInstance, 0, 1] MaxBatchSize: 1 WaitOnResourceSignals: !If [IsBottlerocket, false, true] PauseTime: !If [IsBottlerocket, PT3M, PT15M] ManagedNodeGroup: Type: AWS::EKS::Nodegroup Condition: CreateManagedNodeGroup DependsOn: [CleanupNodeSecurityGroupDependencies] Properties: ClusterName: !Ref EKSClusterName LaunchTemplate: Id: !If [CreateLaunchTemplate, !Ref NodeLaunchTemplate, !Ref LaunchTemplateId] Version: !If [CreateLaunchTemplate, !GetAtt NodeLaunchTemplate.LatestVersionNumber, !Ref LaunchTemplateVersion] NodegroupName: !Ref NodeGroupName NodeRole: !Ref GetNodeRoleArn ScalingConfig: DesiredSize: !Ref NumberOfNodes MaxSize: !If [MaxNodesDefined, !Ref MaxNumberOfNodes, !Ref NumberOfNodes] MinSize: !Ref NumberOfNodes Subnets: !If - 3AZDeployment - [!Ref Subnet1ID, !Ref Subnet2ID, !Ref Subnet3ID] - !If [2AZDeployment, [!Ref Subnet1ID, !Ref Subnet2ID], [!Ref Subnet1ID]] UpdateConfig: MaxUnavailable: !If [UseMaxNodesUnavailable, !Ref MaxNodesUnavailable, !Ref AWS::NoValue] MaxUnavailablePercentage: !If - UseMaxNodesUnavailablePercentage - !Ref MaxNodesUnavailablePercentage - !Ref AWS::NoValue NodeLaunchTemplate: Type: AWS::EC2::LaunchTemplate Condition: CreateNodeGroup Metadata: cfn-lint: config: ignore_checks: [E3008] ignore_reasons: - E3008: IamInstanceProfile Arn resource refs are necessary. Properties: LaunchTemplateData: BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: !Ref NodeVolumeSize VolumeType: gp2 DeleteOnTermination: true IamInstanceProfile: !If [IsUnmanaged, { Arn: !Ref GetNodeInstanceProfileArn }, !Ref AWS::NoValue] KeyName: !If [UseKeyPair, !Ref KeyPairName, !Ref AWS::NoValue] NetworkInterfaces: - DeviceIndex: 0 AssociatePublicIpAddress: false Description: String Groups: - !If [UseClusterNodeSecurityGroup, !Ref GetClusterNodeSecurityGroup, !Ref NodeSecurityGroupId] ImageId: !If - UseCustomAmi - !Ref CustomAmiId - !If - IsAL2 - !Sub - '{{resolve:ssm:/aws/service/eks/optimized-ami/${KubernetesVersion}/${OS}/recommended/image_id}}' - OS: !If [IsArm, amazon-linux-2-arm64, !If [IsGpu, amazon-linux-2-gpu, amazon-linux-2]] - !If - IsWindows - !Sub '{{resolve:ssm:/aws/service/ami-windows-latest/Windows_Server-${WindowsVersion}-English-${WindowsEdition}-EKS_Optimized-${KubernetesVersion}/image_id}}' - !If - IsBottlerocket - !Sub - '{{resolve:ssm:/aws/service/bottlerocket/aws-k8s-${KubernetesVersion}/${OS}/latest/image_id}}' - OS: !If [IsArm, arm64, x86_64] - !Ref AWS::NoValue InstanceType: !Ref NodeInstanceType UserData: Fn::Base64: !If - IsWindows - !Sub - | [string]$EKSBinDir = "$env:ProgramFiles\Amazon\EKS" [string]$EKSBootstrapScriptName = 'Start-EKSBootstrap.ps1' [string]$EKSBootstrapScriptFile = "$EKSBinDir\$EKSBootstrapScriptName" [string]$cfn_signal = "$env:ProgramFiles\Amazon\cfn-bootstrap\cfn-signal.exe" & $EKSBootstrapScriptFile -EKSClusterName ${EKSClusterName} -APIServerEndpoint ${GetClusterEndpoint} -Base64ClusterCA ${GetClusterEndpoint.CaData} ${BootstrapArguments} 3>&1 4>&1 5>&1 6>&1 $LastError = if ($?) { 0 } else { $Error[0].Exception.HResult } & $cfn_signal --exit-code=$LastError ` --stack="${AWS::StackName}" ` --resource="UnmanagedASG" ` --region=${AWS::Region} - BootstrapArguments: !If - AddExtraArgs - !Sub - -KubeletExtraArgs '${LabelsArg} ${TaintsArg}' - LabelsArg: !If [AddLabels, !Sub '--node-labels=${Labels}', ''] TaintsArg: !If [AddTaints, !Sub '--register-with-taints=${Taints}', ''] - '' - !If - IsBottlerocket - !Sub - | [settings.kubernetes] api-server = "${GetClusterEndpoint}" cluster-certificate = "${GetClusterEndpoint.CaData}" cluster-name = "${EKSClusterName}" ${LabelsArg} ${TaintsArg} - LabelsArg: !If - AddLabels - !Sub - | [settings.kubernetes.node-labels] ${LabelPairs} - LabelPairs: !Join [' = "', !Split ['=', !Join ['"\n', !Split [',', !Sub '${Labels}"']]]] - '' TaintsArg: !If - AddTaints - !Sub - | [settings.kubernetes.node-labels] ${TaintPairs} - TaintPairs: !Join [' = "', !Split ['=', !Join ['"\n', !Split [',', !Sub '${Taints}"']]]] - '' - !Sub - | #!/bin/bash set -o xtrace function signal() { /opt/aws/bin/cfn-signal --exit-code $1 \ --stack ${AWS::StackName} \ --resource UnmanagedASG \ --region ${AWS::Region} \ --role ${NodeInstanceRoleName} } ${ProxySetup} /etc/eks/bootstrap.sh ${EKSClusterName} ${ExtraArgs} \ --b64-cluster-ca ${GetClusterEndpoint.CaData} \ --apiserver-endpoint ${GetClusterEndpoint} || signal 1 ${ProxyPostSetup} signal $? - ExtraArgs: !If - AddExtraArgs - !Sub - --kubelet-extra-args '${LabelsArg} ${TaintsArg}' - LabelsArg: !If [AddLabels, !Sub '--node-labels=${Labels}', ''] TaintsArg: !If [AddTaints, !Sub '--register-with-taints=${Taints}', ''] - '' ProxySetup: !If - EnableProxy - !Sub | cat <> /etc/environment HTTP_PROXY=${HttpProxy} HTTPS_PROXY=${HttpProxy} http_proxy=${HttpProxy} https_proxy=${HttpProxy} no_proxy=${GetVpcCidr},localhost,127.0.0.1,169.254.169.254,.internal NO_PROXY=${GetVpcCidr},localhost,127.0.0.1,169.254.169.254,.internal EOF set -a source /etc/environment - '' ProxyPostSetup: !If - EnableProxy - | mkdir -p /etc/systemd/system/docker.service.d cat <> /etc/systemd/system/docker.service.d/proxy.conf [Service] EnvironmentFile=/etc/environment EOF cat <> /etc/systemd/system/kubelet.service.d/proxy.conf [Service] EnvironmentFile=/etc/environment EOF systemctl daemon-reload systemctl enable --now --no-block docker systemctl restart docker systemctl restart kubelet - '' NodeInstanceRoleName: !Sub - eks-quickstart-${Suffix} - Suffix: !If [IsManaged, ManagedNodeInstance, UnmanagedNodeInstance] MetadataOptions: HttpPutResponseHopLimit: !Ref EC2MetadataPutResponseHopLimit HttpEndpoint: enabled HttpTokens: !Ref EC2MetadataHttpTokens Outputs: EKSNodeSecurityGroup: Value: !If [UseClusterNodeSecurityGroup, !Ref GetClusterNodeSecurityGroup, !Ref NodeSecurityGroupId] NodeAutoScalingGroup: Condition: CreateNodeGroup Value: !If [IsManaged, !Ref GetManagedASG, !Ref UnmanagedASG]