Last active
October 8, 2018 13:45
-
-
Save dcvz/4770965e548407d64773cb4dc01bea0d to your computer and use it in GitHub Desktop.
Setup Buildkite Agent Amazon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "Buildkite stack v3.3.1", | |
"Parameters": { | |
"KeyName": { | |
"Description": "SSH keypair used to access the buildkite instances", | |
"Type": "AWS::EC2::KeyPair::KeyName", | |
"MinLength": 1 | |
}, | |
"BuildkiteAgentRelease": { | |
"Type": "String", | |
"AllowedValues": [ | |
"stable", | |
"beta", | |
"edge" | |
], | |
"Default": "stable" | |
}, | |
"BuildkiteAgentToken": { | |
"Description": "Buildkite agent registration token", | |
"Type": "String", | |
"NoEcho": true, | |
"MinLength": 1 | |
}, | |
"BuildkiteAgentTags": { | |
"Description": "Additional tags seperated by commas to provide to the agent. E.g os=linux,llamas=always", | |
"Type": "String", | |
"Default": "" | |
}, | |
"BuildkiteAgentExperiments": { | |
"Description": "Agent experiments to enable, comma delimited. See https://github.com/buildkite/agent/blob/master/EXPERIMENTS.md.", | |
"Type": "String", | |
"Default": "" | |
}, | |
"BuildkiteQueue": { | |
"Description": "Queue name that agents will use, targeted in pipeline steps using \"queue={value}\"", | |
"Type": "String", | |
"Default": "default", | |
"MinLength": 1 | |
}, | |
"AgentsPerInstance": { | |
"Description": "Number of Buildkite agents to run on each instance", | |
"Type": "Number", | |
"Default": 1, | |
"MinValue": 1 | |
}, | |
"SecretsBucket": { | |
"Description": "Optional - Name of an existing S3 bucket containing pipeline secrets (Created if left blank)", | |
"Type": "String", | |
"Default": "" | |
}, | |
"ArtifactsBucket": { | |
"Description": "Optional - Name of an existing S3 bucket for build artifact storage", | |
"Type": "String", | |
"Default": "" | |
}, | |
"BootstrapScriptUrl": { | |
"Description": "Optional - HTTPS or S3 URL to run on each instance during boot", | |
"Type": "String", | |
"Default": "" | |
}, | |
"AuthorizedUsersUrl": { | |
"Description": "Optional - HTTPS or S3 URL to periodically download ssh authorized_keys from", | |
"Type": "String", | |
"Default": "" | |
}, | |
"VpcId": { | |
"Type": "String", | |
"Description": "Optional - Id of an existing VPC to launch instances into. Leave blank to have a new VPC created", | |
"Default": "" | |
}, | |
"Subnets": { | |
"Type": "CommaDelimitedList", | |
"Description": "Optional - Comma separated list of two existing VPC subnet ids where EC2 instances will run. Required if setting VpcId.", | |
"Default": "" | |
}, | |
"AvailabilityZones": { | |
"Type": "CommaDelimitedList", | |
"Description": "Optional - Comma separated list of AZs that subnets are created in (if Subnets parameter is not specified)", | |
"Default": "" | |
}, | |
"InstanceType": { | |
"Description": "Instance type", | |
"Type": "String", | |
"Default": "t2.nano", | |
"MinLength": 1 | |
}, | |
"SpotPrice": { | |
"Description": "Spot bid price to use for the instances. 0 means normal (non-spot) instances", | |
"Type": "String", | |
"Default": 0 | |
}, | |
"MaxSize": { | |
"Description": "Maximum number of instances", | |
"Type": "Number", | |
"Default": 10, | |
"MinValue": 1 | |
}, | |
"MinSize": { | |
"Description": "Minimum number of instances", | |
"Type": "Number", | |
"Default": 0 | |
}, | |
"ScaleUpAdjustment": { | |
"Description": "Number of instances to add on scale up events (ScheduledJobsCount > 0 for 1 min)", | |
"Type": "Number", | |
"Default": 5, | |
"MinValue": 0 | |
}, | |
"ScaleDownAdjustment": { | |
"Description": "Number of instances to remove on scale down events (UnfinishedJobs == 0 for ScaleDownPeriod)", | |
"Type": "Number", | |
"Default": -1, | |
"MaxValue": 0 | |
}, | |
"ScaleDownPeriod": { | |
"Description": "Number of seconds UnfinishedJobs must equal 0 before scale down", | |
"Type": "Number", | |
"Default": 1800 | |
}, | |
"RootVolumeSize": { | |
"Description": "Size of each instance's root EBS volume (in GB)", | |
"Type": "Number", | |
"Default": 250, | |
"MinValue": 10 | |
}, | |
"SecurityGroupId": { | |
"Type": "String", | |
"Description": "Optional - Security group id to assign to instances", | |
"Default": "" | |
}, | |
"ImageId": { | |
"Type": "String", | |
"Description": "Optional - Custom AMI to use for instances (must be based on the stack's AMI)", | |
"Default": "" | |
}, | |
"ManagedPolicyARN": { | |
"Type": "CommaDelimitedList", | |
"Description": "Optional - Comma separated list of managed IAM policy ARNs to attach to the instance role", | |
"Default": "" | |
}, | |
"InstanceRoleName": { | |
"Type": "String", | |
"Description": "Optional - A name for the IAM Role attached to the Instance Profile", | |
"Default": "" | |
}, | |
"ECRAccessPolicy": { | |
"Type": "String", | |
"Description": "ECR access policy to give container instances", | |
"AllowedValues": [ | |
"none", | |
"readonly", | |
"poweruser", | |
"full" | |
], | |
"Default": "none" | |
}, | |
"AssociatePublicIpAddress": { | |
"Type": "String", | |
"Description": "Associate instances with public IP addresses", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "true" | |
}, | |
"EnableSecretsPlugin": { | |
"Type": "String", | |
"Description": "Enables s3-secrets plugin for all pipelines", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "true" | |
}, | |
"EnableECRPlugin": { | |
"Type": "String", | |
"Description": "Enables ecr plugin for all pipelines", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "true" | |
}, | |
"EnableDockerLoginPlugin": { | |
"Type": "String", | |
"Description": "Enables docker-login plugin for all pipelines", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "true" | |
}, | |
"EnableDockerUserNamespaceRemap": { | |
"Type": "String", | |
"Description": "Enables Docker user namespace remapping so docker runs as buildkite-agent", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "true" | |
}, | |
"EnableCostAllocationTags": { | |
"Type": "String", | |
"Description": "Enables AWS Cost Allocation tags for all resources in the stack. See https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html", | |
"AllowedValues": [ | |
true, | |
false | |
], | |
"Default": "false" | |
}, | |
"CostAllocationTagName": { | |
"Type": "String", | |
"Description": "The name of the Cost Allocation Tag used for billing purposes", | |
"Default": "aws:createdBy" | |
}, | |
"CostAllocationTagValue": { | |
"Type": "String", | |
"Description": "The value of the Cost Allocation Tag used for billing purposes", | |
"Default": "buildkite-elastic-ci-stack-for-aws" | |
} | |
}, | |
"Mappings": { | |
"ECRManagedPolicy": { | |
"none": { | |
"Policy": "" | |
}, | |
"readonly": { | |
"Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" | |
}, | |
"poweruser": { | |
"Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser" | |
}, | |
"full": { | |
"Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess" | |
} | |
}, | |
"MetricsLambdaBucket": { | |
"us-east-1": { | |
"Bucket": "buildkite-metrics" | |
}, | |
"us-east-2": { | |
"Bucket": "buildkite-metrics-us-east-2" | |
}, | |
"us-west-1": { | |
"Bucket": "buildkite-metrics-us-west-1" | |
}, | |
"us-west-2": { | |
"Bucket": "buildkite-metrics-us-west-2" | |
}, | |
"eu-west-1": { | |
"Bucket": "buildkite-metrics-eu-west-1" | |
}, | |
"eu-west-2": { | |
"Bucket": "buildkite-metrics-eu-west-2" | |
}, | |
"eu-central-1": { | |
"Bucket": "buildkite-metrics-eu-central-1" | |
}, | |
"ap-northeast-1": { | |
"Bucket": "buildkite-metrics-ap-northeast-1" | |
}, | |
"ap-northeast-2": { | |
"Bucket": "buildkite-metrics-ap-northeast-2" | |
}, | |
"ap-southeast-1": { | |
"Bucket": "buildkite-metrics-ap-southeast-1" | |
}, | |
"ap-southeast-2": { | |
"Bucket": "buildkite-metrics-ap-southeast-2" | |
}, | |
"ap-south-1": { | |
"Bucket": "buildkite-metrics-ap-south-1" | |
}, | |
"sa-east-1": { | |
"Bucket": "buildkite-metrics-sa-east-1" | |
} | |
}, | |
"AWSRegion2AMI": { | |
"us-east-1": { | |
"AMI": "ami-0ccbb1be706551583" | |
}, | |
"us-east-2": { | |
"AMI": "ami-04c89a93551decccd" | |
}, | |
"us-west-1": { | |
"AMI": "ami-0b850adc5401d6252" | |
}, | |
"us-west-2": { | |
"AMI": "ami-008bac39f038b021f" | |
}, | |
"eu-west-1": { | |
"AMI": "ami-0a65104d2b5bbeb48" | |
}, | |
"eu-west-2": { | |
"AMI": "ami-0c1fdbe3436b6d7a1" | |
}, | |
"eu-central-1": { | |
"AMI": "ami-0674dcf71667602e2" | |
}, | |
"ap-northeast-1": { | |
"AMI": "ami-0dcde5424bc3022b8" | |
}, | |
"ap-northeast-2": { | |
"AMI": "ami-0184af1fc64e3c966" | |
}, | |
"ap-southeast-1": { | |
"AMI": "ami-0dfeb86ce0828898c" | |
}, | |
"ap-southeast-2": { | |
"AMI": "ami-0b216a9fc227ebf67" | |
}, | |
"ap-south-1": { | |
"AMI": "ami-0dad5eb943e2812bd" | |
}, | |
"sa-east-1": { | |
"AMI": "ami-0e32b90122bf621c8" | |
} | |
} | |
}, | |
"Conditions": { | |
"UseSpotInstances": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "SpotPrice" | |
}, | |
0 | |
] | |
} | |
] | |
}, | |
"CreateVpcResources": { | |
"Fn::Equals": [ | |
{ | |
"Ref": "VpcId" | |
}, | |
"" | |
] | |
}, | |
"CreateSecurityGroup": { | |
"Fn::Equals": [ | |
{ | |
"Ref": "SecurityGroupId" | |
}, | |
"" | |
] | |
}, | |
"CreateSecretsBucket": { | |
"Fn::Equals": [ | |
{ | |
"Ref": "SecretsBucket" | |
}, | |
"" | |
] | |
}, | |
"SetInstanceRoleName": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "InstanceRoleName" | |
}, | |
"" | |
] | |
} | |
] | |
}, | |
"UseSpecifiedSecretsBucket": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "SecretsBucket" | |
}, | |
"" | |
] | |
} | |
] | |
}, | |
"UseSpecifiedAvailabilityZones": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Fn::Join": [ | |
"", | |
{ | |
"Ref": "AvailabilityZones" | |
} | |
] | |
}, | |
"" | |
] | |
} | |
] | |
}, | |
"UseArtifactsBucket": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "ArtifactsBucket" | |
}, | |
"" | |
] | |
} | |
] | |
}, | |
"UseDefaultAMI": { | |
"Fn::Equals": [ | |
{ | |
"Ref": "ImageId" | |
}, | |
"" | |
] | |
}, | |
"UseManagedPolicyARN": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Fn::Join": [ | |
"", | |
{ | |
"Ref": "ManagedPolicyARN" | |
} | |
] | |
}, | |
"" | |
] | |
} | |
] | |
}, | |
"UseECR": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "ECRAccessPolicy" | |
}, | |
"none" | |
] | |
} | |
] | |
}, | |
"UseAutoscaling": { | |
"Fn::Not": [ | |
{ | |
"Fn::Equals": [ | |
{ | |
"Ref": "MaxSize" | |
}, | |
{ | |
"Ref": "MinSize" | |
} | |
] | |
} | |
] | |
}, | |
"CreateMetricsStack": { | |
"Condition": "UseAutoscaling" | |
}, | |
"UseCostAllocationTags": { | |
"Fn::Equals": [ | |
{ | |
"Ref": "EnableCostAllocationTags" | |
}, | |
"true" | |
] | |
}, | |
"HasManagedPolicies": { | |
"Fn::Or": [ | |
{ | |
"Condition": "UseManagedPolicyARN" | |
}, | |
{ | |
"Condition": "UseECR" | |
} | |
] | |
} | |
}, | |
"Resources": { | |
"AgentScaleUpPolicy": { | |
"Type": "AWS::AutoScaling::ScalingPolicy", | |
"Condition": "UseAutoscaling", | |
"Properties": { | |
"AdjustmentType": "ChangeInCapacity", | |
"AutoScalingGroupName": { | |
"Ref": "AgentAutoScaleGroup" | |
}, | |
"Cooldown": 300, | |
"ScalingAdjustment": { | |
"Ref": "ScaleUpAdjustment" | |
} | |
} | |
}, | |
"AgentScaleDownPolicy": { | |
"Type": "AWS::AutoScaling::ScalingPolicy", | |
"Condition": "UseAutoscaling", | |
"Properties": { | |
"AdjustmentType": "ChangeInCapacity", | |
"AutoScalingGroupName": { | |
"Ref": "AgentAutoScaleGroup" | |
}, | |
"Cooldown": 300, | |
"ScalingAdjustment": { | |
"Ref": "ScaleDownAdjustment" | |
} | |
} | |
}, | |
"AgentUtilizationAlarmHigh": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Condition": "UseAutoscaling", | |
"Properties": { | |
"AlarmDescription": "Scale-up if ScheduledJobs > 0 for 1 minute", | |
"MetricName": "ScheduledJobsCount", | |
"Namespace": "Buildkite", | |
"Statistic": "Minimum", | |
"Period": 60, | |
"EvaluationPeriods": 1, | |
"Threshold": 0, | |
"AlarmActions": [ | |
{ | |
"Ref": "AgentScaleUpPolicy" | |
} | |
], | |
"Dimensions": [ | |
{ | |
"Name": "Queue", | |
"Value": { | |
"Ref": "BuildkiteQueue" | |
} | |
} | |
], | |
"ComparisonOperator": "GreaterThanThreshold" | |
} | |
}, | |
"AgentUtilizationAlarmLow": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Condition": "UseAutoscaling", | |
"Properties": { | |
"AlarmDescription": "Scale-down if UnfinishedJobs == 0 for N minutes", | |
"MetricName": "UnfinishedJobsCount", | |
"Namespace": "Buildkite", | |
"Statistic": "Maximum", | |
"Period": { | |
"Ref": "ScaleDownPeriod" | |
}, | |
"EvaluationPeriods": 1, | |
"Threshold": 0, | |
"AlarmActions": [ | |
{ | |
"Ref": "AgentScaleDownPolicy" | |
} | |
], | |
"Dimensions": [ | |
{ | |
"Name": "Queue", | |
"Value": { | |
"Ref": "BuildkiteQueue" | |
} | |
} | |
], | |
"ComparisonOperator": "LessThanOrEqualToThreshold" | |
} | |
}, | |
"IAMInstanceProfile": { | |
"Type": "AWS::IAM::InstanceProfile", | |
"Properties": { | |
"Path": "/", | |
"Roles": [ | |
{ | |
"Ref": "IAMRole" | |
} | |
] | |
} | |
}, | |
"IAMRole": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"RoleName": { | |
"Fn::If": [ | |
"SetInstanceRoleName", | |
{ | |
"Ref": "InstanceRoleName" | |
}, | |
{ | |
"Fn::Sub": "${AWS::StackName}-Role" | |
} | |
] | |
}, | |
"ManagedPolicyArns": { | |
"Fn::If": [ | |
"HasManagedPolicies", | |
{ | |
"Fn::Split": [ | |
",", | |
{ | |
"Fn::Join": [ | |
",", | |
[ | |
{ | |
"Fn::If": [ | |
"UseECR", | |
{ | |
"Fn::FindInMap": [ | |
"ECRManagedPolicy", | |
{ | |
"Ref": "ECRAccessPolicy" | |
}, | |
"Policy" | |
] | |
}, | |
{ | |
"Ref": "AWS::NoValue" | |
} | |
] | |
}, | |
{ | |
"Fn::If": [ | |
"UseManagedPolicyARN", | |
{ | |
"Fn::Join": [ | |
",", | |
{ | |
"Ref": "ManagedPolicyARN" | |
} | |
] | |
}, | |
{ | |
"Ref": "AWS::NoValue" | |
} | |
] | |
} | |
] | |
] | |
} | |
] | |
}, | |
{ | |
"Ref": "AWS::NoValue" | |
} | |
] | |
}, | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ | |
"autoscaling.amazonaws.com", | |
"ec2.amazonaws.com" | |
] | |
}, | |
"Action": "sts:AssumeRole" | |
} | |
] | |
}, | |
"Path": "/" | |
} | |
}, | |
"IAMPolicies": { | |
"Type": "AWS::IAM::Policy", | |
"Properties": { | |
"PolicyName": "InstancePolicy", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"cloudwatch:PutMetricData", | |
"cloudformation:DescribeStackResource", | |
"ec2:DescribeTags", | |
"autoscaling:DescribeAutoScalingInstances", | |
"autoscaling:DescribeLifecycleHooks", | |
"autoscaling:RecordLifecycleActionHeartbeat", | |
"autoscaling:CompleteLifecycleAction", | |
"autoscaling:SetInstanceHealth" | |
], | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents", | |
"logs:DescribeLogStreams" | |
], | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"sqs:*", | |
"sns:Unsubscribe", | |
"sns:Subscribe" | |
], | |
"Resource": "*" | |
} | |
] | |
}, | |
"Roles": [ | |
{ | |
"Ref": "IAMRole" | |
} | |
] | |
} | |
}, | |
"ManagedSecretsLoggingBucket": { | |
"Type": "AWS::S3::Bucket", | |
"Condition": "CreateSecretsBucket", | |
"DeletionPolicy": "Retain", | |
"Properties": { | |
"AccessControl": "LogDeliveryWrite" | |
} | |
}, | |
"ManagedSecretsBucket": { | |
"Type": "AWS::S3::Bucket", | |
"Condition": "CreateSecretsBucket", | |
"DeletionPolicy": "Retain", | |
"Properties": { | |
"LoggingConfiguration": { | |
"DestinationBucketName": { | |
"Ref": "ManagedSecretsLoggingBucket" | |
} | |
}, | |
"VersioningConfiguration": { | |
"Status": "Enabled" | |
} | |
} | |
}, | |
"ManagedSecretsBucketPolicy": { | |
"Type": "AWS::IAM::Policy", | |
"Condition": "CreateSecretsBucket", | |
"Properties": { | |
"PolicyName": "SecretsBucketPolicy", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"s3:Get*", | |
"s3:Get", | |
"s3:List*" | |
], | |
"Resource": [ | |
{ | |
"Fn::Sub": "arn:aws:s3:::${ManagedSecretsBucket}/*" | |
}, | |
{ | |
"Fn::Sub": "arn:aws:s3:::${ManagedSecretsBucket}" | |
} | |
] | |
} | |
] | |
}, | |
"Roles": [ | |
{ | |
"Ref": "IAMRole" | |
} | |
] | |
} | |
}, | |
"UnmanagedSecretsBucketPolicy": { | |
"Type": "AWS::IAM::Policy", | |
"Condition": "UseSpecifiedSecretsBucket", | |
"Properties": { | |
"PolicyName": "SecretsBucketPolicy", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"s3:Get*", | |
"s3:Get", | |
"s3:List*" | |
], | |
"Resource": [ | |
{ | |
"Fn::Sub": "arn:aws:s3:::${SecretsBucket}/*" | |
}, | |
{ | |
"Fn::Sub": "arn:aws:s3:::${SecretsBucket}" | |
} | |
] | |
} | |
] | |
}, | |
"Roles": [ | |
{ | |
"Ref": "IAMRole" | |
} | |
] | |
} | |
}, | |
"ArtifactsBucketPolicies": { | |
"Type": "AWS::IAM::Policy", | |
"Condition": "UseArtifactsBucket", | |
"Properties": { | |
"PolicyName": "ArtifactsBucketPolicy", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"s3:Put*", | |
"s3:List*", | |
"s3:Get*" | |
], | |
"Resource": [ | |
{ | |
"Fn::Sub": "arn:aws:s3:::${ArtifactsBucket}/*" | |
}, | |
{ | |
"Fn::Sub": "arn:aws:s3:::${ArtifactsBucket}" | |
} | |
] | |
} | |
] | |
}, | |
"Roles": [ | |
{ | |
"Ref": "IAMRole" | |
} | |
] | |
} | |
}, | |
"AgentLaunchConfiguration": { | |
"Type": "AWS::AutoScaling::LaunchConfiguration", | |
"Properties": { | |
"AssociatePublicIpAddress": { | |
"Ref": "AssociatePublicIpAddress" | |
}, | |
"SecurityGroups": [ | |
{ | |
"Fn::If": [ | |
"CreateSecurityGroup", | |
{ | |
"Ref": "SecurityGroup" | |
}, | |
{ | |
"Ref": "SecurityGroupId" | |
} | |
] | |
} | |
], | |
"KeyName": { | |
"Ref": "KeyName" | |
}, | |
"IamInstanceProfile": { | |
"Ref": "IAMInstanceProfile" | |
}, | |
"InstanceType": { | |
"Ref": "InstanceType" | |
}, | |
"SpotPrice": { | |
"Fn::If": [ | |
"UseSpotInstances", | |
{ | |
"Ref": "SpotPrice" | |
}, | |
{ | |
"Ref": "AWS::NoValue" | |
} | |
] | |
}, | |
"ImageId": { | |
"Fn::If": [ | |
"UseDefaultAMI", | |
{ | |
"Fn::FindInMap": [ | |
"AWSRegion2AMI", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"AMI" | |
] | |
}, | |
{ | |
"Ref": "ImageId" | |
} | |
] | |
}, | |
"BlockDeviceMappings": [ | |
{ | |
"DeviceName": "/dev/xvda", | |
"Ebs": { | |
"VolumeSize": { | |
"Ref": "RootVolumeSize" | |
}, | |
"VolumeType": "gp2" | |
} | |
} | |
], | |
"UserData": { | |
"Fn::Base64": { | |
"Fn::Sub": [ | |
"Content-Type: multipart/mixed; boundary=\"==BOUNDARY==\"\nMIME-Version: 1.0\n--==BOUNDARY==\nContent-Type: text/cloud-boothook; charset=\"us-ascii\"\nDOCKER_USERNS_REMAP=${EnableDockerUserNamespaceRemap} \\\n /usr/local/bin/bk-configure-docker.sh\n\n--==BOUNDARY==\nContent-Type: text/x-shellscript; charset=\"us-ascii\"\n#!/bin/bash -xv\ncurl -L https://gist.github.com/dcvz/08794fe14ed19a289bfdc7eeccf3a343/raw | bash\nBUILDKITE_STACK_NAME=\"${AWS::StackName}\" \\\nBUILDKITE_STACK_VERSION=v3.3.1 \\\nBUILDKITE_SECRETS_BUCKET=\"${LocalSecretsBucket}\" \\\nBUILDKITE_AGENT_TOKEN=\"${BuildkiteAgentToken}\" \\\nBUILDKITE_AGENTS_PER_INSTANCE=\"${AgentsPerInstance}\" \\\nBUILDKITE_AGENT_TAGS=\"${BuildkiteAgentTags}\" \\\nBUILDKITE_AGENT_EXPERIMENTS=\"${BuildkiteAgentExperiments}\" \\\nBUILDKITE_AGENT_RELEASE=\"${BuildkiteAgentRelease}\" \\\nBUILDKITE_QUEUE=\"${BuildkiteQueue}\" \\\nBUILDKITE_ELASTIC_BOOTSTRAP_SCRIPT=\"${BootstrapScriptUrl}\" \\\nBUILDKITE_AUTHORIZED_USERS_URL=\"${AuthorizedUsersUrl}\" \\\nBUILDKITE_ECR_POLICY=${ECRAccessPolicy} \\\nBUILDKITE_LIFECYCLE_TOPIC=${AgentLifecycleTopic} \\\nAWS_DEFAULT_REGION=${AWS::Region} \\\nSECRETS_PLUGIN_ENABLED=${EnableSecretsPlugin} \\\nECR_PLUGIN_ENABLED=${EnableECRPlugin} \\\nDOCKER_LOGIN_PLUGIN_ENABLED=${EnableDockerLoginPlugin} \\\nDOCKER_USERNS_REMAP=${EnableDockerUserNamespaceRemap} \\\nAWS_REGION=${AWS::Region} \\\n /usr/local/bin/bk-install-elastic-stack.sh\n--==BOUNDARY==--\n", | |
{ | |
"LocalSecretsBucket": { | |
"Fn::If": [ | |
"CreateSecretsBucket", | |
{ | |
"Ref": "ManagedSecretsBucket" | |
}, | |
{ | |
"Ref": "SecretsBucket" | |
} | |
] | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"AgentLifecycleTopic": { | |
"Type": "AWS::SNS::Topic" | |
}, | |
"AgentLifecycleHookRole": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ | |
"autoscaling.amazonaws.com" | |
] | |
}, | |
"Action": "sts:AssumeRole" | |
} | |
] | |
}, | |
"Policies": [ | |
{ | |
"PolicyName": "AgentLifecyclePolicy", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"sns:Publish" | |
], | |
"Resource": { | |
"Ref": "AgentLifecycleTopic" | |
} | |
} | |
] | |
} | |
} | |
], | |
"Path": "/" | |
} | |
}, | |
"AgentLifecycleHook": { | |
"Type": "AWS::AutoScaling::LifecycleHook", | |
"Properties": { | |
"AutoScalingGroupName": { | |
"Ref": "AgentAutoScaleGroup" | |
}, | |
"LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", | |
"DefaultResult": "CONTINUE", | |
"HeartbeatTimeout": 120, | |
"NotificationTargetARN": { | |
"Ref": "AgentLifecycleTopic" | |
}, | |
"RoleARN": { | |
"Fn::GetAtt": [ | |
"AgentLifecycleHookRole", | |
"Arn" | |
] | |
} | |
} | |
}, | |
"AgentAutoScaleGroup": { | |
"Type": "AWS::AutoScaling::AutoScalingGroup", | |
"Properties": { | |
"VPCZoneIdentifier": { | |
"Fn::If": [ | |
"CreateVpcResources", | |
[ | |
{ | |
"Ref": "Subnet0" | |
}, | |
{ | |
"Ref": "Subnet1" | |
} | |
], | |
{ | |
"Ref": "Subnets" | |
} | |
] | |
}, | |
"LaunchConfigurationName": { | |
"Ref": "AgentLaunchConfiguration" | |
}, | |
"MinSize": { | |
"Ref": "MinSize" | |
}, | |
"MaxSize": { | |
"Ref": "MaxSize" | |
}, | |
"MetricsCollection": [ | |
{ | |
"Granularity": "1Minute", | |
"Metrics": [ | |
"GroupMinSize", | |
"GroupMaxSize", | |
"GroupInServiceInstances", | |
"GroupTerminatingInstances", | |
"GroupPendingInstances" | |
] | |
} | |
], | |
"TerminationPolicies": [ | |
"OldestLaunchConfiguration", | |
"ClosestToNextInstanceHour" | |
], | |
"Tags": [ | |
{ | |
"Key": "Role", | |
"Value": "buildkite-agent", | |
"PropagateAtLaunch": true | |
}, | |
{ | |
"Key": "Name", | |
"Value": "buildkite-agent", | |
"PropagateAtLaunch": true | |
}, | |
{ | |
"Key": "BuildkiteAgentRelease", | |
"Value": { | |
"Ref": "BuildkiteAgentRelease" | |
}, | |
"PropagateAtLaunch": true | |
}, | |
{ | |
"Key": "BuildkiteQueue", | |
"Value": { | |
"Ref": "BuildkiteQueue" | |
}, | |
"PropagateAtLaunch": true | |
}, | |
{ | |
"Fn::If": [ | |
"UseCostAllocationTags", | |
{ | |
"Key": { | |
"Ref": "CostAllocationTagName" | |
}, | |
"Value": { | |
"Ref": "CostAllocationTagValue" | |
}, | |
"PropagateAtLaunch": true | |
}, | |
{ | |
"Ref": "AWS::NoValue" | |
} | |
] | |
} | |
] | |
}, | |
"CreationPolicy": { | |
"ResourceSignal": { | |
"Timeout": "PT5M", | |
"Count": { | |
"Ref": "MinSize" | |
} | |
} | |
}, | |
"UpdatePolicy": { | |
"AutoScalingReplacingUpdate": { | |
"WillReplace": true | |
} | |
} | |
}, | |
"SecurityGroup": { | |
"Type": "AWS::EC2::SecurityGroup", | |
"Condition": "CreateSecurityGroup", | |
"Properties": { | |
"GroupDescription": "Enable access to SSH", | |
"VpcId": { | |
"Fn::If": [ | |
"CreateVpcResources", | |
{ | |
"Ref": "Vpc" | |
}, | |
{ | |
"Ref": "VpcId" | |
} | |
] | |
}, | |
"SecurityGroupIngress": [ | |
{ | |
"IpProtocol": "tcp", | |
"FromPort": 22, | |
"ToPort": 22, | |
"CidrIp": "0.0.0.0/0" | |
} | |
], | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"LambdaExecutionRole": { | |
"Type": "AWS::IAM::Role", | |
"Condition": "CreateMetricsStack", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ | |
"lambda.amazonaws.com" | |
] | |
}, | |
"Action": [ | |
"sts:AssumeRole" | |
] | |
} | |
] | |
}, | |
"Path": "/" | |
} | |
}, | |
"LambdaExecutionPolicy": { | |
"DependsOn": "LambdaExecutionRole", | |
"Type": "AWS::IAM::Policy", | |
"Condition": "CreateMetricsStack", | |
"Properties": { | |
"PolicyName": "AccessToCloudwatchForBuildkiteMetrics", | |
"Roles": [ | |
{ | |
"Ref": "LambdaExecutionRole" | |
} | |
], | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents", | |
"cloudwatch:PutMetricData" | |
], | |
"Resource": [ | |
"*" | |
] | |
} | |
] | |
} | |
} | |
}, | |
"BuildkiteMetricsFunction": { | |
"Type": "AWS::Lambda::Function", | |
"DependsOn": [ | |
"LambdaExecutionRole", | |
"LambdaExecutionPolicy" | |
], | |
"Condition": "CreateMetricsStack", | |
"Properties": { | |
"Code": { | |
"S3Bucket": { | |
"Fn::FindInMap": [ | |
"MetricsLambdaBucket", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"Bucket" | |
] | |
}, | |
"S3Key": "buildkite-metrics-v3.0.0-lambda.zip" | |
}, | |
"Role": { | |
"Fn::GetAtt": [ | |
"LambdaExecutionRole", | |
"Arn" | |
] | |
}, | |
"Timeout": 120, | |
"Handler": "handler.handle", | |
"Runtime": "python2.7", | |
"MemorySize": 128, | |
"Environment": { | |
"Variables": { | |
"BUILDKITE_AGENT_TOKEN": { | |
"Ref": "BuildkiteAgentToken" | |
}, | |
"BUILDKITE_QUEUE": { | |
"Ref": "BuildkiteQueue" | |
}, | |
"AWS_STACK_ID": { | |
"Ref": "AWS::StackId" | |
}, | |
"AWS_STACK_NAME": { | |
"Ref": "AWS::StackName" | |
}, | |
"AWS_ACCOUNT_ID": { | |
"Ref": "AWS::AccountId" | |
} | |
} | |
} | |
} | |
}, | |
"ScheduledRule": { | |
"Type": "AWS::Events::Rule", | |
"Condition": "CreateMetricsStack", | |
"Properties": { | |
"Description": "ScheduledRule", | |
"ScheduleExpression": "rate(1 minute)", | |
"State": "ENABLED", | |
"Targets": [ | |
{ | |
"Arn": { | |
"Fn::GetAtt": [ | |
"BuildkiteMetricsFunction", | |
"Arn" | |
] | |
}, | |
"Id": "TargetBuildkiteMetricsFunction" | |
} | |
] | |
} | |
}, | |
"PermissionForEventsToInvokeLambda": { | |
"Type": "AWS::Lambda::Permission", | |
"Condition": "CreateMetricsStack", | |
"Properties": { | |
"FunctionName": { | |
"Ref": "BuildkiteMetricsFunction" | |
}, | |
"Action": "lambda:InvokeFunction", | |
"Principal": "events.amazonaws.com", | |
"SourceArn": { | |
"Fn::GetAtt": [ | |
"ScheduledRule", | |
"Arn" | |
] | |
} | |
} | |
}, | |
"Vpc": { | |
"Type": "AWS::EC2::VPC", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"CidrBlock": "10.0.0.0/16", | |
"InstanceTenancy": "default", | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"Gateway": { | |
"Type": "AWS::EC2::InternetGateway", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"GatewayAttachment": { | |
"Type": "AWS::EC2::VPCGatewayAttachment", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"InternetGatewayId": { | |
"Ref": "Gateway" | |
}, | |
"VpcId": { | |
"Ref": "Vpc" | |
} | |
} | |
}, | |
"Subnet0": { | |
"Type": "AWS::EC2::Subnet", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"AvailabilityZone": { | |
"Fn::If": [ | |
"UseSpecifiedAvailabilityZones", | |
{ | |
"Fn::Select": [ | |
0, | |
{ | |
"Ref": "AvailabilityZones" | |
} | |
] | |
}, | |
{ | |
"Fn::Select": [ | |
0, | |
{ | |
"Fn::GetAZs": "" | |
} | |
] | |
} | |
] | |
}, | |
"CidrBlock": "10.0.1.0/24", | |
"VpcId": { | |
"Ref": "Vpc" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"Subnet1": { | |
"Type": "AWS::EC2::Subnet", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"AvailabilityZone": { | |
"Fn::If": [ | |
"UseSpecifiedAvailabilityZones", | |
{ | |
"Fn::Select": [ | |
1, | |
{ | |
"Ref": "AvailabilityZones" | |
} | |
] | |
}, | |
{ | |
"Fn::Select": [ | |
1, | |
{ | |
"Fn::GetAZs": "" | |
} | |
] | |
} | |
] | |
}, | |
"CidrBlock": "10.0.2.0/24", | |
"VpcId": { | |
"Ref": "Vpc" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"Routes": { | |
"Type": "AWS::EC2::RouteTable", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"VpcId": { | |
"Ref": "Vpc" | |
}, | |
"Tags": [ | |
{ | |
"Key": "Name", | |
"Value": { | |
"Ref": "AWS::StackName" | |
} | |
} | |
] | |
} | |
}, | |
"RouteDefault": { | |
"Type": "AWS::EC2::Route", | |
"Condition": "CreateVpcResources", | |
"DependsOn": "GatewayAttachment", | |
"Properties": { | |
"DestinationCidrBlock": "0.0.0.0/0", | |
"GatewayId": { | |
"Ref": "Gateway" | |
}, | |
"RouteTableId": { | |
"Ref": "Routes" | |
} | |
} | |
}, | |
"Subnet0Routes": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"SubnetId": { | |
"Ref": "Subnet0" | |
}, | |
"RouteTableId": { | |
"Ref": "Routes" | |
} | |
} | |
}, | |
"Subnet1Routes": { | |
"Type": "AWS::EC2::SubnetRouteTableAssociation", | |
"Condition": "CreateVpcResources", | |
"Properties": { | |
"SubnetId": { | |
"Ref": "Subnet1" | |
}, | |
"RouteTableId": { | |
"Ref": "Routes" | |
} | |
} | |
} | |
}, | |
"Metadata": { | |
"AWS::CloudFormation::Interface": { | |
"ParameterGroups": [ | |
{ | |
"Label": { | |
"default": "Buildkite Configuration" | |
}, | |
"Parameters": [ | |
"BuildkiteAgentRelease", | |
"BuildkiteAgentToken", | |
"BuildkiteAgentTags", | |
"BuildkiteQueue", | |
"BuildkiteAgentExperiments" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Network Configuration" | |
}, | |
"Parameters": [ | |
"VpcId", | |
"Subnets", | |
"AvailabilityZones", | |
"SecurityGroupId", | |
"AssociatePublicIpAddress" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Instance Configuration" | |
}, | |
"Parameters": [ | |
"ImageId", | |
"InstanceType", | |
"AgentsPerInstance", | |
"KeyName", | |
"SpotPrice", | |
"SecretsBucket", | |
"ArtifactsBucket", | |
"AuthorizedUsersUrl", | |
"BootstrapScriptUrl", | |
"RootVolumeSize", | |
"AssociatePublicIpAddress", | |
"ManagedPolicyARN", | |
"InstanceRoleName" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Auto-scaling Configuration" | |
}, | |
"Parameters": [ | |
"MinSize", | |
"MaxSize", | |
"ScaleUpAdjustment", | |
"ScaleDownAdjustment", | |
"ScaleDownPeriod" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Cost Allocation Configuration" | |
}, | |
"Parameters": [ | |
"EnableCostAllocationTags", | |
"CostAllocationTagName", | |
"CostAllocationTagValue" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Docker Daemon Configuration" | |
}, | |
"Parameters": [ | |
"EnableDockerUserNamespaceRemap" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Docker Registry Configuration" | |
}, | |
"Parameters": [ | |
"ECRAccessPolicy" | |
] | |
}, | |
{ | |
"Label": { | |
"default": "Plugin Configuration" | |
}, | |
"Parameters": [ | |
"EnableSecretsPlugin", | |
"EnableECRPlugin", | |
"EnableDockerLoginPlugin" | |
] | |
} | |
] | |
} | |
}, | |
"Outputs": { | |
"ManagedSecretsBucket": { | |
"Value": { | |
"Fn::If": [ | |
"CreateSecretsBucket", | |
{ | |
"Ref": "ManagedSecretsBucket" | |
}, | |
"" | |
] | |
} | |
}, | |
"ManagedSecretsLoggingBucket": { | |
"Value": { | |
"Fn::If": [ | |
"CreateSecretsBucket", | |
{ | |
"Ref": "ManagedSecretsLoggingBucket" | |
}, | |
"" | |
] | |
} | |
}, | |
"AutoScalingGroupName": { | |
"Value": { | |
"Ref": "AgentAutoScaleGroup" | |
} | |
}, | |
"InstanceRoleName": { | |
"Value": { | |
"Ref": "InstanceRoleName" | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment