Skip to content

Instantly share code, notes, and snippets.

@jamesandersen
Created January 12, 2017 04:52
Show Gist options
  • Save jamesandersen/0ed3a6c4841f184831b47ce4398a42af to your computer and use it in GitHub Desktop.
Save jamesandersen/0ed3a6c4841f184831b47ce4398a42af to your computer and use it in GitHub Desktop.
AWS Cloud Formation Template for ECS Stack with Elastic IP Associated to Auto-Scaling Group
AWSTemplateFormatVersion: '2010-09-09'
Description: >
AWS CloudFormation template to create a new VPC
or use an existing VPC for ECS deployment
in Create Cluster Wizard
Parameters:
EcsClusterName:
Type: String
Description: >
Specifies the ECS Cluster Name with which the resources would be
associated
Default: default
EcsAmiId:
Type: String
Description: Specifies the AMI ID for your container instances.
EcsInstanceType:
Type: String
Description: >
Specifies the EC2 instance type for your container instances.
Defaults to m4.large
Default: m4.large
ConstraintDescription: must be a valid EC2 instance type.
KeyName:
Type: String
Description: >
Optional - Specifies the name of an existing Amazon EC2 key pair
to enable SSH access to the EC2 instances in your cluster.
Default: ''
EIPAllocationID:
Type: String
Description: >
Optional - Specifies the Allocation ID of an Elastic IP
to associate with the first instance in the cluster
Default: ''
VpcId:
Type: String
Description: >
Optional - Specifies the ID of an existing VPC in which to launch
your container instances. If you specify a VPC ID, you must specify a list of
existing subnets in that VPC. If you do not specify a VPC ID, a new VPC is created
with atleast 1 subnet.
Default: ''
AllowedPattern: "^(?:vpc-[0-9a-f]{8}|)$"
ConstraintDescription: >
VPC Id must begin with 'vpc-' or leave blank to have a
new VPC created
SubnetIds:
Type: CommaDelimitedList
Description: >
Optional - Specifies the Comma separated list of existing VPC Subnet
Ids where ECS instances will run
Default: ''
SecurityGroupId:
Type: String
Description: >
Optional - Specifies the Security Group Id of an existing Security
Group. Leave blank to have a new Security Group created
Default: ''
VpcCidr:
Type: String
Description: Optional - Specifies the CIDR Block of VPC
Default: ''
SubnetCidr1:
Type: String
Description: Specifies the CIDR Block of Subnet 1
Default: ''
SubnetCidr2:
Type: String
Description: Specifies the CIDR Block of Subnet 2
Default: ''
SubnetCidr3:
Type: String
Description: Specifies the CIDR Block of Subnet 3
Default: ''
AsgMaxSize:
Type: Number
Description: >
Specifies the number of instances to launch and register to the cluster.
Defaults to 1.
Default: '1'
IamRoleInstanceProfile:
Type: String
Description: >
Specifies the Name or the Amazon Resource Name (ARN) of the instance
profile associated with the IAM role for the instance
SecurityIngressFromPort:
Type: Number
Description: >
Optional - Specifies the Start of Security Group port to open on
ECS instances - defaults to port 0
Default: '0'
SecurityIngressToPort:
Type: Number
Description: >
Optional - Specifies the End of Security Group port to open on ECS
instances - defaults to port 65535
Default: '65535'
SecurityIngressCidrIp:
Type: String
Description: >
Optional - Specifies the CIDR/IP range for Security Ports - defaults
to 0.0.0.0/0
Default: 0.0.0.0/0
EcsEndpoint:
Type: String
Description: >
Optional - Specifies the ECS Endpoint for the ECS Agent to connect to
Default: ''
VpcAvailabilityZones:
Type: CommaDelimitedList
Description: >
Specifies a comma-separated list of 3 VPC Availability Zones for
the creation of new subnets. These zones must have the available status.
Default: ''
EbsVolumeSize:
Type: Number
Description: >
Optional - Specifies the Size in GBs, of the newly created Amazon
Elastic Block Store (Amazon EBS) volume
Default: '0'
EbsVolumeType:
Type: String
Description: Optional - Specifies the Type of (Amazon EBS) volume
Default: ''
AllowedValues:
- ''
- standard
- io1
- gp2
- sc1
- st1
ConstraintDescription: Must be a valid EC2 volume type.
DeviceName:
Type: String
Description: Optional - Specifies the device mapping for the Volume
Default: ''
Conditions:
CreateEC2LCWithKeyPair:
!Not [!Equals [!Ref KeyName, '']]
SetEndpointToECSAgent:
!Not [!Equals [!Ref EcsEndpoint, '']]
CreateNewSecurityGroup:
!Equals [!Ref SecurityGroupId, '']
CreateNewVpc:
!Equals [!Ref VpcId, '']
CreateSubnet1: !And
- !Not [!Equals [!Ref SubnetCidr1, '']]
- !Condition CreateNewVpc
CreateSubnet2: !And
- !Not [!Equals [!Ref SubnetCidr2, '']]
- !Condition CreateSubnet1
CreateSubnet3: !And
- !Not [!Equals [!Ref SubnetCidr3, '']]
- !Condition CreateSubnet2
CreateEbsVolume: !And
- !Not [!Equals [!Ref EbsVolumeSize, '0']]
- !Not [!Equals [!Ref EbsVolumeType, '']]
- !Not [!Equals [!Ref DeviceName, '']]
Resources:
Vpc:
Condition: CreateSubnet1
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
PubSubnetAz1:
Condition: CreateSubnet1
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Ref SubnetCidr1
AvailabilityZone: !Select [ 0, !Ref VpcAvailabilityZones ]
PubSubnetAz2:
Condition: CreateSubnet2
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Ref SubnetCidr2
AvailabilityZone: !Select [ 1, !Ref VpcAvailabilityZones ]
PubSubnetAz3:
Condition: CreateSubnet3
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Ref SubnetCidr3
AvailabilityZone: !Select [ 2, !Ref VpcAvailabilityZones ]
InternetGateway:
Condition: CreateSubnet1
Type: AWS::EC2::InternetGateway
AttachGateway:
Condition: CreateSubnet1
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGateway
RouteViaIgw:
Condition: CreateSubnet1
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
PublicRouteViaIgw:
Condition: CreateSubnet1
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteViaIgw
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PubSubnet1RouteTableAssociation:
Condition: CreateSubnet1
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PubSubnetAz1
RouteTableId: !Ref RouteViaIgw
PubSubnet2RouteTableAssociation:
Condition: CreateSubnet2
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PubSubnetAz2
RouteTableId: !Ref RouteViaIgw
PubSubnet3RouteTableAssociation:
Condition: CreateSubnet3
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PubSubnetAz3
RouteTableId: !Ref RouteViaIgw
EcsSecurityGroup:
Condition: CreateNewSecurityGroup
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ECS Allowed Ports
VpcId: !If [ CreateSubnet1, !Ref Vpc, !Ref VpcId ]
SecurityGroupIngress:
IpProtocol: tcp
FromPort: !Ref SecurityIngressFromPort
ToPort: !Ref SecurityIngressToPort
CidrIp: !Ref SecurityIngressCidrIp
EcsInstanceLc:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref EcsAmiId
InstanceType: !Ref EcsInstanceType
AssociatePublicIpAddress: true
IamInstanceProfile: !Ref IamRoleInstanceProfile
KeyName: !If [ CreateEC2LCWithKeyPair, !Ref KeyName, !Ref "AWS::NoValue" ]
SecurityGroups: [ !If [ CreateNewSecurityGroup, !Ref EcsSecurityGroup, !Ref SecurityGroupId ] ]
BlockDeviceMappings: !If
- CreateEbsVolume
-
- DeviceName: !Ref DeviceName
Ebs:
VolumeSize: !Ref EbsVolumeSize
VolumeType: !Ref EbsVolumeType
- !Ref "AWS::NoValue"
UserData: !If
- SetEndpointToECSAgent
- Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${EcsClusterName} >> /etc/ecs/ecs.config
echo ECS_BACKEND_HOST=${EcsEndpoint} >> /etc/ecs/ecs.config
export AWS_ACCESS_KEY_ID='XXXXXXXXXX'
export AWS_SECRET_ACCESS_KEY='XXXXXXXXXXXXXXXX'
InstanceID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
Allocate_ID=${EIPAllocationID}
cd /usr/tmp
curl -O https://bootstrap.pypa.io/get-pip.py
sudo python27 get-pip.py
sudo /usr/local/bin/pip install awscli
/usr/local/bin/aws ec2 associate-address --instance-id $InstanceID --allocation-id $Allocate_ID --region XXXXXXXX
- Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${EcsClusterName} >> /etc/ecs/ecs.config
export AWS_ACCESS_KEY_ID='XXXXXXXXX'
export AWS_SECRET_ACCESS_KEY='XXXXXXXXXXXXXXXXXXXX'
InstanceID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
Allocate_ID=${EIPAllocationID}
cd /usr/tmp
curl -O https://bootstrap.pypa.io/get-pip.py
sudo python27 get-pip.py
sudo /usr/local/bin/pip install awscli
/usr/local/bin/aws ec2 associate-address --instance-id $InstanceID --allocation-id $Allocate_ID --region XXXXXXXX
EcsInstanceAsg:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier: !If
- CreateSubnet1
- !If
- CreateSubnet2
- !If
- CreateSubnet3
- [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}, ${PubSubnetAz3}" ]
- [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}" ]
- [ !Sub "${PubSubnetAz1}" ]
- !Ref SubnetIds
LaunchConfigurationName: !Ref EcsInstanceLc
MinSize: '0'
MaxSize: !Ref AsgMaxSize
DesiredCapacity: !Ref AsgMaxSize
Tags:
-
Key: Name
Value: !Sub "ECS Instance - ${AWS::StackName}"
PropagateAtLaunch: 'true'
-
Key: Description
Value: >
This instance is the part of the Auto Scaling group which was created
through ECS Console
PropagateAtLaunch: 'true'
Outputs:
EcsInstanceAsgName:
Description: Auto Scaling Group Name for ECS Instances
Value: !Ref EcsInstanceAsg
UsedByECSCreateCluster:
Description: Flag used by EC2 Container Service Create Cluster Wizard
Value: 'true'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment