- AWS
CloudFormation Product Details
- User
guide
- 19
Best
Practices for Creating Amazon CloudFormation Templates
- Designer
- Preserve resources after stack destruction
- Info
- Estructura / Structure
{
"AWSTemplateFormatVersion" :
"2010-09-09",
"Description": "...",
"Parameters":
{},
"Conditions":
{},
"Resources": {},
"Outputs": {}
}
- Comentaris / Comments
- Etiquetes / Tags
- CLI
Cloudformation
- EC2
- Instance
- Volume
- VPC
- single EC2
instance
- single_ec2.json
{
"Description": "Single EC2
instance",
"AWSTemplateFormatVersion":
"2010-09-09",
"Metadata": {},
"Resources": {
"singleEC2": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId":"ami-xxxxxxxx",
"KeyName":"my_key_pair",
"InstanceType":"t2.micro"
}
}
}
}
- single ec2
instance with an extra volume
- single_ec2_volume.json
"Resources": {
...
"EC2Instance": {
"Type":
"AWS::EC2::Instance",
"Properties": {
"ImageId":{"Ref" : "ImageId"},
"SecurityGroups" : [ { "Ref" :
"InstanceSecurityGroup" } ],
"KeyName":"my_server_key",
"InstanceType":{"Ref" : "InstanceType"},
"UserData":
{
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash
-xe\n",
"sudo mkfs
-t xfs /dev/xvdh \n ",
"sudo mkdir
/mnt/vol \n ",
"sudo chmod
777 /mnt/vol \n ",
"sudo mount
/dev/xvdh /mnt/vol \n ",
] ]
}
},
"Tags":[{"Key":"Name","Value":{"Ref":"BaseName"}}]
}
},
...
"NewVolume" : {
"Type" :
"AWS::EC2::Volume",
"Properties"
: {
"Size" : "100",
"AvailabilityZone"
: { "Fn::GetAtt" : [ "EC2Instance",
"AvailabilityZone" ]}
}
},
"MountPoint" : {
"Type" :
"AWS::EC2::VolumeAttachment",
"Properties"
: {
"InstanceId" : { "Ref" :
"EC2Instance" },
"VolumeId" : { "Ref" :
"NewVolume" },
"Device" : "/dev/xvdh"
}
},
- single EC2 with
UserData
and extra volume
- Notes:
- When using direct bash commands:
- add "\n" at the end of each command
- no need to call sudo
- single_ec2_userdata_volume.json
{
"Description": "Single EC2
instance with extra volume",
"AWSTemplateFormatVersion":
"2010-09-09",
"Metadata": {},
"Parameters" : {
"InstanceType" : {
"Description" : "EC2 instance type",
"Type" :
"String",
"Default" :
"t2.micro",
"AllowedValues" : [ "t1.micro", "t2.micro",
"t2.small", "t2.medium", "m1.small", "m1.medium",
"m1.large", "m1.xlarge", "m2.xlarge",
"m2.2xlarge", "m2.4xlarge", "m3.medium",
"m3.large", "m3.xlarge", "m3.2xlarge",
"c1.medium", "c1.xlarge", "c3.large", "c3.xlarge",
"c3.2xlarge", "c3.4xlarge", "c3.8xlarge",
"c4.large", "c4.xlarge", "c4.2xlarge",
"c4.4xlarge", "c4.8xlarge", "g2.2xlarge",
"r3.large", "r3.xlarge", "r3.2xlarge",
"r3.4xlarge", "r3.8xlarge", "i2.xlarge",
"i2.2xlarge", "i2.4xlarge", "i2.8xlarge",
"d2.xlarge", "d2.2xlarge", "d2.4xlarge",
"d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge",
"cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"]
,
"ConstraintDescription" : "must be a valid EC2
instance type."
},
"HostedZone" : {
"Type" :
"String",
"Description" : "The DNS name of an existing
Amazon Route 53 hosted zone",
"AllowedPattern" :
"(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
"ConstraintDescription" : "must be a valid DNS
zone name.",
"Default" :
"example.net"
},
"ImageId" : {
"Type" :
"String",
"Description" : "The image_id for the ec2
instance"
},
"NewVolumeSize" : {
"Type" :
"String",
"Description" : "The size of the new volume (GB)",
"Default":
"5"
}
},
"Resources": {
"EC2Instance": {
"Type":
"AWS::EC2::Instance",
"Properties": {
"ImageId":{"Ref" : "ImageId"},
"SecurityGroups" : [ { "Ref" :
"InstanceSecurityGroup" } ],
"KeyName":"wct_streaming_server",
"InstanceType":{"Ref" : "InstanceType"},
"UserData":
{
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash
-xe \n",
"while [ !
-e /dev/xvdh ]; do echo waiting for /dev/xvdh to
attach; sleep 10; done \n",
"mkfs -t xfs
/dev/xvdh \n",
"mkdir -p
/mnt/vol1 \n",
"mount
/dev/xvdh /mnt/vol1 \n",
"chmod 777
/mnt/vol1 \n"
] ]
}
},
"Tags":[{"Key":"Name","Value":{"Ref":"BaseName"}}]
}
},
"NewVolume" : {
"Type" :
"AWS::EC2::Volume",
"Properties"
: {
"Size" :
{"Ref" : "NewVolumeSize"},
"AvailabilityZone" : { "Fn::GetAtt" : [
"EC2Instance", "AvailabilityZone" ]}
}
},
"MountPoint" : {
"Type" :
"AWS::EC2::VolumeAttachment",
"Properties"
: {
"InstanceId"
: { "Ref" : "EC2Instance" },
"VolumeId" : { "Ref" : "NewVolume" },
"Device" :
"/dev/xvdh"
}
},
}
- single EC2 entry with
Route53
- single_ec2_r53.json
{
"Description":
"Single EC2 instance",
"AWSTemplateFormatVersion":
"2010-09-09",
"Metadata": {},
"Parameters" : {
"InstanceType" : {
"Description" : "EC2 instance type",
"Type" :
"String",
"Default" :
"m1.small",
"AllowedValues" : [ "t1.micro", "t2.micro",
"t2.small", "t2.medium", "m1.small", "m1.medium",
"m1.large", "m1.xlarge", "m2.xlarge",
"m2.2xlarge", "m2.4xlarge", "m3.medium",
"m3.large", "m3.xlarge", "m3.2xlarge",
"c1.medium", "c1.xlarge", "c3.large", "c3.xlarge",
"c3.2xlarge", "c3.4xlarge", "c3.8xlarge",
"c4.large", "c4.xlarge", "c4.2xlarge",
"c4.4xlarge", "c4.8xlarge", "g2.2xlarge",
"r3.large", "r3.xlarge", "r3.2xlarge",
"r3.4xlarge", "r3.8xlarge", "i2.xlarge",
"i2.2xlarge", "i2.4xlarge", "i2.8xlarge",
"d2.xlarge", "d2.2xlarge", "d2.4xlarge",
"d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge",
"cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"]
,
"ConstraintDescription" : "must be a valid EC2
instance type."
},
"HostedZone" : {
"Type" :
"String",
"Description" : "The DNS name of an existing
Amazon Route 53 hosted zone",
"AllowedPattern" :
"(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
"ConstraintDescription" : "must be a valid DNS
zone name."
}
},
"Resources": {
"EC2Instance": {
"Type":
"AWS::EC2::Instance",
"Properties": {
"ImageId":"ami-437da730",
"SecurityGroups" : [ { "Ref" :
"InstanceSecurityGroup" } ],
"KeyName":"my_key_pair",
"InstanceType":"t2.micro"
}
},
"InstanceSecurityGroup" : {
"Type" :
"AWS::EC2::SecurityGroup",
"Properties"
: {
"GroupDescription" : "Enable SSH, HTTP, RTMP",
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
},
{
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"
},
{
"IpProtocol" : "tcp",
"FromPort" : "1935",
"ToPort" : "1935",
"CidrIp" : "0.0.0.0/0"
}
]
}
},
"MyDNSRecord" : {
"Type" :
"AWS::Route53::RecordSet",
"Properties"
: {
"HostedZoneName" : { "Fn::Join" : [ "", [{"Ref" :
"HostedZone"}, "." ]]},
"Comment" :
"DNS name for my instance.",
"Name" : {
"Fn::Join" : [ "", [{"Ref" : "EC2Instance"}, ".",
{"Ref" : "AWS::Region"}, ".", {"Ref" :
"HostedZone"} ,"."]]},
"Type" :
"A",
"TTL" :
"900",
"ResourceRecords" : [ { "Fn::GetAtt" : [
"EC2Instance", "PublicIp" ] } ]
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created
EC2 instance",
"Value" : {
"Ref" : "EC2Instance" }
},
"AZ" : {
"Description" : "Availability Zone of the newly
created EC2 instance",
"Value" : {
"Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone"
] }
},
"PublicDNS" : {
"Description" : "Public DNSName of the newly
created EC2 instance",
"Value" : {
"Fn::GetAtt" : [ "EC2Instance", "PublicDnsName" ]
}
},
"PublicIP" : {
"Description" : "Public IP address of the newly
created EC2 instance",
"Value" : {
"Fn::GetAtt" : [ "EC2Instance", "PublicIp" ] }
},
"DomainName" : {
"Description" : "Fully qualified domain name",
"Value" : {
"Ref" : "MyDNSRecord" }
}
}
}
- EFS
- AWS::EFS::FileSystem
- AWS::EFS::MountTarget
- exemple
...
"Resources" : {
"MyFileSystem" : {
"Type":
"AWS::EFS::FileSystem",
"Properties": {
"PerformanceMode": "generalPurpose",
"FileSystemTags": [
{
"Key": "Name",
"Value": "my-fs"
}
]
}
},
"MyMountTargetSecurityGroup" : {
"Type" :
"AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable ports 2049 (nfs)",
"VpcId" : {"Ref"
: "VPCId"},
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "2049",
"ToPort" : "2049",
"CidrIp" : {"Ref": "CidrSubnet"}
}
]
}
},
"MyMountTarget" : {
"Type":
"AWS::EFS::MountTarget",
"Properties": {
"FileSystemId":
{ "Ref": "MyFileSystem" },
"SubnetId": {
"Ref": "MySubnet" },
"SecurityGroups": [ { "Ref":
"MyMountTargetSecurityGroup" }
]
}
},
...
"# mount efs
from instance \n",
"# mount -t nfs4 -o
nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport
", {"Ref": "ProcessFileSystem"},".efs.",{"Ref" :
"AWS::Region"},".amazonaws.com:/ /mnt/efs \n",
" mkdir -p /mnt/efs \n",
"echo ", {"Ref":
"ProcessFileSystem"},".efs.",{"Ref" :
"AWS::Region"},".amazonaws.com:/ /mnt/efs nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport
0 0 >>/etc/fstab \n",
" mount /mnt/efs \n",
...
}
- Route53
- Alarm
- Autoscaling group
- Recover
- S3
- CloudFront
- AWS::CloudFront::Distribution
"PriceClass"
:
"PriceClass_100" -> Use Only U.S.,
Canada and Europe
"PriceClass_200" -> Use U.S.,
Canada, Europe, Asia and Africa
"PriceClass_All" -> Use All Edge
Locations (Best Performance)
- No cache for 404
"MyCloudFront" : {
"Type" :
"AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig"
: {
"CustomErrorResponses" : [ {
"ErrorCode"
: "404",
"ErrorCachingMinTTL" : "2"
} ]
...
}
}
}
- Cache
behaviour
/ Forward headers: Whitelist
- Configuring
CloudFront
to Cache Objects Based on Request Headers
- To avoid problems with CORS and 403 response from CloudFront
"DefaultCacheBehavior"
: {
"TargetOriginId"
: { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"},
"-my_dir" ] ]},
"CachePolicyId":
"658327ea-f89d-4fab-a63d-7e88639e58f6" ,
"OriginRequestPolicyId":
"88a5eaf4-2fd4-4709-b370-b4c650ea3fcf",
"ResponseHeaderPolicyId":
"60669652-455b-4ae9-85a4-c4c02393f86c",
"AllowedMethods" :
["GET", "HEAD", "OPTIONS"],
"CachedMethods" : ["GET", "HEAD", "OPTIONS"],
"ViewerProtocolPolicy"
: "allow-all"
},
- (ForwardedValues is deprecated; use CachePolicyId) To
avoid problems with CORS and 403 response from CloudFront
"DefaultCacheBehavior"
: {
"TargetOriginId"
: { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"},
"-my_dir" ] ]},
"ForwardedValues"
: {
"Headers" :
["Origin","Access-Control-Request-Headers"," Access-Control-Request-Method "],
"QueryString"
: "false",
"Cookies"
: { "Forward" : "none" }
},
"AllowedMethods" :
["GET", "HEAD", "OPTIONS"],
"CachedMethods"
: ["GET", "HEAD", "OPTIONS"],
"ViewerProtocolPolicy"
: "allow-all"
},
- Group of origins, to establish a fallback
"Origins": [
{"Id": "My-primary-origin",
...
},
{"Id": "My-secondary-origin",
...
}
],
"OriginGroups":
{
"Items": [
{
"Id":
"My-first-origin-group",
"FailoverCriteria": {"StatusCodes": {"Items": [403,
404], "Quantity": 2} },
"Members": {
"Items": [
{"OriginId": "My-primary-origin",
{"OriginId": "My-secondary-origin"}
],
"Quantity": 2
}
}
],
"Quantity":
1
},
"DeafultCacheBehavior": ...
- Full examples:
- Origin is S3, with whitelist for forwarded headers
("Origin"):
"Resources": {
"MyCloudFront" : {
"Type"
: "AWS::CloudFront::Distribution",
"Properties"
: {
"DistributionConfig"
: {
"Origins"
: [ {
"DomainName":
{ "Fn::Join" : [ "", [{"Ref":"BucketName"},
".s3.amazonaws.com"]]},
"OriginPath":
"my_dir",
"Id"
: { "Fn::Join" : [ "", ["S3-",
{"Ref":"BucketName"}, "-my_dir" ] ]},
"S3OriginConfig":
{}
}],
"Enabled"
: "true",
"Comment"
: "My comments",
"DefaultCacheBehavior"
: {
"TargetOriginId"
: { "Fn::Join" : [ "", ["S3-",
{"Ref":"BucketName"}, "-my_dir" ] ]},
"ForwardedValues"
: {
"Headers"
: ["Origin"],
"QueryString"
: "false",
"Cookies"
: { "Forward" : "none" }
},
"ViewerProtocolPolicy"
: "allow-all"
},
"PriceClass"
: "PriceClass_100"
}
}
}
},
- Origin is own http server, with no cache for 404
responses:
"Resources": {
"MyCloudFront" : {
"Type"
: "AWS::CloudFront::Distribution",
"Properties"
: {
"DistributionConfig"
: {
"Origins"
: [ {
"DomainName":
"myserver.toto.org",
"OriginPath":
"/root_dir",
"Id"
: "oid-root_dir",
"CustomOriginConfig":
{
"HTTPPort":
"80",
"HTTPSPort":
"443",
"OriginProtocolPolicy":
"http-only"
}
}],
"Enabled"
: "true",
"Comment"
: "My comments",
"DefaultCacheBehavior"
: {
"TargetOriginId"
: "oid-root_dir" ,
"ForwardedValues"
: {
"QueryString"
: "false",
"Cookies"
: { "Forward" : "none" }
},
"ViewerProtocolPolicy"
: "allow-all"
},
"CustomErrorResponses"
: [ {
"ErrorCode"
: "404",
"ErrorCachingMinTTL"
: "2"
}
],
"PriceClass"
: "PriceClass_100"
}
}
}
},
- ...
- Amazon
CloudFront
Template Snippets
- Amazon
CloudFront
- Introduction
- LoadBalancer
-
|
Application
Load Balancer |
Network
Load Balancer
|
Classic Load Balancer |
protocols
|
HTTP, HTTPS, HTTP/2,
WebSockets
|
TCP, UDP
|
HTTP, HTTPS, TCP,
SSL
|
|
AWS::ElasticLoadBalancingV2::LoadBalancer
- Type: application
- Subnets
|
AWS::ElasticLoadBalancingV2::LoadBalancer
|
AWS::ElasticLoadBalancing::LoadBalancer
- AvailabilityZones
- HealthCheck
|
Fn::GetAtt
|
CanonicalHostedZoneID
|
|
CanonicalHostedZoneNameID
|
DNSName
|
|
CanonicalHostedZoneName
|
LoadBalancerName
|
|
-
|
|
AWS::ElasticLoadBalancingV2::Listener
AWS::ElasticLoadBalancingV2::TargetGroup
(TargetGroups)
- "HealthCheckPath": "/mypath/",
"HealthCheckPort": "443",
"HealthCheckProtocol": "HTTPS",
"HealthCheckTimeoutSeconds": 5,
"UnhealthyThresholdCount": 5,
"HealthCheckIntervalSeconds": 30
|
|
Listeners
|
- Application Load Balancer
- Create
and Configure AWS Application Load Balancer with
CloudFormation
- a minimum of 2 subnets (in 2 different availability
zones) are needed
{
"Description": "Application
load balancer",
"AWSTemplateFormatVersion":
"2010-09-09",
"Metadata": {},
"Parameters" : {
"BaseName" : {
"Type" : "String",
"Description" : "The basename of the stack",
"Default": "basename"
},
"VPCId"
: {
"Type" : "String",
"Description" : "Id of the used VPC",
"Default" : "vpc-de64aab8"
},
"AvailabilityZone" : {
"Description" : "Availability zone to try to
deploy the resources to. Passing empty string will
let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1a"
},
"CidrSubnet" : {
"Type" : "String",
"Description" : "CIDR for the created subnet (must
be a subset of VPC CIDR)",
"Default" : "10.1.1.0/27"
},
"SecondaryAvailabilityZone" : {
"Description" : "Secondary vailability zone to try
to deploy the resources to. Passing empty string
will let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1b"
},
"CidrSecondarySubnet" : {
"Type" : "String",
"Description" : "Secondary CIDR for the created
subnet (must be a subset of VPC CIDR)",
"Default" : "10.1.1.32/27"
},
"CertificateId" : {
"Type" : "String",
"Description" : "Certificate id"
}
},
"Resources": {
"PrimarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" : "AvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" :
"BaseName"}]]}
}
]
}
},
"SecondarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" :
"SecondaryAvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSecondarySubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" :
"BaseName"}, "-sec"]]}
}
]
}
},
"MyApplicationLoadBalancer": {
"Type" :
"AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"Name": "my-alb",
"Type": "application",
"IpAddressType": "ipv4",
"Subnets": [{"Ref" : "PrimarySubnet"}, {"Ref" :
"SecondarySubnet"}],
"LoadBalancerAttributes": [
{"Key": "idle_timeout.timeout_seconds", "Value":
60}
]
}
},
"MyHTTPSListener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"LoadBalancerArn": {"Ref" :
"MyApplicationLoadBalancer"},
"Port": 443,
"Protocol": "HTTPS",
"Certificates": [{"Ref" : "CertificateId"}],
"DefaultActions": [
{
"Order": 1,
"Type": "forward",
"TargetGroupArn": {"Ref": "MyTargetGroup"}
}
]
}
},
"MyTargetGroup": {
"Type":
"AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"VpcId": {"Ref" : "VPCId"},
"TargetType": "instance",
"Name": "my-targetgroup",
"Port": 443,
"Protocol": "HTTPS"
}
}
}
}
- Network load balancer
- only one subnet is needed:
{
"Description": "Network load
balancer",
"AWSTemplateFormatVersion":
"2010-09-09",
"Metadata": {},
"Parameters" : {
"BaseName" : {
"Type" : "String",
"Description" : "The basename of the stack",
"Default": "nbasename"
},
"VPCId"
: {
"Type" : "String",
"Description" : "Id of the used VPC",
"Default" : "vpc-de64aab8"
},
"AvailabilityZone" : {
"Description" : "Availability zone to try to
deploy the resources to. Passing empty string will
let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1a"
},
"CidrSubnet" : {
"Type" : "String",
"Description" : "CIDR for the created subnet (must
be a subset of VPC CIDR)",
"Default" : "10.1.3.0/27"
},
"CertificateId" : {
"Type" : "String",
"Description" : "Certificate id",
"Default" :
"arn:aws:acm:eu-west-1:458626664701:certificate/c82f280a-8f5f-4d34-bbec-45e521724b60"
}
},
"Resources": {
"PrimarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" : "AvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" :
"BaseName"}]]}
}
]
}
},
"MyNetworkLoadBalancer": {
"Type" :
"AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"Name": "dev-my-nlb",
"Type": "network",
"IpAddressType": "ipv4",
"Subnets": [{"Ref" : "PrimarySubnet"}],
"LoadBalancerAttributes": [
]
}
},
"MyRTMPListener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"LoadBalancerArn": {"Ref" :
"MyNetworkLoadBalancer"},
"Port": 1935,
"Protocol": "TCP",
"DefaultActions": [
{
"Order": 1,
"Type": "forward",
"TargetGroupArn": {"Ref": "MyTargetGroup"}
}
]
}
},
"MyTargetGroup": {
"Type":
"AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"VpcId": {"Ref" : "VPCId"},
"TargetType": "instance",
"Name": "my-ntargetgroup",
"Port": 1935,
"Protocol": "TCP"
}
}
}
}
- Classic Load Balancer
- listener with redirect ports http/80, http/8088,
https/8089, tcp/1935 and LBCookieStickinessPolicy:
"MyLoadBalancer": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer ",
"Properties": {
"LoadBalancerName": "MyLoadbalancerName",
"SecurityGroups" : [ ... ],
"AvailabilityZones": {
"Fn::GetAZs":
""
},
"CrossZone": "true",
"ConnectionSettings":
{
"IdleTimeout"
: 60
}
"Listeners":
[
{
"LoadBalancerPort":
"80",
"InstancePort":
"80",
"Protocol":
"HTTP",
"PolicyNames":
["MyFirstLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort":
"8088",
"InstancePort":
"8088",
"Protocol":
"HTTP",
"PolicyNames":
["MySecondLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort":
"8089",
"Protocol":
"HTTPS",
"InstancePort":
"8089",
"InstanceProtocol":
"HTTPS",
"SSLCertificateId":
"arn:aws:acm:eu-west-1:...",
"PolicyNames":
["MySecondLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort":
"1935",
"InstancePort":
"1935",
"Protocol":
"TCP"
}
],
"LBCookieStickinessPolicy" : [
{
"CookieExpirationPeriod"
: "500",
"PolicyName"
: "MyFirstLBCookieStickinessPolicy"
},
{
"CookieExpirationPeriod"
: "1000",
"PolicyName"
: "MySecondLBCookieStickinessPolicy"
}
],
"HealthCheck": {
"Target":
"HTTP:80/",
"HealthyThreshold":
"3",
"UnhealthyThreshold":
"5",
"Interval":
"30",
"Timeout":
"5"
}
}
}
- listener with a certificate from ACM
- SecurityGroup
- UDP
- AutoScalingGroup
- Prerequisites (only for LaunchConfig?):
- cfn-signal
- Download from:
- kixorz/ubuntu-cloudformation.json
- Install (Python 3)
- Install (Python 2)
mkdir aws-cfn-bootstrap-latest
curl
https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
| tar xz -C aws-cfn-bootstrap-latest
--strip-components 1
easy_install aws-cfn-bootstrap-latest
- Problemes / Problems
Traceback (most recent call last):
File "/bin/easy_install", line 9, in
<module>
load_entry_point('setuptools==0.9.8',
'console_scripts', 'easy_install')()
[...]
File
"/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py",
line 701, in process_distribution
distreq.project_name,
distreq.specs, requirement.extras
TypeError: __init__() takes exactly 2
arguments (4 given)
- Diagnose
- python
>>> from
pkg_resources import
load_entry_point
>>>
load_entry_point('setuptools==0.9.8',
'console_scripts',
'easy_install')()
...
pkg_resources.VersionConflict:
(setuptools 25.1.4
(/usr/lib/python2.7/site-packages/setuptools-25.1.4-py2.7.egg),
Requirement.parse('setuptools==0.9.8'))
- Solució / Solution
sudo rm -rf
/usr/lib/python2.7/site-packages/setuptools-25.1.4-py2.7.egg
- You must install a UserData
on your instance (AMI) that generates a cfn-signal received by CreationPolicy
"LaunchConfig" : {
"Type" :
"AWS::AutoScaling::LaunchConfiguration",
"Properties"
: {
"ImageId":{"Ref" : "MyImageId"},
"SecurityGroups" : [ { "Ref" : "MySecurityGroup" }
],
"KeyName":"my_key",
"InstanceType":{"Ref" : "MyInstanceType"},
"IamInstanceProfile":
"role_my_server",
"UserData":
{
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash
-xe\n",
"/usr/bin/cfn-signal -e
0 --stack ", { "Ref": "AWS::StackName" },
" --resource
MyAutoscalingGroup ",
" --region
", { "Ref" : "AWS::Region" }, "\n"
] ]
}
}
}
},
- Auto
Scaling
Template Snippets
- AutoScalingGroup
- AWS::AutoScaling::AutoScalingGroup
- example.json
"MyAutoScalingGroup" : {
"Type" :
"AWS::AutoScaling::AutoScalingGroup",
"Properties"
: {
"LaunchConfigurationName" : { "Ref" :
"MyLaunchConfig" },
"MinSize" :
"1",
"MaxSize" :
"3",
"LoadBalancerNames" : [ { "Ref" : "MyLoadBalancer"
} ],
"Tags":[
{
"Key":"Name",
"Value":{ "Fn::Join" : [ "",
["myinstance-", {"Ref" : "MyName"}]]},
"PropagateAtLaunch" : "true"
}
]
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT15M",
"Count" : "1"
}
},
"UpdatePolicy": {
"AutoScalingRollingUpdate": {
"MinInstancesInService": "1",
"MaxBatchSize": "1",
"PauseTime" : "PT15M",
"WaitOnResourceSignals": "true"
}
}
},
- example_with_launch_template.json (create a single
instance of type, in order of preference: t3.micro or
t3.small or t3.medium; t3.nano is not used)
{
"AWSTemplateFormatVersion" :
"2010-09-09",
"Description": "Tetst asg",
"Parameters": {},
"Resources": {
"MyLaunchTemplate": {
"Type": "AWS::EC2::LaunchTemplate",
"Properties": {
"LaunchTemplateData": {
"ImageId" : "ami-xxx",
"InstanceType" : "t3.nano",
"IamInstanceProfile":
{"Name": "role_my_server"},
"UserData": {
"Fn::Base64": {
"Fn::Join" : [
"",
[
"#!/bin/bash -xe\n",
"sudo mkdir /mnt/toto \n",
"sudo chmod 777 /mnt/toto \n"
]
]
}
}
}
}
},
"MyGroup": {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"MinSize": "1",
"MaxSize": "1",
"DesiredCapacity" : "1",
"AvailabilityZones" :
["eu-west-1a","eu-west-1b","eu-west-1c"],
"MixedInstancesPolicy":
{
"InstancesDistribution": {
"OnDemandAllocationStrategy": "prioritized"
},
"LaunchTemplate":
{
"LaunchTemplateSpecification":
{
"LaunchTemplateId": {
"Ref": "MyLaunchTemplate"
},
"Version" : {
"Fn::GetAtt": ["MyLaunchTemplate",
"DefaultVersionNumber"]
}
},
"Overrides":
[
{"InstanceType": "t3.micro"},
{"InstanceType": "t3.small"},
{"InstanceType": "t3.medium"}
]
}
}
}
}
}
}
- ScalingPolicy
- Alarm
- AWS::...
- example.json
"MyUpScalingPolicy" : {
"Type" :
"AWS::AutoScaling::ScalingPolicy",
"Properties"
: {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" :
"MyAutoScalingGroup" },
"Cooldown" :
"60",
"ScalingAdjustment" : "1"
}
},
"MyCPUHighAlarm": {
"Type":
"AWS::CloudWatch::Alarm",
"Properties": {
"EvaluationPeriods": "1",
"Statistic":
"Average",
"Threshold":
"80",
"AlarmDescription": "Alarm if CPU too high or
metric disappears indicating instance is down",
"Period":
"60",
"AlarmActions": [ { "Ref": "MyUpScalingPolicy" }
],
"Namespace":
"AWS/EC2",
"Dimensions": [ {
"Name": "AutoScalingGroupName",
"Value": { "Ref":
"MyAutoScalingGroup" }
} ],
"ComparisonOperator": "GreaterThanThreshold",
"MetricName": "CPUUtilization"
}
},
- Launch
-
|
response from:
autoscaling describe-auto-scaling-groups
--auto-scaling-group-names ... |
UserData |
cfn-signal |
LaunchTemplate
(new) |
"LaunchTemplate": {
"LaunchTemplateId": "...",
"LaunchTemplateName": "...",
"Version": "$Default"
} |
|
? |
LaunchConfiguration (old) |
"LaunchConfigurationName": "..." |
|
needed in UserData |
- LaunchTemplate
(preferred over LaunchConfiguration)
- LaunchConfiguration
(use LaunchTemplate
instead) (deprecated by end 2022)
- Example:
- ElastiCache
- ...
|