evergreen/distribution/flavors/aws-ec2-cloud/CloudFormation/cloudformation-template.json

322 lines
12 KiB
JSON

{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters" : {
"InstanceTypeParameter" : {
"Type" : "String",
"Default" : "t3.large",
"AllowedValues" : ["t2.micro", "t3.micro", "m1.small", "m5.small", "m1.large", "m5.large", "t2.large", "t3.large"],
"Description" : "Type of EC2 instance you want to run your master in."
},
"KeyNameParameter": {
"Type": "AWS::EC2::KeyPair::KeyName",
"Description": "The KeyName that will be used to access this EC2 instance."
},
"PrivateKey": {
"Type" : "String",
"Description" : "The private key for the keypair specified above (required to access agents from master)."
},
"SSHLocation" : {
"Description" : "The IP address range that can be used to SSH to the EC2 instance for your Jenkins Evergreen instance.",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x"
},
"VPCIPRange": {
"Description": "The private IP address range for allocating IPs within the VPC.",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "10.0.0.0/16",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form `x.x.x.x/x`."
},
"EvergreenImageId": {
"Description": "AMI to use for the EC2 Evergreen instance",
"Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
},
"AgentImageId": {
"Description": "AMI to use for the EC2 agent instances",
"Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
}
},
"Resources": {
"EvergreenVPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"EnableDnsSupport": true,
"EnableDnsHostnames": true,
"CidrBlock": {"Ref": "VPCIPRange"},
"InstanceTenancy": "default",
"Tags": [
{ "Key": "Application", "Value": {"Ref": "AWS::StackId"}},
{ "Key": "Name", "Value" : "VPC for Jenkins"}
]
}
},
"EvergreenInternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{ "Key": "Name", "Value" : {"Fn::Sub": "Jenkins ${AWS::StackName}"}}
]
}
},
"EvergreenGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "EvergreenVPC" },
"InternetGatewayId": { "Ref" : "EvergreenInternetGateway" }
}
},
"EvergreenSubnet": {
"Type" : "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"VpcId": { "Ref" : "EvergreenVPC" },
"CidrBlock" : {"Ref": "VPCIPRange"},
"MapPublicIpOnLaunch": true,
"Tags": [
{ "Key": "Name", "Value" : {"Fn::Sub": "Subnet for Jenkins ${AWS::StackName}"}}
]
}
},
"EvergreenRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId" : { "Ref" : "EvergreenVPC" },
"Tags": [
{ "Key": "Name", "Value" : {"Fn::Sub": "RouteTable for Jenkins ${AWS::StackName}"}}
]
}
},
"EvergreenInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": "EvergreenGatewayAttachment",
"Properties": {
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId": { "Ref" : "EvergreenInternetGateway" },
"RouteTableId": { "Ref" : "EvergreenRouteTable" }
}
},
"EvergreenSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": { "Ref" : "EvergreenRouteTable" },
"SubnetId": { "Ref" : "EvergreenSubnet" }
}
},
"EvergreenSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : {"Ref" : "EvergreenVPC"},
"GroupDescription" : "allow all traffic",
"SecurityGroupIngress" : [{
"IpProtocol": "-1",
"FromPort" : -1,
"ToPort" : -1,
"CidrIp" : "0.0.0.0/0"
}],
"SecurityGroupEgress" : [{
"IpProtocol" : "-1",
"CidrIp" : "0.0.0.0/0"
}],
"Tags": [
{ "Key": "Name", "Value" : {"Fn::Sub": "Global SecurityGroup for ${AWS::StackName}"}}
]
}
},
"EC2EvergreenInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": {"Ref": "EvergreenImageId"},
"InstanceType": {"Ref": "InstanceTypeParameter"},
"IamInstanceProfile": {"Ref": "MasterInstanceProfile"},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": "115"
}
}
],
"KeyName" : { "Ref" : "KeyNameParameter" },
"SecurityGroupIds": [
{ "Ref": "EvergreenMasterSecurityGroup"}
],
"SubnetId": { "Ref" : "EvergreenSubnet" },
"Tags" : [
{"Key" : "Name", "Value" : "Jenkins Evergreen Master"}
],
"UserData": {
"Fn::Base64" : {
"Fn::Join" : ["", [
"#!/bin/bash -v\n",
"# Install Docker to be able to start the Jenkins Evergreen container\n",
"sudo yum update -y\n",
"sudo yum install -y docker\n",
"sudo service docker start\n",
"sudo usermod -a -G docker ec2-user # not strictly necessary\n",
"# Now the Evergreen specific part\n",
"export DOCKER_IMAGE=jenkins/evergreen:aws-ec2-cloud\n",
"echo \"", { "Ref": "PrivateKey"}, "\" > ssh-agents-private-key\n",
"sudo docker volume create jenkins-evergreen-data\n",
"sudo docker pull $DOCKER_IMAGE\n",
"sudo docker run -d -p 8080:80 -p 50000:50000 ",
" --name evergreen",
" --restart=always",
" -v jenkins-evergreen-data:/evergreen/data",
" -v $PWD/ssh-agents-private-key:/run/secrets/PRIVATE_KEY:ro",
" -e REGION=", {"Ref":"AWS::Region"},
" -e AGENT_AMI=", {"Ref":"AgentImageId"},
" -e ARTIFACT_MANAGER_S3_BUCKET_NAME=", {"Ref":"S3BucketForArtifactManager"},
" -e AGENT_SECURITY_GROUP=", {"Ref":"EvergreenAgentSecurityGroup"},
" -e AGENT_SUBNET=", {"Ref":"EvergreenSubnet"},
" $DOCKER_IMAGE\n"
]
]
}
}
}
},
"EC2EvergreenInstanceEIP": {
"DependsOn": [
"EvergreenVPC"
],
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc",
"InstanceId" : {
"Ref" : "EC2EvergreenInstance"
}
}
},
"EvergreenMasterSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable HTTP access via port 8080 and JNLP port (TODO: restrict agent port)",
"VpcId" : { "Ref":"EvergreenVPC"},
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : { "Ref" : "SSHLocation"}},
{"IpProtocol" : "tcp", "FromPort" : 8080, "ToPort" : 8080, "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : 50000, "ToPort" : 50000, "CidrIp" : "0.0.0.0/0"}
]
}
},
"EvergreenAgentSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable HTTP access via port 8080 and JNLP port (TODO: restrict agent port)",
"VpcId" : { "Ref":"EvergreenVPC"},
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : "0.0.0.0/0"}
]
}
},
"MasterInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Roles": [ { "Ref": "EvergreenMasterRole" } ]
}
},
"EvergreenMasterRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Principal": {
"Service": [ "ec2.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
} ]
},
"Policies": [{
"PolicyName": "EC2CloudPluginPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Sid": "ControlEC2JenkinsAgents",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:TerminateInstances",
"ec2:RequestSpotInstances",
"ec2:DeleteTags",
"ec2:CreateTags",
"ec2:DescribeRegions",
"ec2:RunInstances",
"ec2:DescribeSpotInstanceRequests",
"ec2:StopInstances",
"ec2:DescribeSecurityGroups",
"ec2:GetConsoleOutput",
"ec2:DescribeImages",
"ec2:CancelSpotInstanceRequests",
"ec2:StartInstances",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeSubnets",
"ec2:DescribeKeyPairs"
],
"Resource": "*"
}]
}
}, {
"PolicyName": "S3ArtifactManagerPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TodoRefineSecurityALot",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": "*"
}
]
}
}
]
}
},
"S3BucketForArtifactManager": {
"Type": "AWS::S3::Bucket"
},
"EC2EvergreenInstanceAlarm": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Trigger a recovery when instance status check fails for 5 consecutive minutes.",
"Namespace": "AWS/EC2",
"MetricName": "StatusCheckFailed_System",
"Statistic": "Minimum",
"Period": 60,
"EvaluationPeriods": 5,
"ComparisonOperator": "GreaterThanThreshold",
"Threshold": 0,
"AlarmActions": [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
"Dimensions": [{"Name": "InstanceId","Value": {"Ref": "EC2EvergreenInstance"}}]
}
}
},
"Outputs": {
"EC2EvergreenInstanceIP": {
"Description": "Public IP address of the Evergreen EC2 instance",
"Value": {
"Fn::GetAtt": [
"EC2EvergreenInstance",
"PublicIp"
]
}
}
}
}