Skip to content

Instantly share code, notes, and snippets.

@dcvz
Last active October 8, 2018 13:45
Show Gist options
  • Save dcvz/4770965e548407d64773cb4dc01bea0d to your computer and use it in GitHub Desktop.
Save dcvz/4770965e548407d64773cb4dc01bea0d to your computer and use it in GitHub Desktop.
Setup Buildkite Agent Amazon
{
"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