AWSTemplateFormatVersion: '2010-09-09' Description: >- AWS CloudFormation Template creates a load-balanced Elastigroup with a sample website where the instances can accept traffic from the load balancer. The web site is available on port 80; however, the instances can be configured to listen on any port (8888, by default). Intelligent Traffic Flow ensures the traffic is distributed across the instance types by vCPU weight, and predictive auto scaling can scale instances up and down in advance, using Machine Learning algorithm. Scheduling tasks are set up to automatically scale down the group to 0 on weekends (at 12:00 AM, only on Saturday UTC) and scale the capacity back up during weekdays (at 12:00 AM, only on Monday UTC). **WARNING** This template creates one or more Amazon Elastic Compute Cloud (Amazon EC2) instances, an Application Load Balancer, and target groups. You'll be billed for the AWS resources used if you create a stack from this template. (qs-1ti8doc1u) Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network configuration Parameters: - VpcId - Subnets - Label: default: Elastic Spot Config Parameters: - AccountId - AccessToken - KeyPair - ShouldRoll - ShouldUpdateTargetCapacity - AWSAccountType - ElastigroupName ParameterLabels: VpcId: default: VPC ID Subnets: default: VPC subnets AccountId: default: Spotinst account ID AccessToken: default: Spotinst API token KeyPair: default: Amazon EC2 KeyPair ShouldRoll: default: Should roll when updating ShouldUpdateTargetCapacity: default: Should update target capacity on group update AWSAccountType: default: Type of AWS account resources are created in ElastigroupName: default: Elastigroup name Parameters: VpcId: Type: AWS::EC2::VPC::Id Description: Existing VPC ID. Subnets: Type: List Description: List of Subnet IDs in your selected VPC. ConstraintDescription: Must be a list of at least two existing subnets associated. They should reside in the selected VPC. AccountId: Type: String Description: Provide Spotinst account ID. AccessToken: Type: String Description: Provide Spotinst API token. KeyPair: Description: Existing Amazon EC2 KeyPair name to enable SSH access to the instances. Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: Must be the name of an existing Amazon EC2 KeyPair. ShouldRoll: Type: String Default: 'false' Description: Should roll when updating. ShouldUpdateTargetCapacity: Type: String Default: 'true' AllowedValues: - 'false' - 'true' Description: Should update target capacity on group update. AWSAccountType: Description: Type of AWS account the resources are created in. Type: String AllowedValues: - AWSChina - AWS Default: AWS ElastigroupName: Type: String Default: ElastigroupPartnerSolution Description: Provide a name for your Elastigroup. Mappings: AWSAccountTypeToDetails: AWSChina: ServiceTokenAccount: '779522903477' EC2ServiceEndpoint: ec2.amazonaws.com.cn ArnPrefix: arn:aws-cn AWS: ServiceTokenAccount: '178579023202' EC2ServiceEndpoint: ec2.amazonaws.com ArnPrefix: arn:aws RegionMap: af-south-1: AMI: ami-064cc455f8a1ef504 ap-east-1: AMI: ami-f85b1989 ap-northeast-1: AMI: ami-0b2c2a754d5b4da22 ap-northeast-2: AMI: ami-0493ab99920f410fc ap-northeast-3: AMI: ami-01344f6f63a4decc1 ap-south-1: AMI: ami-03cfb5e1fb4fac428 ap-southeast-1: AMI: ami-0ba35dc9caf73d1c7 ap-southeast-2: AMI: ami-0ae99b503e8694028 ca-central-1: AMI: ami-0803e21a2ec22f953 cn-north-1: AMI: ami-07a3f215cc90c889c cn-northwest-1: AMI: ami-0a3b3b10f714a0ff4 eu-central-1: AMI: ami-0474863011a7d1541 eu-north-1: AMI: ami-0de4b8910494dba0f eu-south-1: AMI: ami-08427144fe9ebdef6 eu-west-1: AMI: ami-015232c01a82b847b eu-west-2: AMI: ami-0765d48d7e15beb93 eu-west-3: AMI: ami-0caf07637eda19d9c me-south-1: AMI: ami-0744743d80915b497 sa-east-1: AMI: ami-0a52e8a6018e92bb0 us-east-1: AMI: ami-032930428bf1abbff us-east-2: AMI: ami-027cab9a7bf0155df us-west-1: AMI: ami-088c153f74339f34c us-west-2: AMI: ami-01fee56b22f308154 Resources: ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Subnets: !Ref 'Subnets' ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref 'ALBTargetGroup' LoadBalancerArn: !Ref 'ApplicationLoadBalancer' Port: '80' Protocol: HTTP ALBListenerRule1: Type: AWS::ElasticLoadBalancingV2::ListenerRule Properties: Actions: - Type: forward TargetGroupArn: !Ref 'ALBTargetGroup' Conditions: - Field: http-header HttpHeaderConfig: HttpHeaderName: User-Agent Values: - Chrome ListenerArn: !Ref 'ALBListener' Priority: 1 ALBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 3 Port: 80 Protocol: HTTP UnhealthyThresholdCount: 5 VpcId: !Ref 'VpcId' InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable SSH access and HTTP access on the inbound port. SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' SourceSecurityGroupId: !Select - 0 - !GetAtt 'ApplicationLoadBalancer.SecurityGroups' - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: '0.0.0.0/0' Description: Allow SSH access to any IP. VpcId: !Ref 'VpcId' SpotinstElastigroup: Type: Custom::elasticgroup Properties: ServiceToken: !Sub - ${ArnPrefix}:lambda:${AWS::Region}:${ServiceTokenAccount}:function:spotinst-cloudformation - ArnPrefix: !FindInMap - AWSAccountTypeToDetails - !Ref 'AWSAccountType' - ArnPrefix ServiceTokenAccount: !FindInMap - AWSAccountTypeToDetails - !Ref 'AWSAccountType' - ServiceTokenAccount accessToken: !Ref 'AccessToken' accountId: !Ref 'AccountId' updatePolicy: shouldRoll: !Ref 'ShouldRoll' rollConfig: batchSizePercentage: 50 gracePeriod: 600 shouldUpdateTargetCapacity: !Ref 'ShouldUpdateTargetCapacity' group: name: !Ref 'ElastigroupName' region: !Ref 'AWS::Region' strategy: risk: 100 availabilityVsCost: balanced drainingTimeout: 120 fallbackToOd: true revertToSpot: performAt: always capacity: target: 2 minimum: 1 maximum: 10 unit: instance scaling: target: - policyName: Target CPU 50 namespace: AWS/EC2 metricName: CPUUtilization statistic: average unit: percent target: 50 cooldown: 300 predictive: mode: FORECAST_AND_SCALE compute: instanceTypes: ondemand: t2.medium spot: - t2.micro - t2.small - t2.medium - t2.large - t2.xlarge - t2.2xlarge subnetIds: !Ref 'Subnets' product: Linux/UNIX launchSpecification: loadBalancersConfig: {} securityGroupIds: - !Ref 'InstanceSecurityGroup' monitoring: false ebsOptimized: false imageId: !FindInMap - RegionMap - !Ref 'AWS::Region' - AMI keyPair: !Ref 'KeyPair' userData: IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCAteSBodHRwZC54ODZfNjQKc2VydmljZSBodHRwZCBzdGFydAplY2hvICJXZWxjb21lIHRvIEVsYXN0aWdyb3VwIHR1dG9yaWFsLiIgPiAvdmFyL3d3dy9odG1sL2luZGV4Lmh0bWw= tags: - tagKey: Creator tagValue: Spot tenancy: default itf: weightStrategy: vcpu fixedTargetGroups: false loadBalancers: - loadBalancerArn: !Ref 'ApplicationLoadBalancer' listenerRules: - ruleArn: !Ref 'ALBListenerRule1' targetGroupConfig: vpcId: !Ref 'VpcId' protocol: HTTP port: 80 protocolVersion: HTTP1 healthCheckProtocol: HTTP healthCheckPath: / healthCheckPort: traffic-port healthCheckTimeoutSeconds: 5 healthyThresholdCount: 5 unhealthyThresholdCount: 2 healthCheckIntervalSeconds: 30 matcher: httpCode: '200' migrationHealthinessThreshold: 50 scheduling: tasks: - taskType: scale cronExpression: '0 0 * * 6' scaleTargetCapacity: 0 scaleMinCapacity: 0 scaleMaxCapacity: 0 isEnabled: true - taskType: scale cronExpression: '0 0 * * 1' scaleTargetCapacity: 2 scaleMinCapacity: 1 scaleMaxCapacity: 10 isEnabled: true Outputs: ElastigroupId: Value: !Ref 'SpotinstElastigroup' ApplicationLoadBalancer: Value: !Ref 'ApplicationLoadBalancer'