AWSTemplateFormatVersion: '2010-09-09' Description: aws-eks Parameters: ClusterName: Description: Cluster name of EKS Type: String Default: eks-cluster 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. ami-02d2e0c36bbdb4bc3: Asia Pacific (Tokyo) ap-northeast-1. ami-0a54c984b9f908c81: US East (Ohio) us-east-2. ami-0440e4f6b9713faf6: US East (N. Virginia) us-east-1. ami-0c7a4976cb6fafd3a: EU (Ireland) eu-west-1. Default: ami-02d2e0c36bbdb4bc3 AllowedValues: - ami-02d2e0c36bbdb4bc3 - ami-0a54c984b9f908c81 - ami-0440e4f6b9713faf6 - ami-0c7a4976cb6fafd3a NodeGroupName: Description: Unique identifier for the Node Group. Type: String Default: node-group NodeInstanceType: Description: EC2 instance type for the node instances Type: String Default: t2.medium AllowedValues: - t2.small - t2.medium - t2.large - t2.xlarge - t2.2xlarge - m3.medium - m3.large - m3.xlarge - m3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.12xlarge - m5.24xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.18xlarge - i3.large - i3.xlarge - i3.2xlarge - i3.4xlarge - i3.8xlarge - i3.16xlarge - r3.xlarge - r3.2xlarge - r3.4xlarge - r3.8xlarge - r4.large - r4.xlarge - r4.2xlarge - r4.4xlarge - r4.8xlarge - r4.16xlarge - x1.16xlarge - x1.32xlarge - p2.xlarge - p2.8xlarge - p2.16xlarge - p3.2xlarge - p3.8xlarge - p3.16xlarge ConstraintDescription: Must be a valid EC2 instance type NodeAutoScalingGroupMinSize: Type: Number Description: Minimum size of Node Group ASG. Default: 0 NodeAutoScalingGroupMaxSize: Type: Number Description: Maximum size of Node Group ASG. Default: 0 NodeVolumeSize: Type: Number Description: Node volume size Default: 20 BootstrapArguments: Description: Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami Default: "" Type: String Resources: EKSRole: 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/AmazonEKSClusterPolicy - arn:aws:iam::aws:policy/AmazonEKSServicePolicy RoleName: eks-cluster-role VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 192.168.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: eks-vpc InternetGateway: Type: "AWS::EC2::InternetGateway" VPCGatewayAttachment: Type: "AWS::EC2::VPCGatewayAttachment" Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Public Subnets - Key: Network Value: Public Route: DependsOn: VPCGatewayAttachment Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway Subnet01: Type: AWS::EC2::Subnet Metadata: Comment: Subnet 01 Properties: AvailabilityZone: Fn::Select: - '0' - Fn::GetAZs: Ref: AWS::Region CidrBlock: 192.168.64.0/18 VpcId: Ref: VPC Tags: - Key: Name Value: eks-Subnet01 Subnet02: Type: AWS::EC2::Subnet Metadata: Comment: Subnet 02 Properties: AvailabilityZone: Fn::Select: - '1' - Fn::GetAZs: Ref: AWS::Region CidrBlock: 192.168.128.0/18 VpcId: Ref: VPC Tags: - Key: Name Value: eks-Subnet02 Subnet03: Type: AWS::EC2::Subnet Metadata: Comment: Subnet 03 Properties: AvailabilityZone: Fn::Select: - '2' - Fn::GetAZs: Ref: AWS::Region CidrBlock: 192.168.192.0/18 VpcId: Ref: VPC Tags: - Key: Name Value: eks-Subnet03 Subnet01RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref Subnet01 RouteTableId: !Ref RouteTable Subnet02RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref Subnet02 RouteTableId: !Ref RouteTable Subnet03RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref Subnet03 RouteTableId: !Ref RouteTable ControlPlaneSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Cluster communication with worker nodes VpcId: !Ref VPC EKSCluster: Type: AWS::EKS::Cluster Properties: Name: !Sub ${ClusterName} RoleArn: Fn::GetAtt: - EKSRole - Arn ResourcesVpcConfig: SecurityGroupIds: - Fn::GetAtt: - ControlPlaneSecurityGroup - GroupId SubnetIds: - !Ref Subnet01 - !Ref Subnet02 - !Ref Subnet03 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: !Ref VPC Tags: - Key: !Sub "kubernetes.io/cluster/${ClusterName}" 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 ControlPlaneSecurityGroup 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 ControlPlaneSecurityGroup 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 ControlPlaneSecurityGroup 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 ControlPlaneSecurityGroup DestinationSecurityGroupId: !Ref NodeSecurityGroup IpProtocol: tcp FromPort: 443 ToPort: 443 ClusterControlPlaneSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress DependsOn: NodeSecurityGroup Properties: Description: Allow pods to communicate with the cluster API Server GroupId: !Ref ControlPlaneSecurityGroup 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: - !Ref Subnet01 - !Ref Subnet02 - !Ref Subnet03 Tags: - Key: Name Value: !Sub "${ClusterName}-${NodeGroupName}-Node" PropagateAtLaunch: 'true' - Key: !Sub 'kubernetes.io/cluster/${ClusterName}' 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 NodeInstanceType 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 ${ClusterName} ${BootstrapArguments} /opt/aws/bin/cfn-signal --exit-code $? \ --stack ${AWS::StackName} \ --resource NodeGroup \ --region ${AWS::Region} Outputs: SubnetIds: Description: All subnets in the VPC Value: !Join [ ",", [ !Ref Subnet01, !Ref Subnet02, !Ref Subnet03 ] ] SecurityGroups: Description: Security group for the cluster control plane communication with worker nodes Value: !Join [ ",", [ !Ref ControlPlaneSecurityGroup ] ] VpcId: Description: The VPC Id Value: !Ref VPC NodeInstanceRole: Description: The node instance role Value: !GetAtt NodeInstanceRole.Arn