From dee0e5a278f2df5dcccaaafc48eab374a32cd62f Mon Sep 17 00:00:00 2001 From: Michael Robinson Date: Fri, 15 Jul 2016 20:39:12 +1200 Subject: [PATCH 1/8] Updated LambCI access policy modification section --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d4af9c7..f5c5a8a 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,19 @@ permissions something like this: ```json { - "Effect": "Allow", - "Action": "ecs:RunTask", - "Resource": "arn:aws:ecs:*:*:task-definition/lambci-ecs-BuildTask-1PVABCDEFKFT" + "PolicyName": "LambCIECS", + "PolicyDocument": { + "Statement": { + "Effect": "Allow", + "Action": "ecs:RunTask", + "Resource": "arn:aws:ecs:*:*:task-definition/lambci-ecs-BuildTask-1PVABCDEFKFT" + } + } } ``` +This block should be added as part of the `LambdaExecution > Properties > Policies` section of the `lambci` template. + Where you replace the resource with the name of the ECS task definition created in your `lambci-ecs` stack. Then in the project you want to build using ECS, you'll need to ensure the following LambCI config settings are given: From 753be559cc56b79158223ab24953981093d5379d Mon Sep 17 00:00:00 2001 From: Michael Robinson Date: Fri, 15 Jul 2016 20:44:18 +1200 Subject: [PATCH 2/8] Updated resource value replacement section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5c5a8a..ca943c9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ permissions something like this: This block should be added as part of the `LambdaExecution > Properties > Policies` section of the `lambci` template. -Where you replace the resource with the name of the ECS task definition created in your `lambci-ecs` stack. +Replace the `Resource` value with the name of the ECS task definition created in your `lambci-ecs` stack. Then in the project you want to build using ECS, you'll need to ensure the following LambCI config settings are given: From f75ecfd38b994a2e7aca971c3191e695304a39c5 Mon Sep 17 00:00:00 2001 From: Michael Robinson Date: Fri, 15 Jul 2016 20:57:28 +1200 Subject: [PATCH 3/8] Added screenshots and clearer instructions for AWS noobs like myself --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ca943c9..f3d969b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ # LambCI ECS cluster and Docker image More documentation should be coming soon, but to get up and running quickly, -launch the `cluster.template` file in CloudFormation and give your stack a name like `lambci-ecs` +launch the `cluster.template` file in CloudFormation and give your stack a name like `lambci-ecs`. (You should have already created a LambCI stack as documented at https://github.com/lambci/lambci) This will create an auto-scaling group and an ECS cluster and task definition, which you can find in the AWS console from `Services > EC2 Container Service` +LambCI will automatically send builds to the ECS stack if a `Dockerfile.test` is present in the root of the repository. + ## LambCI configuration You'll need to give the Lambda function in your LambCI stack access to run the task, so will need add to IAM @@ -30,6 +32,10 @@ This block should be added as part of the `LambdaExecution > Properties > Polici Replace the `Resource` value with the name of the ECS task definition created in your `lambci-ecs` stack. +![Example resource location](http://i.imgur.com/3U7NHQr.png) + +## Project configuration + Then in the project you want to build using ECS, you'll need to ensure the following LambCI config settings are given: ```js @@ -41,6 +47,8 @@ Then in the project you want to build using ECS, you'll need to ensure the follo } ``` -(replacing with the actual names of your cluster and task) +(replacing with the actual names of your ECS cluster and task) + +![Example cluster and task location](http://i.imgur.com/DKgcdBU.png) These are normal LambCI config settings which you can set in your `.lambci.js[on]` file or in the config DB. From c0d8017120d237a35485c4e1f23a3115f9401c3b Mon Sep 17 00:00:00 2001 From: Michael Robinson Date: Fri, 15 Jul 2016 20:58:31 +1200 Subject: [PATCH 4/8] Clarified dockerfile.test usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3d969b..29eda5c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ launch the `cluster.template` file in CloudFormation and give your stack a name This will create an auto-scaling group and an ECS cluster and task definition, which you can find in the AWS console from `Services > EC2 Container Service` -LambCI will automatically send builds to the ECS stack if a `Dockerfile.test` is present in the root of the repository. +LambCI-ECS will look for a `Dockerfile.test` is in the root of the repository. This is where you put your test/build instructions. ## LambCI configuration From 1a070dfca0278a324c41816134f2634b943dfa2b Mon Sep 17 00:00:00 2001 From: Joy Prakash Sharma Date: Fri, 16 Dec 2016 11:31:33 +0530 Subject: [PATCH 5/8] Adding Launch Config to use VPC T2 EC2 requires to be launched under a VPC. Otherwise it Autoscaling fails to launch EC2 and complains as The specified instance type can only be used in a VPC. A subnet ID or network interface ID is required to carry out the request. Launching EC2 instance failed. --- cluster.template | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/cluster.template b/cluster.template index 5edced3..4e3ca80 100644 --- a/cluster.template +++ b/cluster.template @@ -7,6 +7,24 @@ "Type": "String", "Default": "t2.micro", "ConstraintDescription": "must be a valid EC2 instance type." + }, + + "VpcId" : { + "Type" : "AWS::EC2::VPC::Id", + "Description" : "VpcId of your existing Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be the VPC Id of an existing Virtual Private Cloud." + }, + + "Subnets" : { + "Type" : "List", + "Description" : "The list of SubnetIds in your Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be a list of an existing subnets in the selected Virtual Private Cloud." + }, + + "AZs" : { + "Type" : "List", + "Description" : "The list of AvailabilityZones for your Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be a list if valid EC2 availability zones for the selected Virtual Private Cloud" } }, "Mappings": { @@ -51,7 +69,8 @@ "AutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "Properties": { - "AvailabilityZones": {"Fn::GetAZs": ""}, + "AvailabilityZones": {"Ref": "AZs"}, + "VPCZoneIdentifier" : { "Ref" : "Subnets" }, "LaunchConfigurationName": {"Ref": "LaunchConfig"}, "DesiredCapacity": "1", "MinSize": "0", @@ -66,9 +85,11 @@ "LaunchConfig": { "Type": "AWS::AutoScaling::LaunchConfiguration", "Properties": { + "AssociatePublicIpAddress" : "true", "ImageId": {"Fn::FindInMap": ["EcsAmisByRegion", {"Ref": "AWS::Region"}, "ami"]}, "IamInstanceProfile": {"Ref": "InstanceProfile"}, "InstanceType": {"Ref": "InstanceType"}, + "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], "UserData": { "Fn::Base64": { "Fn::Join": ["", [ @@ -80,6 +101,16 @@ } } } + }, + "InstanceSecurityGroup" : { + "Type" : "AWS::EC2::SecurityGroup", + "Properties" : { + "GroupDescription" : "Enable HTTP access and SSH access", + "VpcId" : { "Ref" : "VpcId" }, + "SecurityGroupIngress" : [ + { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0" } + ] + } }, "InstanceProfile": { "Type": "AWS::IAM::InstanceProfile", @@ -131,4 +162,3 @@ } } } - From 894f6c4740914f37caecc62d7ed0f4ad8f14b3a9 Mon Sep 17 00:00:00 2001 From: Joy Prakash Sharma Date: Mon, 19 Dec 2016 18:04:33 +0530 Subject: [PATCH 6/8] Spot Pricing Input added --- cluster.spot.template | 170 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 cluster.spot.template diff --git a/cluster.spot.template b/cluster.spot.template new file mode 100644 index 0000000..69769c0 --- /dev/null +++ b/cluster.spot.template @@ -0,0 +1,170 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "LambCI build servers running on ECS", + "Parameters": { + "InstanceType": { + "Description": "EC2 instance type (t2.micro, t2.medium, t2.large, etc)", + "Type": "String", + "Default": "t2.micro", + "ConstraintDescription": "must be a valid EC2 instance type." + }, + + "SpotPrice" : { + "Type" : Number, + "Description" : "Spot Price based on your EC2 type", + }, + + "VpcId" : { + "Type" : "AWS::EC2::VPC::Id", + "Description" : "VpcId of your existing Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be the VPC Id of an existing Virtual Private Cloud." + }, + + "Subnets" : { + "Type" : "List", + "Description" : "The list of SubnetIds in your Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be a list of an existing subnets in the selected Virtual Private Cloud." + }, + + "AZs" : { + "Type" : "List", + "Description" : "The list of AvailabilityZones for your Virtual Private Cloud (VPC)", + "ConstraintDescription" : "must be a list if valid EC2 availability zones for the selected Virtual Private Cloud" + } + }, + "Mappings": { + "EcsAmisByRegion": { + "us-east-1": {"ami": "ami-a88a46c5"}, + "us-west-1": {"ami": "ami-34a7e354"}, + "us-west-2": {"ami": "ami-ae0acdce"}, + "eu-west-1": {"ami": "ami-ccd942bf"}, + "eu-central-1": {"ami": "ami-4a5eb625"}, + "ap-northeast-1": {"ami": "ami-4aab5d2b"}, + "ap-southeast-1": {"ami": "ami-24c71547"}, + "ap-southeast-2": {"ami": "ami-0bf2da68"} + } + }, + "Resources": { + "Cluster": { + "Type": "AWS::ECS::Cluster" + }, + "BuildTask": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [{ + "Name": "build", + "Image": "lambci/ecs", + "Memory": 450, + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": {"Ref": "EcsLogs"}, + "awslogs-region": {"Ref": "AWS::Region"} + } + }, + "Environment": [{"Name": "LOG_GROUP", "Value": {"Ref": "EcsLogs"}}], + "MountPoints": [{"SourceVolume": "docker-socket", "ContainerPath": "/var/run/docker.sock"}] + }], + "Volumes": [{"Name": "docker-socket", "Host": {"SourcePath": "/var/run/docker.sock"}}] + } + }, + "EcsLogs": { + "Type": "AWS::Logs::LogGroup" + }, + "AutoScalingGroup": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "AvailabilityZones": {"Ref": "AZs"}, + "VPCZoneIdentifier" : { "Ref" : "Subnets" }, + "LaunchConfigurationName": {"Ref": "LaunchConfig"}, + "DesiredCapacity": "1", + "MinSize": "0", + "MaxSize": "4" + }, + "CreationPolicy": { + "ResourceSignal": { + "Count": "1" + } + } + }, + "LaunchConfig": { + "Type": "AWS::AutoScaling::LaunchConfiguration", + "Properties": { + "AssociatePublicIpAddress" : "true", + "SpotPrice": { "Ref" : "SpotPrice" }, + "ImageId": {"Fn::FindInMap": ["EcsAmisByRegion", {"Ref": "AWS::Region"}, "ami"]}, + "IamInstanceProfile": {"Ref": "InstanceProfile"}, + "InstanceType": {"Ref": "InstanceType"}, + "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], + "UserData": { + "Fn::Base64": { + "Fn::Join": ["", [ + "#!/bin/bash\n", + "echo ECS_CLUSTER=", {"Ref": "Cluster"}, " >> /etc/ecs/ecs.config\n", + "yum install -y aws-cfn-bootstrap\n", + "/opt/aws/bin/cfn-signal -e $? --resource AutoScalingGroup --stack ", {"Ref": "AWS::StackName"}, " --region ", {"Ref": "AWS::Region"} + ]] + } + } + } + }, + "InstanceSecurityGroup" : { + "Type" : "AWS::EC2::SecurityGroup", + "Properties" : { + "GroupDescription" : "Enable HTTP access and SSH access", + "VpcId" : { "Ref" : "VpcId" }, + "SecurityGroupIngress" : [ + { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0" } + ] + } + }, + "InstanceProfile": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Path": "/", + "Roles": [{"Ref": "InstanceRole"}] + } + }, + "InstanceRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": { + "Effect": "Allow", + "Principal": {"Service": "ec2.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + }, + "Policies": [{ + "PolicyName": "RunEcs", + "PolicyDocument": { + "Statement": { + "Effect": "Allow", + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:DiscoverPollEndpoint", + "ecs:Poll", + "ecs:RegisterContainerInstance", + "ecs:StartTelemetrySession", + "ecs:Submit*" + ], + "Resource": "*" + } + } + },{ + "PolicyName": "WriteLogs", + "PolicyDocument": { + "Statement": { + "Effect": "Allow", + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "*" + } + } + }] + } + } + } +} From b64850fdf2161bb54e3da4b0a1a8213632ff2bd8 Mon Sep 17 00:00:00 2001 From: Joy Prakash Sharma Date: Mon, 19 Dec 2016 19:46:05 +0530 Subject: [PATCH 7/8] Removed wrong syntax for policy --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 29eda5c..2176834 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,11 @@ permissions something like this: ```json { - "PolicyName": "LambCIECS", - "PolicyDocument": { "Statement": { "Effect": "Allow", "Action": "ecs:RunTask", "Resource": "arn:aws:ecs:*:*:task-definition/lambci-ecs-BuildTask-1PVABCDEFKFT" } - } } ``` From ce0e59ecbf9d99e028908fa793e27badda15439c Mon Sep 17 00:00:00 2001 From: Joy Prakash Sharma Date: Mon, 19 Dec 2016 19:51:38 +0530 Subject: [PATCH 8/8] Spot EC2 usage --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2176834..9842c9e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ More documentation should be coming soon, but to get up and running quickly, launch the `cluster.template` file in CloudFormation and give your stack a name like `lambci-ecs`. +You can also use `cluster.spot.template` to use ECS under Spot Instances. (You should have already created a LambCI stack as documented at https://github.com/lambci/lambci) @@ -49,3 +50,4 @@ Then in the project you want to build using ECS, you'll need to ensure the follo ![Example cluster and task location](http://i.imgur.com/DKgcdBU.png) These are normal LambCI config settings which you can set in your `.lambci.js[on]` file or in the config DB. +