├── diagram.png ├── .circleci └── config.yml ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── Dockerfile ├── LICENSE ├── entrypoint.sh ├── readme.md └── gitlab-runner-template.yml /diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woodjme/autoscaling-ec2-gitlab-runners-fargate/HEAD/diagram.png -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | aws-s3: circleci/aws-s3@1.0.15 4 | jobs: 5 | build: 6 | docker: 7 | - image: 'python:3-slim' 8 | steps: 9 | - checkout 10 | - run: pip install cfn-lint awscli 11 | - run: cfn-lint -t gitlab-runner-template.yml 12 | - aws-s3/copy: 13 | arguments: '--acl public-read' 14 | from: ./gitlab-runner-template.yml 15 | to: 's3://autoscaling-ec2-gitlab-runners-fargate/${CIRCLE_BRANCH}/gitlab-runner-template.yml' 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | LABEL maintainer="me@jamiewood.io" 3 | 4 | ARG GITLAB_RUNNER_VERSION="13.8.0" 5 | ARG DOCKER_MACHINE_VERSION="0.16.2-gitlab.4" 6 | 7 | # Install deps 8 | RUN apt-get update && \ 9 | apt-get install -y --no-install-recommends \ 10 | ca-certificates \ 11 | curl \ 12 | git \ 13 | dumb-init && \ 14 | # Decrease docker image size 15 | rm -rf /var/lib/apt/lists/* && \ 16 | # Install Gitlab Runner 17 | curl -LJO https://gitlab-runner-downloads.s3.amazonaws.com/v${GITLAB_RUNNER_VERSION}/deb/gitlab-runner_amd64.deb && \ 18 | dpkg -i gitlab-runner_amd64.deb && \ 19 | # Install Docker Machine 20 | curl -L https://gitlab-docker-machine-downloads.s3.amazonaws.com/v${DOCKER_MACHINE_VERSION}/docker-machine > /usr/local/bin/docker-machine && \ 21 | chmod +x /usr/local/bin/docker-machine 22 | 23 | COPY ./entrypoint.sh ./entrypoint.sh 24 | 25 | ENV REGISTER_NON_INTERACTIVE=true 26 | 27 | ENTRYPOINT ["/usr/bin/dumb-init", "--", "./entrypoint.sh" ] 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jamie Wood 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set error handling 4 | set -euo pipefail 5 | 6 | # Always unregister runner on exit 7 | function gitlab-unregister { 8 | gitlab-runner unregister --all-runners 9 | } 10 | 11 | trap 'gitlab-unregister' EXIT SIGHUP SIGINT SIGTERM 12 | 13 | # Define runner tags 14 | if [ -n "${RUNNER_TAG_LIST:-}" ] 15 | then 16 | RUNNER_TAG_LIST_OPT=("--tag-list" "$RUNNER_TAG_LIST") 17 | else 18 | RUNNER_TAG_LIST_OPT=("--run-untagged=true") 19 | fi 20 | 21 | # Define adicional parameters 22 | if [ -n "${ADDITIONAL_REGISTER_PARAMS:-}" ] 23 | then 24 | IFS=' ' read -r -a ADDITIONAL_REGISTER_PARAMS_OPT <<< "$ADDITIONAL_REGISTER_PARAMS" 25 | else 26 | IFS=' ' read -r -a ADDITIONAL_REGISTER_PARAMS_OPT <<< "" 27 | fi 28 | 29 | # Register 30 | gitlab-runner register --executor docker+machine \ 31 | --docker-privileged \ 32 | --docker-tlsverify \ 33 | --docker-disable-cache \ 34 | --machine-machine-driver "amazonec2" \ 35 | --machine-machine-name "gitlab-%s" \ 36 | --request-concurrency "$RUNNER_REQUEST_CONCURRENCY" \ 37 | --machine-machine-options amazonec2-use-private-address \ 38 | --machine-machine-options amazonec2-security-group="$AWS_SECURITY_GROUP" \ 39 | "${RUNNER_TAG_LIST_OPT[@]}" \ 40 | "${ADDITIONAL_REGISTER_PARAMS_OPT[@]}" 41 | 42 | # Native env var seems to be broken for security group 43 | 44 | # Start Runner 45 | gitlab-runner run 46 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Autoscaling EC2 GitLab Runners Spawned by Fargate 2 | 3 | The purpose of the CloudFormation template is to create a Fargate Service that manages and autoscales EC2 instances to serve as a Gitlab CI executors. This allows for private GitLab Runners without managing, patching or maintaining servers. 4 | 5 | ## Why Use EC2 executors? 6 | 7 | At the time of writing, Fargate doesn't support the privileged task definition parameter for executors which ultimately means you can't use Docker-in-Docker to build/pull/push docker images in a Fargate executor. Anyone who is looking for a pure Fargate implementation should read [this](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/index.html). 8 | 9 | [![Launch CloudFormation](https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?stackName=stack_name&templateURL=template_locationhttps://console.aws.amazon.com/cloudformation/home?region=region#/stacks/new?stackName=stack_name&templateURL=https://autoscaling-ec2-gitlab-runners-fargate.s3-eu-west-1.amazonaws.com/master/gitlab-runner-template.yml) 10 | 11 | ![Diagram](https://github.com/woodjme/autoscaling-ec2-gitlab-runners-fargate/blob/master/diagram.png?raw=true) 12 | 13 | ## Parameters 14 | 15 | * `VpcId` - Select a VPC that allows instances access to the Internet 16 | * `SubnetID` - Select subnets - Must be in the selected VPC! 17 | * `GitLabURL` - The Gitlab URL, change if self-hosted 18 | * `GitLabRegistrationToken` - The Gitlab runer registration token 19 | * `RunnerRequestConcurrency` - Specify the number of concurrent EC2 virtual machines to spawn (defaults to 12) 20 | * `RunnerTagList` - Optional parameter to specify the gitlab-runner tags (Example "docker,aws") 21 | * `AdditionalRegisterParams` - Any additional parameters you want to pass to `gitlab-runner register` 22 | * `RunnerVersion` The GitLab runner version 23 | * `InstanceType` - The instance type of the runners 24 | * `RootVolumeSize` -The size of the root volume on the runners 25 | * `CacheExpirationInDays` - Select how long to store a jobs cache output in S3 26 | * `CPU` - Set the number of CPUs for the spawner (1 CPU = 1024) 27 | * `Memory` - Set the amount of RAM in KB for the spawner 28 | * `DockerImage` - The default docker image if not provided in a gitlab-ci.yml file 29 | 30 | ## Resource Created 31 | 32 | * IAM User - Used to connect to S3 33 | * IAM Roles for ECS 34 | * S3 Bucket for runner cache 35 | * ECS Cluster, Service & Task Definition 36 | * CloudWatch Logs Groups that streams to logs for the spawner 37 | -------------------------------------------------------------------------------- /gitlab-runner-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: Autoscaling Gitlab Runners Spawned by Fargate 3 | Metadata: 4 | AWS::CloudFormation::Interface: 5 | ParameterGroups: 6 | - 7 | Label: 8 | default: "Network Configuration" 9 | Parameters: 10 | - VpcId 11 | - SubnetId 12 | - 13 | Label: 14 | default: "GitLab Configuration" 15 | Parameters: 16 | - GitLabURL 17 | - GitLabRegistrationToken 18 | - RunnerTagList 19 | - RunnerRequestConcurrency 20 | - AdditionalRegisterParams 21 | - 22 | Label: 23 | default: "GitLab Runner Configuration" 24 | Parameters: 25 | - RunnerVersion 26 | - InstanceType 27 | - RootVolumeSize 28 | - CacheExpirationInDays 29 | - 30 | Label: 31 | default: "Fargate Spawner Configuration" 32 | Parameters: 33 | - CPU 34 | - Memory 35 | - DockerImage 36 | 37 | 38 | 39 | Parameters: 40 | VpcId: 41 | Type: AWS::EC2::VPC::Id 42 | Description: Select a VPC that allows instances access to the Internet 43 | SubnetId: 44 | Type: List 45 | Description: Select subnets - Must be in the selected VPC! 46 | CacheExpirationInDays: 47 | Type: Number 48 | Default: 1 49 | Description: Select how long to store a jobs cache output in S3 50 | RootVolumeSize: 51 | Type: Number 52 | Description: The size of the root volume on the runners 53 | Default: 40 54 | GitLabURL: 55 | Type: String 56 | Description: The Gitlab URL, change if self-hosted 57 | Default: https://gitlab.com 58 | GitLabRegistrationToken: 59 | Type: String 60 | Description: The Gitlab runer registration token 61 | NoEcho: true 62 | RunnerRequestConcurrency: 63 | Type: Number 64 | Description: Specify the number of concurrent EC2 virtual machines to spawn 65 | Default: 12 66 | RunnerTagList: 67 | Type: String 68 | Description: Optional parameter to specify the gitlab-runner tags (Example "docker,aws") 69 | Default: "" 70 | AdditionalRegisterParams: 71 | Type: String 72 | Description: Optional parameters to be passed to gitlab-runner register 73 | Default: "" 74 | DockerImage: 75 | Type: String 76 | Default: "docker:latest" 77 | Description: The default docker image if not provided in a gitlab-ci.yml file 78 | CPU: 79 | Type: Number 80 | Description: Set the number of CPUs for the spawner (1 CPU = 1024) 81 | Default: '512' 82 | Memory: 83 | Type: Number 84 | Description: Set the amount of RAM in KB for the spawner 85 | Default: '1024' 86 | InstanceType: 87 | Type: String 88 | Description: The instance type of the runners 89 | Default: t3.micro 90 | AllowedValues: [ 91 | 'c1.medium', 'c1.xlarge', 92 | 'c3.large', 'c3.xlarge', 'c3.2xlarge', 'c3.4xlarge', 'c3.8xlarge', 93 | 'c4.large', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', 94 | 'c5.large', 'c5.xlarge', 'c5.2xlarge', 'c5.4xlarge', 'c5.9xlarge', 'c5.18xlarge', 95 | 'c5d.large', 'c5d.xlarge', 'c5d.2xlarge', 'c5d.4xlarge', 'c5d.9xlarge', 'c5d.18xlarge', 96 | 'cc2.8xlarge', 97 | 'cr1.8xlarge', 98 | 'd2.xlarge', 'd2.2xlarge', 'd2.4xlarge', 'd2.8xlarge', 99 | 'f1.2xlarge', 'f1.4xlarge', 'f1.16xlarge', 100 | 'g2.2xlarge', 'g2.8xlarge', 101 | 'g3.4xlarge', 'g3.8xlarge', 'g3.16xlarge', 102 | 'g3s.xlarge', 103 | 'h1.2xlarge', 'h1.4xlarge', 'h1.8xlarge', 'h1.16xlarge', 104 | 'hs1.8xlarge', 105 | 'i2.xlarge', 'i2.2xlarge', 'i2.4xlarge', 'i2.8xlarge', 106 | 'i3.large', 'i3.xlarge', 'i3.2xlarge', 'i3.4xlarge', 'i3.8xlarge', 'i3.16xlarge', 'i3.metal', 107 | 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 108 | 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 109 | 'm3.medium', 'm3.large', 'm3.xlarge', 'm3.2xlarge', 110 | 'm4.large', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'm4.16xlarge', 111 | 'm5.large', 'm5.xlarge', 'm5.2xlarge', 'm5.4xlarge', 'm5.12xlarge', 'm5.24xlarge', 112 | 'm5d.large', 'm5d.xlarge', 'm5d.2xlarge', 'm5d.4xlarge', 'm5d.12xlarge', 'm5d.24xlarge', 113 | 'p2.xlarge', 'p2.8xlarge', 'p2.16xlarge', 114 | 'p3.2xlarge', 'p3.8xlarge', 'p3.16xlarge', 115 | 'r3.large', 'r3.xlarge', 'r3.2xlarge', 'r3.4xlarge', 'r3.8xlarge', 116 | 'r4.large', 'r4.xlarge', 'r4.2xlarge', 'r4.4xlarge', 'r4.8xlarge', 'r4.16xlarge', 117 | 'r5.large', 'r5.xlarge', 'r5.2xlarge', 'r5.4xlarge', 'r5.12xlarge', 'r5.24xlarge', 118 | 'r5d.large', 'r5d.xlarge', 'r5d.2xlarge', 'r5d.4xlarge', 'r5d.12xlarge', 'r5d.24xlarge', 119 | 't1.micro', 120 | 't2.nano', 't2.micro', 't2.small', 't2.medium', 't2.large', 't2.xlarge', 't2.2xlarge', 121 | 't3.nano', 't3.micro', 't3.small', 't3.medium', 't3.large', 't3.xlarge', 't3.2xlarge', 122 | 'x1.16xlarge', 'x1.32xlarge', 123 | 'x1e.xlarge', 'x1e.2xlarge', 'x1e.4xlarge', 'x1e.8xlarge', 'x1e.16xlarge', 'x1e.32xlarge', 124 | 'z1d.large', 'z1d.xlarge', 'z1d.2xlarge', 'z1d.3xlarge', 'z1d.6xlarge', 'z1d.12xlarge', 125 | ] 126 | RunnerVersion: 127 | Type: String 128 | Description: The GitLab Runner Version 129 | Default: latest 130 | AllowedValues: [ 131 | 'latest', 132 | '13.2.1', 133 | '13.2.0', 134 | '13.1.1', 135 | '13.1.0', 136 | '13.0.0', 137 | '12.10.2', 138 | '12.10.1', 139 | '12.10.0', 140 | '12.8.0', 141 | '12.7.1', 142 | 'dev', 143 | ] 144 | 145 | Mappings: 146 | AWSAMIRegionMap: 147 | af-south-1: 148 | UBUNTU1804: ami-04ef2733e8b8097f4 149 | ap-east-1: 150 | UBUNTU1804: ami-107d3e61 151 | ap-northeast-1: 152 | UBUNTU1804: ami-01c36f3329957b16a 153 | ap-northeast-2: 154 | UBUNTU1804: ami-05438a9ce08100b25 155 | ap-northeast-3: 156 | UBUNTU1804: ami-05a1fb6629fedc070 157 | ap-south-1: 158 | UBUNTU1804: ami-02b5fbc2cb28b77b8 159 | ap-southeast-1: 160 | UBUNTU1804: ami-0007cf37783ff7e10 161 | ap-southeast-2: 162 | UBUNTU1804: ami-0f87b0a4eff45d9ce 163 | ca-central-1: 164 | UBUNTU1804: ami-054798b3f62ca2a31 165 | eu-central-1: 166 | UBUNTU1804: ami-04932daa2567651e7 167 | eu-north-1: 168 | UBUNTU1804: ami-0363142d8c97b94c8 169 | eu-south-1: 170 | UBUNTU1804: ami-072ba62ae4c03effc 171 | eu-west-1: 172 | UBUNTU1804: ami-07ee42ba0209b6d77 173 | eu-west-2: 174 | UBUNTU1804: ami-04edc9c2bfcf9a772 175 | eu-west-3: 176 | UBUNTU1804: ami-03d4fca0a9ced3d1f 177 | me-south-1: 178 | UBUNTU1804: ami-06fdc76efb53b5d44 179 | sa-east-1: 180 | UBUNTU1804: ami-08caf314e5abfbef4 181 | us-east-1: 182 | UBUNTU1804: ami-0bcc094591f354be2 183 | us-east-2: 184 | UBUNTU1804: ami-0bbe28eb2173f6167 185 | us-west-1: 186 | UBUNTU1804: ami-0dd005d3eb03f66e8 187 | us-west-2: 188 | UBUNTU1804: ami-0a634ae95e11c6f91 189 | 190 | # Conditions: 191 | 192 | Resources: 193 | gitLabRegistrationToken: 194 | Type: AWS::SecretsManager::Secret 195 | Properties: 196 | Name: !Join ['-', [ !Ref 'AWS::StackName', gitLabRegistrationToken]] 197 | Description: The Gitlab runer registration token 198 | SecretString: !Ref GitLabRegistrationToken 199 | iamUser: 200 | Type: AWS::IAM::User 201 | Properties: 202 | UserName: !Join ['-', [ !Ref 'AWS::StackName', s3user]] 203 | Policies: 204 | - PolicyName: !Join ['-', [ !Ref 'AWS::StackName', GitLabCacheBucket]] 205 | PolicyDocument: 206 | Version: '2012-10-17' 207 | Statement: 208 | - Effect: 'Allow' 209 | Action: 210 | - 's3:ListObjects*' 211 | - 's3:GetObject*' 212 | - 's3:DeleteObject*' 213 | - 's3:PutObject*' 214 | Resource: 215 | - !Sub '${GitLabRunnerCacheBucket.Arn}/*' 216 | - Effect: 'Allow' 217 | Action: 218 | - 's3:ListBucket' 219 | Resource: 220 | - !GetAtt GitLabRunnerCacheBucket.Arn 221 | iamAccessKey: 222 | Type: AWS::IAM::AccessKey 223 | Properties: 224 | Status: Active 225 | UserName: !Ref iamUser 226 | iamRoleForEcsExecution: 227 | Type: AWS::IAM::Role 228 | Properties: 229 | RoleName: !Join ['-', [ !Ref 'AWS::StackName', GitlabECSExecutionRole]] 230 | ManagedPolicyArns: 231 | - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy 232 | AssumeRolePolicyDocument: 233 | Version: 2012-10-17 234 | Statement: 235 | - Effect: Allow 236 | Principal: 237 | Service: 238 | - ecs-tasks.amazonaws.com 239 | Action: 240 | - 'sts:AssumeRole' 241 | Policies: 242 | - PolicyName: !Join ['-', [ !Ref 'AWS::StackName', GitLabRegistrationToken]] 243 | PolicyDocument: 244 | Statement: 245 | - Effect: Allow 246 | Action: 247 | - 'secretsmanager:DescribeSecret' 248 | - 'secretsmanager:GetSecretValue' 249 | Resource: !Ref gitLabRegistrationToken 250 | iamRoleForEcsTask: 251 | Type: AWS::IAM::Role 252 | Properties: 253 | RoleName: !Join ['-', [ !Ref 'AWS::StackName', GitlabECSTaskRole]] 254 | ManagedPolicyArns: 255 | - arn:aws:iam::aws:policy/AmazonEC2FullAccess 256 | AssumeRolePolicyDocument: 257 | Version: 2012-10-17 258 | Statement: 259 | - Effect: Allow 260 | Principal: 261 | Service: 262 | - ecs-tasks.amazonaws.com 263 | Action: 264 | - 'sts:AssumeRole' 265 | SpawnerSecurityGroup: 266 | Type: AWS::EC2::SecurityGroup 267 | Properties: 268 | GroupDescription: GitlabSpawnerSecurityRules 269 | GroupName: !Join ['-', [ !Ref 'AWS::StackName', GitlabSpawnerSecurityRules]] 270 | SecurityGroupEgress: 271 | - IpProtocol: "-1" 272 | CidrIp: 0.0.0.0/0 273 | VpcId: !Ref VpcId 274 | RunnerSecurityGroup: 275 | Type: AWS::EC2::SecurityGroup 276 | Properties: 277 | GroupDescription: GitlabRunnerSecurityRules 278 | GroupName: !Join ['-', [ !Ref 'AWS::StackName', GitlabRunnerSecurityRules]] 279 | SecurityGroupIngress: 280 | - IpProtocol: tcp 281 | FromPort: 22 282 | ToPort: 22 283 | SourceSecurityGroupId: !GetAtt SpawnerSecurityGroup.GroupId 284 | - IpProtocol: tcp 285 | FromPort: 2376 286 | ToPort: 2376 287 | SourceSecurityGroupId: !GetAtt SpawnerSecurityGroup.GroupId 288 | SecurityGroupEgress: 289 | - IpProtocol: "-1" 290 | CidrIp: 0.0.0.0/0 291 | VpcId: !Ref VpcId 292 | GitLabRunnerCacheBucket: 293 | Type: 'AWS::S3::Bucket' 294 | Properties: 295 | AccessControl: Private 296 | PublicAccessBlockConfiguration: 297 | BlockPublicAcls: true 298 | BlockPublicPolicy: true 299 | IgnorePublicAcls: true 300 | RestrictPublicBuckets: true 301 | LifecycleConfiguration: 302 | Rules: 303 | - Status: 'Enabled' 304 | ExpirationInDays: !Ref 'CacheExpirationInDays' 305 | ECSCluster: 306 | Type: AWS::ECS::Cluster 307 | ECSService: 308 | Type: AWS::ECS::Service 309 | Properties: 310 | Cluster: !Ref ECSCluster 311 | DesiredCount: 1 312 | LaunchType: FARGATE 313 | ServiceName: !Join ['-', [ !Ref 'AWS::StackName', service]] 314 | TaskDefinition: !Ref TaskDefinition 315 | NetworkConfiguration: 316 | AwsvpcConfiguration: 317 | AssignPublicIp: ENABLED 318 | Subnets: !Ref SubnetId 319 | SecurityGroups: 320 | - !GetAtt SpawnerSecurityGroup.GroupId 321 | CloudwatchLogsGroup: 322 | Type: AWS::Logs::LogGroup 323 | Properties: 324 | LogGroupName: !Join ['-', [!Ref 'AWS::StackName', ECSLogGroup]] 325 | RetentionInDays: 14 326 | TaskDefinition: 327 | Type: AWS::ECS::TaskDefinition 328 | Properties: 329 | Family: !Join ['', [!Ref 'AWS::StackName', -gitlab-runner-spawner]] 330 | Cpu: !Ref CPU 331 | Memory: !Ref Memory 332 | NetworkMode: awsvpc 333 | ExecutionRoleArn: !GetAtt iamRoleForEcsExecution.Arn 334 | TaskRoleArn: !GetAtt iamRoleForEcsTask.Arn 335 | RequiresCompatibilities: [ FARGATE ] 336 | ContainerDefinitions: 337 | - Name: !Join ['', [!Ref 'AWS::StackName', -gitlab-runner-spawner]] 338 | Image: !Join [':', [woodjme/autoscaling-ec2-gitlab-runners-fargate, !Ref RunnerVersion]] 339 | Environment: [ 340 | {"Name":"CI_SERVER_URL", "Value": !Ref GitLabURL}, 341 | {"Name":"AWS_ROOT_SIZE", "Value": !Ref RootVolumeSize}, 342 | {"Name":"AWS_DEFAULT_REGION", "Value": !Ref "AWS::Region"}, 343 | {"Name":"AWS_VPC_ID", "Value": !Ref VpcId}, 344 | {"Name":"AWS_SSH_USER", "Value": 'ubuntu'}, 345 | {"Name":"AWS_SECURITY_GROUP", "Value": !Join ['-', [ !Ref 'AWS::StackName', GitlabRunnerSecurityRules]]}, 346 | {"Name":"AWS_AMI", "Value": { "Fn::FindInMap": [ "AWSAMIRegionMap", { "Ref": "AWS::Region" }, "UBUNTU1804"]}}, 347 | {"Name":"DOCKER_IMAGE", "Value": !Ref DockerImage}, 348 | {"Name":"ADDITIONAL_REGISTER_PARAMS", "Value": !Ref AdditionalRegisterParams}, 349 | {"Name":"AWS_INSTANCE_TYPE", "Value": !Ref InstanceType}, 350 | {"Name":"CACHE_TYPE", "Value": 's3'}, 351 | {"Name":"CACHE_S3_ACCESS_KEY", "Value": !Ref iamAccessKey}, 352 | {"Name":"CACHE_S3_SECRET_KEY", "Value": !GetAtt iamAccessKey.SecretAccessKey}, 353 | {"Name":"CACHE_SHARED", "Value": "true"}, 354 | {"Name":"CACHE_S3_BUCKET_NAME", "Value": !Ref GitLabRunnerCacheBucket}, 355 | {"Name":"CACHE_S3_BUCKET_LOCATION", "Value": !Ref "AWS::Region"}, 356 | {"Name":"CACHE_S3_SERVER_ADDRESS", "Value": !Join ['', [s3., !Ref 'AWS::URLSuffix']]}, 357 | {"Name":"RUNNER_REQUEST_CONCURRENCY", "Value": !Ref RunnerRequestConcurrency}, 358 | {"Name":"RUNNER_TAG_LIST", "Value": !Ref RunnerTagList} 359 | ] 360 | Secrets: [ 361 | {"Name":"REGISTRATION_TOKEN", "ValueFrom": !Ref gitLabRegistrationToken} 362 | ] 363 | LogConfiguration: 364 | LogDriver: awslogs 365 | Options: 366 | awslogs-group: !Ref 'CloudwatchLogsGroup' 367 | awslogs-region: !Ref 'AWS::Region' 368 | awslogs-stream-prefix: gitlab-runner-spawner 369 | 370 | Outputs: 371 | GitLabRunnerCacheBucketName: 372 | Description: Name of the cache bucket 373 | Value: !Ref GitLabRunnerCacheBucket 374 | --------------------------------------------------------------------------------