Description: > This template deploys an EKS cluster to the provided VPC and subnets using an Auto Scaling Group Parameters: EnvironmentName: Description: An environment name that will be prefixed to resource names Type: String InstanceType: Description: Which instance type should we use to build the EKS cluster? Type: String Default: c4.large NodeAutoScalingGroupMinSize: Type: Number Description: Minimum size of Node Group ASG. Default: 10 NodeAutoScalingGroupMaxSize: Type: Number Description: Maximum size of Node Group ASG. Default: 20 NodeVolumeSize: Type: Number Description: Node volume size Default: 20 NodeGroupName: Description: Unique identifier for the Node Group. Type: String Default: "ng-1" BootstrapArguments: Description: Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami Default: "" Type: String KeyName: Description: The EC2 Key Pair to allow SSH access to the instances Type: AWS::EC2::KeyPair::KeyName NodeImageId: Type: AWS::EC2::Image::Id Description: AMI id for the node instances. Mappings: AWSRegionToEKSAMI: us-west-2: AMI: ami-0f54a2f7d2e9c88b3 Resources: AWSServiceRoleForAmazonEKS: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - eks.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonEKSServicePolicy - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy EKSControlPlaneSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security group for EKS control-plane" VpcId: 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, VPC ] ] SecurityGroupIngress: - CidrIp: 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, VpcCIDR ] ] IpProtocol: -1 EKSCluster: Type: AWS::EKS::Cluster Properties: Name: !Ref EnvironmentName RoleArn: !GetAtt AWSServiceRoleForAmazonEKS.Arn ResourcesVpcConfig: SecurityGroupIds: - { Ref: EKSControlPlaneSecurityGroup } SubnetIds: - 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, PrivateSubnet1 ] ] - 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, PrivateSubnet2 ] ] NodeInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - !Ref NodeInstanceRole NodeInstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: "/" ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly NodeSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security group for all nodes in the cluster VpcId: 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, VPC ] ] Tags: - Key: !Sub "kubernetes.io/cluster/${EnvironmentName}" Value: 'owned' NodeSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress DependsOn: NodeSecurityGroup Properties: Description: Allow node to communicate with each other GroupId: !Ref NodeSecurityGroup SourceSecurityGroupId: !Ref NodeSecurityGroup IpProtocol: '-1' FromPort: 0 ToPort: 65535 NodeSecurityGroupFromControlPlaneIngress: Type: AWS::EC2::SecurityGroupIngress DependsOn: NodeSecurityGroup Properties: Description: Allow worker Kubelets and pods to receive communication from the cluster control plane GroupId: !Ref NodeSecurityGroup SourceSecurityGroupId: !Ref EKSControlPlaneSecurityGroup IpProtocol: tcp FromPort: 1025 ToPort: 65535 ControlPlaneEgressToNodeSecurityGroup: Type: AWS::EC2::SecurityGroupEgress DependsOn: NodeSecurityGroup Properties: Description: Allow the cluster control plane to communicate with worker Kubelet and pods GroupId: !Ref EKSControlPlaneSecurityGroup DestinationSecurityGroupId: !Ref NodeSecurityGroup IpProtocol: tcp FromPort: 1025 ToPort: 65535 NodeSecurityGroupFromControlPlaneOn443Ingress: Type: AWS::EC2::SecurityGroupIngress DependsOn: NodeSecurityGroup Properties: Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane GroupId: !Ref NodeSecurityGroup SourceSecurityGroupId: !Ref EKSControlPlaneSecurityGroup IpProtocol: tcp FromPort: 443 ToPort: 443 ControlPlaneEgressToNodeSecurityGroupOn443: Type: AWS::EC2::SecurityGroupEgress DependsOn: NodeSecurityGroup Properties: Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443 GroupId: !Ref EKSControlPlaneSecurityGroup DestinationSecurityGroupId: !Ref NodeSecurityGroup IpProtocol: tcp FromPort: 443 ToPort: 443 EKSControlPlaneSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress DependsOn: NodeSecurityGroup Properties: Description: Allow pods to communicate with the cluster API Server GroupId: !Ref EKSControlPlaneSecurityGroup SourceSecurityGroupId: !Ref NodeSecurityGroup IpProtocol: tcp ToPort: 443 FromPort: 443 NodeGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: DesiredCapacity: !Ref NodeAutoScalingGroupMaxSize LaunchConfigurationName: !Ref NodeLaunchConfig MinSize: !Ref NodeAutoScalingGroupMinSize MaxSize: !Ref NodeAutoScalingGroupMaxSize VPCZoneIdentifier: - 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, PrivateSubnet1 ] ] - 'Fn::ImportValue': !Join [ ":", [ !Ref EnvironmentName, PrivateSubnet2 ] ] Tags: - Key: Name Value: !Sub "${EnvironmentName}-${NodeGroupName}-Node" PropagateAtLaunch: 'true' - Key: !Sub 'kubernetes.io/cluster/${EnvironmentName}' Value: 'owned' PropagateAtLaunch: 'true' UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: '1' MaxBatchSize: '1' NodeLaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Properties: AssociatePublicIpAddress: 'true' IamInstanceProfile: !Ref NodeInstanceProfile ImageId: !Ref NodeImageId InstanceType: !Ref InstanceType KeyName: !Ref KeyName SecurityGroups: - !Ref NodeSecurityGroup BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: !Ref NodeVolumeSize VolumeType: gp2 DeleteOnTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash set -o xtrace /etc/eks/bootstrap.sh ${EnvironmentName} ${BootstrapArguments} /opt/aws/bin/cfn-signal --exit-code $? \ --stack ${AWS::StackName} \ --resource NodeGroup \ --region ${AWS::Region}