1---
2AWSTemplateFormatVersion: "2010-09-09"
3Description: GitLab EKS Cluster
4
5Parameters:
6
7  KubernetesVersion:
8    Description: The Kubernetes version to install
9    Type: String
10    Default: "1.20"
11    AllowedValues:
12      - "1.16"
13      - "1.17"
14      - "1.18"
15      - "1.19"
16      - "1.20"
17
18  KeyName:
19    Description: The EC2 Key Pair to allow SSH access to the node instances
20    Type: AWS::EC2::KeyPair::KeyName
21
22  NodeImageIdSSMParam:
23    Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
24    Default: /aws/service/eks/optimized-ami/1.17/amazon-linux-2/recommended/image_id
25    Description: AWS Systems Manager Parameter Store parameter of the AMI ID for the worker node instances.
26
27  NodeInstanceType:
28    Description: EC2 instance type for the node instances
29    Type: String
30    Default: t3.medium
31    ConstraintDescription: Must be a valid EC2 instance type
32    AllowedValues:
33      - t2.small
34      - t2.medium
35      - t2.large
36      - t2.xlarge
37      - t2.2xlarge
38      - t3.nano
39      - t3.micro
40      - t3.small
41      - t3.medium
42      - t3.large
43      - t3.xlarge
44      - t3.2xlarge
45      - m3.medium
46      - m3.large
47      - m3.xlarge
48      - m3.2xlarge
49      - m4.large
50      - m4.xlarge
51      - m4.2xlarge
52      - m4.4xlarge
53      - m4.10xlarge
54      - m5.large
55      - m5.xlarge
56      - m5.2xlarge
57      - m5.4xlarge
58      - m5.12xlarge
59      - m5.24xlarge
60      - c4.large
61      - c4.xlarge
62      - c4.2xlarge
63      - c4.4xlarge
64      - c4.8xlarge
65      - c5.large
66      - c5.xlarge
67      - c5.2xlarge
68      - c5.4xlarge
69      - c5.9xlarge
70      - c5.18xlarge
71      - i3.large
72      - i3.xlarge
73      - i3.2xlarge
74      - i3.4xlarge
75      - i3.8xlarge
76      - i3.16xlarge
77      - r3.xlarge
78      - r3.2xlarge
79      - r3.4xlarge
80      - r3.8xlarge
81      - r4.large
82      - r4.xlarge
83      - r4.2xlarge
84      - r4.4xlarge
85      - r4.8xlarge
86      - r4.16xlarge
87      - x1.16xlarge
88      - x1.32xlarge
89      - p2.xlarge
90      - p2.8xlarge
91      - p2.16xlarge
92      - p3.2xlarge
93      - p3.8xlarge
94      - p3.16xlarge
95      - p3dn.24xlarge
96      - r5.large
97      - r5.xlarge
98      - r5.2xlarge
99      - r5.4xlarge
100      - r5.12xlarge
101      - r5.24xlarge
102      - r5d.large
103      - r5d.xlarge
104      - r5d.2xlarge
105      - r5d.4xlarge
106      - r5d.12xlarge
107      - r5d.24xlarge
108      - z1d.large
109      - z1d.xlarge
110      - z1d.2xlarge
111      - z1d.3xlarge
112      - z1d.6xlarge
113      - z1d.12xlarge
114
115  NodeAutoScalingGroupDesiredCapacity:
116    Description: Desired capacity of Node Group ASG.
117    Type: Number
118    Default: 3
119
120  NodeVolumeSize:
121    Description: Node volume size
122    Type: Number
123    Default: 20
124
125  ClusterName:
126    Description: Unique name for your Amazon EKS cluster.
127    Type: String
128
129  ClusterRole:
130    Description: The IAM Role to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf.
131    Type: String
132
133  ClusterControlPlaneSecurityGroup:
134    Description: The security groups to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.
135    Type: AWS::EC2::SecurityGroup::Id
136
137  VpcId:
138    Description: The VPC to use for your EKS Cluster resources.
139    Type: AWS::EC2::VPC::Id
140
141  Subnets:
142    Description: The subnets in your VPC where your worker nodes will run.
143    Type: List<AWS::EC2::Subnet::Id>
144
145Metadata:
146
147  AWS::CloudFormation::Interface:
148    ParameterGroups:
149      - Label:
150          default: EKS Cluster
151        Parameters:
152          - ClusterName
153          - ClusterRole
154          - KubernetesVersion
155          - ClusterControlPlaneSecurityGroup
156      - Label:
157          default: Worker Node Configuration
158        Parameters:
159          - NodeAutoScalingGroupDesiredCapacity
160          - NodeInstanceType
161          - NodeImageIdSSMParam
162          - NodeVolumeSize
163          - KeyName
164      - Label:
165          default: Worker Network Configuration
166        Parameters:
167          - VpcId
168          - Subnets
169
170Resources:
171
172  Cluster:
173    Type: AWS::EKS::Cluster
174    Properties:
175      Name: !Sub ${ClusterName}
176      Version: !Sub ${KubernetesVersion}
177      RoleArn: !Sub ${ClusterRole}
178      ResourcesVpcConfig:
179        SecurityGroupIds:
180          - !Ref ClusterControlPlaneSecurityGroup
181        SubnetIds: !Ref Subnets
182
183  NodeInstanceProfile:
184    Type: AWS::IAM::InstanceProfile
185    Properties:
186      Path: "/"
187      Roles:
188        - !Ref NodeInstanceRole
189
190  NodeInstanceRole:
191    Type: AWS::IAM::Role
192    Properties:
193      AssumeRolePolicyDocument:
194        Version: "2012-10-17"
195        Statement:
196          - Effect: Allow
197            Principal:
198              Service: ec2.amazonaws.com
199            Action: sts:AssumeRole
200      Path: "/"
201      ManagedPolicyArns:
202        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
203        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
204        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
205
206  NodeSecurityGroup:
207    Type: AWS::EC2::SecurityGroup
208    Properties:
209      GroupDescription: Security group for all nodes in the cluster
210      VpcId: !Ref VpcId
211      Tags:
212        - Key: !Sub kubernetes.io/cluster/${ClusterName}
213          Value: owned
214
215  NodeSecurityGroupIngress:
216    Type: AWS::EC2::SecurityGroupIngress
217    DependsOn: NodeSecurityGroup
218    Properties:
219      Description: Allow nodes to communicate with each other
220      GroupId: !Ref NodeSecurityGroup
221      SourceSecurityGroupId: !Ref NodeSecurityGroup
222      IpProtocol: -1
223      FromPort: 0
224      ToPort: 65535
225
226  NodeSecurityGroupFromControlPlaneIngress:
227    Type: AWS::EC2::SecurityGroupIngress
228    DependsOn: NodeSecurityGroup
229    Properties:
230      Description: Allow worker Kubelets and pods to receive communication from the cluster control plane
231      GroupId: !Ref NodeSecurityGroup
232      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
233      IpProtocol: tcp
234      FromPort: 1025
235      ToPort: 65535
236
237  ControlPlaneEgressToNodeSecurityGroup:
238    Type: AWS::EC2::SecurityGroupEgress
239    DependsOn: NodeSecurityGroup
240    Properties:
241      Description: Allow the cluster control plane to communicate with worker Kubelet and pods
242      GroupId: !Ref ClusterControlPlaneSecurityGroup
243      DestinationSecurityGroupId: !Ref NodeSecurityGroup
244      IpProtocol: tcp
245      FromPort: 1025
246      ToPort: 65535
247
248  NodeSecurityGroupFromControlPlaneOn443Ingress:
249    Type: AWS::EC2::SecurityGroupIngress
250    DependsOn: NodeSecurityGroup
251    Properties:
252      Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane
253      GroupId: !Ref NodeSecurityGroup
254      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
255      IpProtocol: tcp
256      FromPort: 443
257      ToPort: 443
258
259  ControlPlaneEgressToNodeSecurityGroupOn443:
260    Type: AWS::EC2::SecurityGroupEgress
261    DependsOn: NodeSecurityGroup
262    Properties:
263      Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443
264      GroupId: !Ref ClusterControlPlaneSecurityGroup
265      DestinationSecurityGroupId: !Ref NodeSecurityGroup
266      IpProtocol: tcp
267      FromPort: 443
268      ToPort: 443
269
270  ClusterControlPlaneSecurityGroupIngress:
271    Type: AWS::EC2::SecurityGroupIngress
272    DependsOn: NodeSecurityGroup
273    Properties:
274      Description: Allow pods to communicate with the cluster API Server
275      GroupId: !Ref ClusterControlPlaneSecurityGroup
276      SourceSecurityGroupId: !Ref NodeSecurityGroup
277      IpProtocol: tcp
278      ToPort: 443
279      FromPort: 443
280
281  NodeGroup:
282    Type: AWS::AutoScaling::AutoScalingGroup
283    DependsOn: Cluster
284    Properties:
285      DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity
286      LaunchConfigurationName: !Ref NodeLaunchConfig
287      MinSize: !Ref NodeAutoScalingGroupDesiredCapacity
288      MaxSize: !Ref NodeAutoScalingGroupDesiredCapacity
289      VPCZoneIdentifier: !Ref Subnets
290      Tags:
291        - Key: Name
292          Value: !Sub ${ClusterName}-node
293          PropagateAtLaunch: true
294        - Key: !Sub kubernetes.io/cluster/${ClusterName}
295          Value: owned
296          PropagateAtLaunch: true
297    UpdatePolicy:
298      AutoScalingRollingUpdate:
299        MaxBatchSize: 1
300        MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity
301        PauseTime: PT5M
302
303  NodeLaunchConfig:
304    Type: AWS::AutoScaling::LaunchConfiguration
305    Properties:
306      AssociatePublicIpAddress: true
307      IamInstanceProfile: !Ref NodeInstanceProfile
308      ImageId: !Ref NodeImageIdSSMParam
309      InstanceType: !Ref NodeInstanceType
310      KeyName: !Ref KeyName
311      SecurityGroups:
312        - !Ref NodeSecurityGroup
313      BlockDeviceMappings:
314        - DeviceName: /dev/xvda
315          Ebs:
316            VolumeSize: !Ref NodeVolumeSize
317            VolumeType: gp2
318            DeleteOnTermination: true
319      UserData:
320        Fn::Base64:
321          !Sub |
322            #!/bin/bash
323            set -o xtrace
324            /etc/eks/bootstrap.sh "${ClusterName}"
325            /opt/aws/bin/cfn-signal --exit-code $? \
326                     --stack  ${AWS::StackName} \
327                     --resource NodeGroup  \
328                     --region ${AWS::Region}
329
330Outputs:
331
332  NodeInstanceRole:
333    Description: The node instance role
334    Value: !GetAtt NodeInstanceRole.Arn
335
336  ClusterCertificate:
337    Description: The cluster certificate
338    Value: !GetAtt Cluster.CertificateAuthorityData
339
340  ClusterEndpoint:
341    Description: The cluster endpoint
342    Value: !GetAtt Cluster.Endpoint
343