Skip to main content

AWS CDK GitLab Runner 使用 docker+machine 执行器在 EC2 实例上自动扩展。

项目描述

GitHub npm(范围) 派皮 努吉特 Sonatype Nexus(发布) GitHub 工作流状态(分支) GitHub 发布(最新 SemVer)

EC2 上的 AWS CDK GitLab Runner 自动缩放

该项目提供了一个 CDK 构造,用于使用Docker Machine执行器在自动扩展的 EC2 实例上执行作业

用完Runner 分钟,使用Docker-in-Docker (dind) ,使用共享 S3 缓存加速作业,交叉编译/构建环境多架构,在 EC2 上进行经济高效的自动扩展,直接从 AWS 账户部署(无需AWS 访问密钥),运行在Spot 实例上,具有更大的构建日志大小

安装

打字稿

npm install @pepperize/cdk-autoscaling-gitlab-runner

或者

yarn add @pepperize/cdk-autoscaling-gitlab-runner

Python

pip install pepperize.cdk-autoscaling-gitlab-runner

C#/.Net

dotnet add package Pepperize.CDK.AutoscalingGitlabRunner

爪哇

<dependency>
  <groupId>com.pepperize</groupId>
  <artifactId>cdk-autoscaling-gitlab-runner</artifactId>
  <version>${cdkAutoscalingGitlabRunner.version}</version>
</dependency>

快速开始

  1. 使用projen在 TypeScript 中创建新的 AWS CDK 应用程序

    mkdir gitlab-runner
    cd gitlab-runner
    git init
    npx projen new awscdk-app-ts
    
  2. 配置你的项目.projenrc.js

    • 添加deps: ["@pepperize/cdk-autoscaling-gitlab-runner"],
  3. 更新项目文件并安装依赖项

    npx projen
    
  4. 注册一个新的跑步者

    注册跑步者

    • 对于共享跑步者,请转到 GitLab 管理区域并单击概览 > 跑步者
    • 对于组跑步者,请转到Settings > CI/CD并展开Runners部分
    • 对于项目运行器,请转到Settings > CI/CD并展开Runners部分

    可选启用:运行未标记的作业[x] 指示此运行器是否可以选择没有标记的作业

    另请参阅注册令牌与身份验证令牌

  5. 检索新的运行器身份验证令牌

    注册一个新的跑步者

    curl --request POST "https://gitlab.com/api/v4/runners" --form "token=<your register token>" --form "description=gitlab-runner" --form "tag_list=pepperize,docker,production"
    
  6. 将运行器身份验证令牌存储在 SSM ParameterStore 中

    创建字符串参数

    aws ssm put-parameter --name "/gitlab-runner/token" --value "<your runner authentication token>" --type "String"
    
  7. 添加到您的main.ts

    import { Vpc } from "@aws-cdk/aws-ec2";
    import { App, Stack } from "@aws-cdk/core";
    import { GitlabRunnerAutoscaling } from "@pepperize/cdk-autoscaling-gitlab-runner";
    
    const app = new App();
    const stack = new Stack(app, "GitLabRunnerStack");
    const vpc = Vpc.fromLookup(app, "ExistingVpc", {
      vpcId: "<your vpc id>",
    });
    const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
      parameterName: "/gitlab-runner/token",
    });
    new GitlabRunnerAutoscaling(stack, "GitlabRunner", {
      network: {
        vpc: vpc,
      },
      runners: [
        {
          token: token,
          configuration: {
            // optionally configure your runner
          },
        },
      ],
    });
    
  8. 创建服务链接角色

    (如果请求 Spot 实例,默认:true)

    aws iam create-service-linked-role --aws-service-name spot.amazonaws.com
    
  9. 配置 AWS CLI

  10. 部署 GitLab Runner

    npm run deploy
    

例子

自定义缓存桶

默认情况下,创建一个 AWS S3 存储桶作为 GitLab Runner 的分布式缓存。它是加密的,公共访问被阻止。可以配置自定义 S3 存储桶:

const cache = new Bucket(this, "Cache", {
  // Your custom bucket
});
const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
    },
  ],
  cache: { bucket: cache },
});

请参阅示例GitlabRunnerAutoscalingCacheProps

自定义 EC2 密钥对

默认情况下,amazonec2驱动程序将为每个运行器创建一个 EC2 密钥对。要使用自定义 ssh 凭证,请提供带有私钥和公钥文件的 SecretsManager Secret:

  1. 创建密钥对,下载私钥文件并记住创建的密钥对名称

  2. 生成公钥文件

    ssh-keygen -f <the downloaded private key file> -y
    
  3. 从密钥对创建 AWS SecretsManager 密钥

    aws secretsmanager create-secret --name <the secret name> --secret-string "{\"<the key pair name>\":\"<the private key>\",\"<the key pair name>.pub\":\"<the public key>\"}"
    
  4. 配置作业运行器

    const keyPair = Secret.fromSecretNameV2(stack, "Secret", "CustomEC2KeyPair");
    
    new GitlabRunnerAutoscaling(this, "Runner", {
      runners: [
        {
          keyPair: keyPair,
          configuration: {
            machine: {
              machineOptions: {
                keypairName: "<the key pair name>",
              },
            },
          },
        },
      ],
      cache: { bucket: cache },
    });
    

配置 Docker 机器

默认情况下,docker 机器配置为使用 OverlayFS 驱动程序CAP_SYS_ADMIN以支持Docker-in-Docker 的特权运行并使用multiarch 进行交叉编译/构建。

请参阅高级配置 中的runners.docker 部分

import { GitlabRunnerAutoscaling } from "@pepperize/cdk-autoscaling-gitlab-runner";
import { StringParameter } from "aws-cdk-lib/aws-ssm";

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        environment: [], // Reset the OverlayFS driver for every project
        docker: {
          capAdd: [], // Remove the CAP_SYS_ADMIN
          privileged: false, // Run unprivileged
        },
        machine: {
          idleCount: 2, // Number of idle machine
          idleTime: 3000, // Waiting time in idle state
          maxBuilds: 1, // Max builds before instance is removed
        },
      },
    },
  ],
});

请参阅示例DockerConfiguration

更大的实例类型

默认情况下,t3.nano 用于管理器/协调器,并且将生成 t3.micro 实例。对于更大的项目,例如使用webpack,这将是不够的内存。

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  manager: {
    instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.SMALL),
  },
  runners: [
    {
      instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE),
      token: token,
      configuration: {
        // optionally configure your runner
      },
    },
  ],
});

您可能必须禁用或配置Spot 实例

参见示例GitlabRunnerAutoscalingManagerPropsGitlabRunnerAutoscalingJobRunnerProps

不同的机器图像

默认情况下,最新的Amazon 2 Linux将用于管理器/协调器。管理器/协调器实例的云初始化脚本需要安装yum,任何 RHEL 风格都可以工作。默认情况下,请求的运行程序实例使用 Ubuntu 20.04,任何由Docker Machine 配置程序实现的操作系统都应该可以工作。

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  manager: {
    machineImage: MachineImage.genericLinux(managerAmiMap),
  },
  runners: [
    {
      machineImage: MachineImage.genericLinux(runnerAmiMap),
      token: token,
      configuration: {
        // optionally configure your runner
      },
    },
  ],
});

参见示例GitlabRunnerAutoscalingManagerPropsGitlabRunnerAutoscalingJobRunnerProps

多跑步者配置

每个运行器在配置文件[[runners]]中定义一个部分。当您想将跑步者用于特定项目时,请使用特定跑步者。

const privilegedRole = new Role(this, "PrivilegedRunnersRole", {
  // role 1
});

const restrictedRole = new Role(this, "RestrictedRunnersRole", {
  // role 2
});

const token1 = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token1",
});

const token2 = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token2",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token1,
      configuration: {
        name: "privileged-runner",
      },
      role: privilegedRole,
    },
    {
      token: token2,
      configuration: {
        name: "restricted-runner",
        docker: {
          privileged: false, // Run unprivileged
        },
      },
      role: restrictedRole,
    },
  ],
});

请参阅示例GitlabRunnerAutoscalingProps

现货实例

默认情况下,请求 EC2 Spot 实例。

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        machine: {
          machineOptions: {
            requestSpotInstance: false,
            spotPrice: 0.5,
          },
        },
      },
    },
  ],
});

请参阅示例EC2 现货价格MachineConfigurationMachineOptions高级配置 - runners.machine.autoscaling

使用 Multiarch 进行交叉编译

构建不同架构的二进制文件也可以使用Multiarch

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        docker: {
          privileged: true,
        },
      },
    },
  ],
});

配置你的.gitlab-ci.yml文件

build:
  image: multiarch/debian-debootstrap:armhf-buster
  services:
    - docker:stable-dind
    - name: multiarch/qemu-user-static:register
      command:
        - "--reset"
  script:
    - make build

参见multiarch/qemu-user-static

在 AWS Graviton 上运行

要在AWS Graviton上运行您的作业,您必须为 arm64 架构提供 AMI。

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        instanceType: InstanceType.of(InstanceClass.M6G, InstanceSize.LARGE),
        machineImage: MachineImage.genericLinux({
          [this.region]: new LookupMachineImage({
            name: "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-*-server-*",
            owners: ["099720109477"],
            filters: {
              architecture: [InstanceArchitecture.ARM_64],
              "image-type": ["machine"],
              state: ["available"],
              "root-device-type": ["ebs"],
              "virtualization-type": ["hvm"],
            },
          }).getImage(this).imageId,
        }),
      },
    },
  ],
});

请参阅Ubuntu Amazon EC2 AMI 定位器

自定义跑步者的角色

要从您的 GitLab Runner 实例中进行部署,您可以传递一个附加了 IAM 策略的角色。

const role = new Role(this, "RunnersRole", {
  assumedBy: new ServicePrincipal("ec2.amazonaws.com", {}),
  inlinePolicies: {},
});
const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      role: role,
      token: token,
      configuration: {
        // optionally configure your runner
      },
    },
  ],
});

请参阅示例GitlabRunnerAutoscalingProps

虚拟个人电脑

如果没有现有的 Vpc 被传递,将创建一个具有 NatInstance (t3.nano) 和单个 AZ的廉价VPC 。

const natInstanceProvider = aws_ec2.NatProvider.instance({
  instanceType: aws_ec2.InstanceType.of(InstanceClass.T3, InstanceSize.NANO), // using a cheaper gateway (not scalable)
});
const vpc = new Vpc(this, "Vpc", {
  // Your custom vpc, i.e.:
  natGatewayProvider: natInstanceProvider,
  maxAzs: 1,
});

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        // optionally configure your runner
      },
    },
  ],
  network: { vpc: vpc },
});

请参阅示例GitlabRunnerAutoscalingProps

零配置

使用上述默认设置在 AWS EC2 上部署Autoscaling GitLab Runner。

对预设满意吗?

const token = StringParameter.fromStringParameterAttributes(stack, "Token", {
  parameterName: "/gitlab-runner/token",
});

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      token: token,
      configuration: {
        // optionally configure your runner
      },
    },
  ],
});

请参阅示例GitlabRunnerAutoscalingProps

ECR 凭证助手

默认情况下,GitLab amzonec2 驱动程序将配置为在运行程序的实例上安装 amazon-ecr-credential-helper

要进行配置,请覆盖默认的作业运行器环境:

new GitlabRunnerAutoscaling(this, "Runner", {
  runners: [
    {
      // ...
      environment: [
        "DOCKER_DRIVER=overlay2",
        "DOCKER_TLS_CERTDIR=/certs",
        'DOCKER_AUTH_CONFIG={"credHelpers": { "public.ecr.aws": "ecr-login", "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login" } }',
      ],
    },
  ],
});

普罗延

本项目使用projen通过代码维护项目配置。因此,不应手动编辑使用 projen 合成的文件(事实上,projen 强制执行此操作)。

要修改项目设置,您应该与丰富的强类型类AwsCdkTypeScriptApp 交互并执行npx projen以更新项目配置文件。

简单来说,开发者只能修改.projenrc.js配置/维护的文件和/src开发目录下的文件。

另请参阅使用 projen 和 jsii 创建和发布 CDK 构造

项目详情