Skip to content

Instantly share code, notes, and snippets.

@murillodigital
Created March 28, 2016 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save murillodigital/b3aea3d5593e313c727b to your computer and use it in GitHub Desktop.
Save murillodigital/b3aea3d5593e313c727b to your computer and use it in GitHub Desktop.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "ECS Cluster Stack - Version 0.1.0",
"Parameters": {
"ParameterNetworkStackName": {
"Type": "String",
"Description": "Name for networks stack",
"Default": "QwinixNetworkStack"
},
"ParameterDesiredClusterSize": {
"Type": "String",
"Description": "Number of instances to bring up",
"Default": "2"
}
},
"Resources": {
"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": ["lambda.amazonaws.com"]},
"Action": ["sts:AssumeRole"]
}]
},
"Path": "/",
"Policies": [{
"PolicyName": "root",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": ["cloudformation:DescribeStacks"],
"Resource": "*"
}]
}
}]
}
},
"LookupStackOutputs": {
"Type": "AWS::Lambda::Function",
"DependsOn": "LambdaExecutionRole",
"Properties": {
"Description": "Retrieve stack network information",
"Code": {
"ZipFile": { "Fn::Join": ["\n", [
"var response = require('cfn-response');",
"exports.handler = function(event, context) {",
" console.log('REQUEST RECEIVED:\\n', JSON.stringify(event));",
" if (event.RequestType == 'Delete') {",
" response.send(event, context, response.SUCCESS);",
" return;",
" }",
" var stackName = event.ResourceProperties.StackName;",
" var responseData = {};",
" if (stackName) {",
" var aws = require('aws-sdk');",
" var cfn = new aws.CloudFormation();",
" cfn.describeStacks({StackName: stackName}, function(err, data) {",
" if (err) {",
" responseData = {Error: 'DescribeStacks call failed'};",
" console.log(responseData.Error + ':\\n', err);",
" response.send(event, context, response.FAILED, responseData);",
" }",
" else {",
" data.Stacks[0].Outputs.forEach(function(output) {",
" responseData[output.OutputKey] = output.OutputValue;",
" });",
" response.send(event, context, response.SUCCESS, responseData);",
" }",
" });",
" } else {",
" responseData = {Error: 'Stack name not specified'};",
" console.log(responseData.Error);",
" response.send(event, context, response.FAILED, responseData);",
" }",
"};"
]]}
},
"Handler": "index.handler",
"Runtime": "nodejs",
"Timeout": "45",
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] }
}
},
"NetworkInfo": {
"Type": "Custom::NetworkInfo",
"Properties": {
"ServiceToken": { "Fn::GetAtt": ["LookupStackOutputs", "Arn"] },
"StackName": { "Ref": "ParameterNetworkStackName" }
}
},
"ECSCluster": {
"Type": "AWS::ECS::Cluster"
},
"ECSAutoScalingGroup": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"DesiredCapacity": "2",
"LaunchConfigurationName": {"Ref": "ECSLaunchConfiguration"},
"MinSize": "1",
"MaxSize": "10",
"VPCZoneIdentifier": [{"Fn::GetAtt": ["NetworkInfo", "PrivateSubnet"]}]
}
},
"ECSLaunchConfiguration": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"AssociatePublicIpAddress": "false",
"ImageId": "ami-63b25203",
"InstanceType": "c4.large",
"KeyName": "ops-cr",
"SecurityGroups": [{"Ref": "ECSPrivateSecurityGroup"}],
"IamInstanceProfile": {"Ref": "ECSInstanceProfile"},
"UserData": {
"Fn::Base64": {
"Fn::Join": ["", [
"#!/bin/bash\n",
"ifconfig eth0 mtu 1500 up\n",
"yum install -y ecs-init\n",
"usermod -a -G docker ec2-user\n",
"echo ECS_CLUSTER=", {"Ref": "ECSCluster"}, " > /etc/ecs/ecs.config\n",
"service docker start\n",
"start ecs\n"
]]
}
}
}
},
"ECSInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [{"Ref": "ECSInstanceRole"}]
}
},
"ECSInstanceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "ECSClusterPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"ecs:*",
"ecr:*"
],
"Resource": "*"
}
]
}
}
]
}
},
"ECSServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "ECSServicePolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"ecs:*",
"ecr:*"
],
"Resource": "*"
}
]
}
}
]
}
},
"ECSPrivateSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "ECS Cluster - Private",
"VpcId": {"Fn::GetAtt": ["NetworkInfo", "VPC"]},
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"FromPort": "0",
"ToPort": "65535",
"IpProtocol": "tcp"
}
]
}
},
"ECSNatIngressRule": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties": {
"FromPort": "0",
"ToPort": "65535",
"IpProtocol": "tcp",
"SourceSecurityGroupId": {"Ref": "ECSPrivateSecurityGroup"},
"GroupId": {"Fn::GetAtt": ["NetworkInfo", "NATSecurityGroup"]}
}
},
"ECSPublicSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "ECS Cluster - Public",
"VpcId": {"Fn::GetAtt": ["NetworkInfo", "VPC"]},
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"FromPort": "80",
"ToPort": "80",
"IpProtocol": "tcp"
}
]
}
},
"ECSPublicLoadBalancer": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"Listeners": [
{
"InstancePort": "80",
"InstanceProtocol": "HTTP",
"LoadBalancerPort": "80",
"Protocol": "HTTP"
}
],
"SecurityGroups": [
{"Ref": "ECSPublicSecurityGroup"}
],
"Subnets": [
{"Fn::GetAtt": ["NetworkInfo", "PublicSubnet"]}
]
}
},
"ECSTaskDefinition": {
"Type": "AWS::ECS::TaskDefinition",
"Properties": {
"ContainerDefinitions": [
{
"Cpu": "1024",
"Image": "571780515387.dkr.ecr.us-east-1.amazonaws.com/empower_retirement:latest",
"Memory": "256",
"Name": "empower_retirement",
"PortMappings": [
{
"ContainerPort": "80",
"HostPort": "80"
}
]
}
],
"Volumes": [
{
"Name": "my-vol"
}
]
}
},
"ECSService": {
"Type": "AWS::ECS::Service",
"Properties": {
"Cluster": {"Ref": "ECSCluster"},
"DesiredCount": "1",
"LoadBalancers": [
{
"ContainerName": "empower_retirement",
"ContainerPort": "80",
"LoadBalancerName": {"Ref": "ECSPublicLoadBalancer"}
}
],
"Role": {"Ref": "ECSServiceRole"},
"TaskDefinition": {"Ref": "ECSTaskDefinition"}
}
}
},
"Outputs": {
"ECSClusterName": {
"Description": "Name of created ECS Cluster",
"Value": {"Ref": "ECSCluster"}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment