-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.template
289 lines (256 loc) · 9.57 KB
/
main.template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
AWSTemplateFormatVersion: "2010-09-09"
Description: |
Use this template as a sample of Reserving Capacity for your Auto Scaling Groups in AWS.
It creates a new VPC with 3 public subnets across 3 Availability Zones in a Selected Region, with a Specified nr of ODCRs in each AZ.
On top of this sits an Auto Scaling Group across all AZs, backed by the ODCRs via a Capacity Management Resource Group.
Note that this template will only work in Regions that have at least 3 Availability Zones! (uksb-1tupbocl7)
Parameters:
LatestAMIId:
Description: AMI to use for spinning up EC2 instances. Defaulting to the latest Amazon Linux AMI from the parameter store
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
EC2InstanceType:
Description: Instance typ to spin up. As this is for a demo purpose, we pick t2.micro as it is part of the Free Tier
Type: String
Default: t2.micro
VPCCIDR:
Description: CIDR block to use for the VPC. The only important thing here is that it is large enough to fit the subnets and Instances
Type: String
Default: 10.1.0.0/16
SubnetACIDR:
Description: CIDR block for the first subnet. Needs to be within the VPC CIDR range, not overlap with the other subnet CIDRs, and large enough to fit the Instances
Type: String
Default: 10.1.10.0/24
SubnetBCIDR:
Description: CIDR block for the second subnet. Needs to be within the VPC CIDR range, not overlap with the other subnet CIDRs, and large enough to fit the Instances
Type: String
Default: 10.1.20.0/24
SubnetCCIDR:
Description: CIDR block for the third subnet. Needs to be within the VPC CIDR range, not overlap with the other subnet CIDRs, and large enough to fit the Instances
Type: String
Default: 10.1.30.0/24
NrOfCapacityreservationsPerAZ:
Description: Nr of Capacity Reservations to make in each of the 3 Availability Zones
Type: Number
Default: 3
MinValue: 1
ASGMinSize:
Description: Minimum Size of the ASG. Defaulted to 0 here for maximum flexibility
Type: Number
Default: 0
MinValue: 0
ASGMaxSize:
Description: Max Size of the ASG. Defaulted to 12 here to accommodate the tests performed on it
Type: Number
Default: 12
MinValue: 0
ASGDesiredSize:
Description: Actual Size of the ASG at time of creation. Defaulted to 6 so that we have 2 Instances in each AZ
Type: Number
Default: 6
MinValue: 0
Resources:
VPC:
Type: AWS::EC2::VPC
Metadata:
cfn_nag:
rules_to_suppress:
- id: W60
reason: Flow logging would just complicate this scenario, and adds no value for this as a deminstration case for ODCRs
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-VPC
InternetGateway:
Type: AWS::EC2::InternetGateway
DependsOn: VPC
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref SubnetACIDR
AvailabilityZone: !Select
- 0
- !GetAZs
Ref: AWS::Region
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-Public-A
PublicSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref SubnetBCIDR
AvailabilityZone: !Select
- 1
- !GetAZs
Ref: AWS::Region
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-Public-B
PublicSubnetC:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref SubnetCCIDR
AvailabilityZone: !Select
- 2
- !GetAZs
Ref: AWS::Region
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-Public-C
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Public
PublicRoute1: # Public route table has direct routing to IGW:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetA
RouteTableId: !Ref PublicRouteTable
PublicSubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetB
RouteTableId: !Ref PublicRouteTable
PublicSubnetCRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetC
RouteTableId: !Ref PublicRouteTable
# ODCRs and Resource Group for them
CapacityReservationAvailabilityZoneA:
Type: AWS::EC2::CapacityReservation
Properties:
AvailabilityZone: !Select
- 0
- !GetAZs
Ref: AWS::Region
EndDateType: unlimited
InstanceCount: !Ref NrOfCapacityreservationsPerAZ
InstanceMatchCriteria: targeted
InstancePlatform: Linux/UNIX
InstanceType: t2.micro
CapacityReservationAvailabilityZoneB:
Type: AWS::EC2::CapacityReservation
Properties:
AvailabilityZone: !Select
- 1
- !GetAZs
Ref: AWS::Region
EndDateType: unlimited
InstanceCount: !Ref NrOfCapacityreservationsPerAZ
InstanceMatchCriteria: targeted
InstancePlatform: Linux/UNIX
InstanceType: t2.micro
CapacityReservationAvailabilityZoneC:
Type: AWS::EC2::CapacityReservation
Properties:
AvailabilityZone: !Select
- 2
- !GetAZs
Ref: AWS::Region
EndDateType: unlimited
InstanceCount: !Ref NrOfCapacityreservationsPerAZ
InstanceMatchCriteria: targeted
InstancePlatform: Linux/UNIX
InstanceType: t2.micro
CapacityReservationResourceGroup:
Type: AWS::ResourceGroups::Group
Properties:
Name: ASGCapacityReservationResourceGroup
Description: Resource Group for letting the ASG utilize the ODCRs
Configuration:
- Type: AWS::EC2::CapacityReservationPool
Parameters: []
- Type: AWS::ResourceGroups::Generic
Parameters:
- Name: allowed-resource-types
Values:
- AWS::EC2::CapacityReservation
Resources: #ARNs are created using String replacement, as there at the time of writing this template is no ARN property of a Capacity Reservation in CloudFormation
- !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:capacity-reservation/${CapacityReservationAvailabilityZoneA}
- !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:capacity-reservation/${CapacityReservationAvailabilityZoneB}
- !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:capacity-reservation/${CapacityReservationAvailabilityZoneC}
#Security and Auto Scaling Group
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Metadata:
cfn_nag:
rules_to_suppress:
- id: W40
reason: We are intentionally allowing all outbound traffic, as this is an example for ODCRs. This should not be done for a production situation unless explicitly needed.
- id: W5
reason: Egress to the entire world is ok for this example. This should not be done for a production situation unless explicitly needed.
Properties:
GroupDescription: Open nothing for Ingress
VpcId: !Ref VPC
SecurityGroupIngress: []
SecurityGroupEgress:
- CidrIp: 127.0.0.1/32
Description: Dummy rule to block all outbound traffic by only allowing access to self, as we do not need it for this example
IpProtocol: "-1"
CapacityBackedLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
LaunchTemplateData:
InstanceType: !Ref EC2InstanceType
ImageId: !Ref LatestAMIId
CapacityReservationSpecification:
CapacityReservationTarget:
CapacityReservationResourceGroupArn: !GetAtt CapacityReservationResourceGroup.Arn
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: true
Groups:
- !Ref InstanceSecurityGroup
DeleteOnTermination: true
CapacityBackedASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier:
- !Ref PublicSubnetA
- !Ref PublicSubnetB
- !Ref PublicSubnetC
LaunchTemplate:
LaunchTemplateId: !Ref CapacityBackedLaunchTemplate
Version: !GetAtt CapacityBackedLaunchTemplate.LatestVersionNumber
MaxSize: !Ref ASGMaxSize
MinSize: !Ref ASGMinSize
DesiredCapacity: !Ref ASGDesiredSize
Tags:
- Key: ODCRASG
Value: true
PropagateAtLaunch: false
Outputs:
AutoScalingGroupName:
Description: The Name of the Solution's Auto Scaling Group
Value: !Ref CapacityBackedASG
SubnetForManuallyAddedInstance:
Description: Subnet to use when Manually Adding an instance to test the ODCR behaviour
Value: !Ref PublicSubnetA
SubnetsToKeepWhenDroppingASGAZ:
Description: Subnets to keep when dropping an ASG AZ to test the ODCR behaviour
Value: !Join [",", [!Ref PublicSubnetA, !Ref PublicSubnetB]]