目录

  • Github 操作

  • 是什么造就了动作跑者?

  • 目前可自动化的是什么?

*初始下载

*配置跑步者

*跑步者

*在 docker 容器中快速测试

  • Dockerizing 跑步者

  • 结论

Github 操作

开箱即用的自托管动作运行器是静态的,因此必须在它们自己的 VM 或类似 Kubernetes 中的 StatefulSet 的东西上运行。这使得它们非常昂贵。如果他们每次提交都启动,运行一项工作,然后进行清理,那不是很好吗?

在接下来的几篇文章中,我将尝试构建一个执行此操作的系统。第一篇文章将逐步介绍我最初如何将自托管操作 docker 化。

是什么造就了动作跑者?

可以按照 repo 中的 Settings -> Actions 菜单中给出的说明,针对给定的 repo 注册自托管的 action runner。简而言之,说明是:


$ mkdir actions-runner && cd actions-runner
$ curl -O -L https://github.com/actions/runner/releases/download/v2.164.0/actions-runner-linux-x64-2.164.0.tar.gz
$ tar xzf ./actions-runner-linux-x64-2.164.0.tar.gz
$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}
$ ./run.sh

√ Connected to GitHub

2020-02-01 21:01:15Z: Listening for Jobs

进入全屏模式 退出全屏模式

请注意,此处和本文其余部分中的 ${TOKEN} 指的是您从 UI 收到的操作运行程序注册令牌。

这将启动一个自托管的操作运行程序,它将侦听新的提交并运行为这些提交配置的操作。config.shrun.sh脚本都调用了一个 .Net core 二进制文件,它可以完成真正的工作。

这很棒,现在您可以在自己的基础架构上运行操作。如果您在一家大公司工作,这是一笔大买卖,因为通常您的构建可能需要的构建工具和其他资源只能从内部网络访问。但是,这些自托管操作的运行方式存在一些问题:

  • 如果你有很多存储库——假设你有一个私有的 github 组织——你现在至少有一个 VM、kubernetes pod 或一些必须不断运行的资源。如果您的组织有 100 多个存储库,这在资源方面可能非常昂贵。

  • 为创建的新存储库添加新的操作运行器并不简单。

  • 如果一个 repo 每天都有很多提交,那么扩展这些操作也不是一件容易的事。

  • 在设置说明中运行的脚本需要一些手动干预(至少默认情况下,稍后会详细介绍),因此自动化它可能会很棘手。

问题是,我们能解决这些问题吗?让我们从抽象设置开始,并为此创建一个 docker 映像。

目前什么是可自动化的?

在我们开始为跑步者创建图像之前,让我们完成设置步骤,看看当前需要手动干预什么。

初始下载

初始下载是完全自动化的,无需人工干预:

$ cd /var/tmp
$ mkdir actions-runner && cd actions-runner
$ curl -s -O -L https://github.com/actions/runner/releases/download/v2.164.0/actions-runner-linux-x64-2.164.0.tar.gz
$ tar xzf ./actions-runner-linux-x64-2.164.0.tar.gz

进入全屏模式 退出全屏模式

我们应该有一个包含以下内容的目录:

$ ls -la
total 73680
drwxr-xr-x  4 chaospie chaospie     4096 Dec 18 20:41 ./
drwxrwxrwt 12 root     root         4096 Feb  1 20:13 ../
-rw-rw-r--  1 chaospie chaospie 75400617 Feb  1 20:14 actions-runner-linux-x64-2.164.0.tar.gz
drwxr-xr-x  2 chaospie chaospie    16384 Dec 18 20:41 bin/
-rwxr-xr-x  1 chaospie chaospie     2671 Dec 18 20:40 config.sh*
-rwxr-xr-x  1 chaospie chaospie      623 Dec 18 20:40 env.sh*
drwxr-xr-x  4 chaospie chaospie     4096 Dec 18 20:41 externals/
-rwxr-xr-x  1 chaospie chaospie     1666 Dec 18 20:40 run.sh*

进入全屏模式 退出全屏模式

配置运行器

让我们配置我们的跑步者。

$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}

-------------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
-------------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration

Enter the name of runner: [press Enter for sky]

进入全屏模式 退出全屏模式

似乎配置需要手动输入。让我们看看config.sh的帮助中是否提到了什么:

 ./config.sh --help

Commands:,
 ./config.sh          Configures the runner
 ./config.sh remove   Unconfigures the runner
 ./run.sh             Runs the runner interactively. Does not require any options.

Options:
 --version  Prints the runner version
 --commit   Prints the runner commit
 --help     Prints the help for each command

进入全屏模式 退出全屏模式

没有什么。看起来没有设置动作运行器名称的参数。我们现在可以作弊:

$ echo my-runner | ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}

-------------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
-------------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration

Enter the name of runner: [press Enter for sky]
√ Runner successfully added
√ Runner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]
√ Settings Saved.

进入全屏模式 退出全屏模式

太好了,全自动配置设置!请注意,这还将第二个手动输入请求(工作文件夹)默认为_work

跑步者

run.sh没有参数或手动输入请求,因此这显然是可自动化的。

在 docker 容器中快速测试

让我们在 docker 容器中进行快速测试:

$ docker run -ti --rm ubuntu:18.04 bash

$ mkdir actions-runner && cd actions-runner

$ curl -O -L https://github.com/actions/runner/releases/download/v2.164.0/actions-runner-linux-x64-2.164.0.tar.gz
bash: curl: command not found

# Ah! There is no curl in the default ubuntu 18.04 image, let's just install it for now.

$ apt update && apt install -y curl
Get:1 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:2 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
...
done.

$ tar xvf actions-runner-linux-x64-2.164.0.tar.gz
./
./bin/
./bin/System.Security.Cryptography.OpenSsl.dll
./bin/System.Memory.dll
./bin/System.Runtime.Serialization.Json.dll
./bin/System.IO.Compression.FileSystem.dll
...

$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}
Must not run with sudo

进入全屏模式 退出全屏模式

看来我们不能以 root 或 sudo 运行config.sh!这是有道理的,通常您不应该使用提升的用户运行构建。似乎需要做一些工作才能将这个容器化。

Docker 化运行器

让我们创建一个简单的 Dockerfile 来解决这个问题:

FROM ubuntu

ENV RUNNER_VERSION=2.164.0

RUN useradd -m actions \
    && apt-get update && apt-get install -y wget

RUN cd /home/actions && mkdir actions-runner && cd actions-runner \
    && wget https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
WORKDIR /home/actions/actions-runner
USER actions

进入全屏模式 退出全屏模式

构建并运行:

$ docker build -t actions-image .
Sending build context to Docker daemon  70.66kB
Step 1/9 : FROM ubuntu
 ---> 775349758637
...

$ docker run -ti --rm actions-image

$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}
Libicu's dependencies is missing for Dotnet Core 3.0
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.

进入全屏模式 退出全屏模式

一个新的错误!似乎我们缺少依赖项。方便地,动作运行器设置为我们提供了一个脚本来设置所有内容。让我们更新我们的 Dockerfile:

FROM ubuntu

ENV RUNNER_VERSION=2.164.0

RUN useradd -m actions \
    && apt-get update && apt-get install -y wget

RUN cd /home/actions && mkdir actions-runner && cd actions-runner \
    && wget https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz

WORKDIR /home/actions/actions-runner

# Here we install the dependencies needed by the runner
RUN /home/actions/actions-runner/bin/installdependencies.sh

USER actions

进入全屏模式 退出全屏模式

再次构建并运行:

$ docker build -t actions-image .
Sending build context to Docker daemon  70.66kB
Step 1/9 : FROM ubuntu
 ---> 775349758637
...

$ docker run -ti --rm actions-image

$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}
touch: cannot touch '.env': Permission denied
./env.sh: line 36: .path: Permission denied
Unhandled exception. System.UnauthorizedAccessException: Access to the path '/home/actions/actions-runner/_diag' is denied.
 ---> System.IO.IOException: Permission denied
   --- End of inner exception stack trace ---
   at System.IO.FileSystem.CreateDirectory(String fullPath)
   at System.IO.Directory.CreateDirectory(String path)
   at GitHub.Runner.Common.HostTraceListener..ctor(String logFileDirectory, String logFilePrefix, Int32 pageSizeLimit, Int32 retentionDays)
   at GitHub.Runner.Common.HostContext..ctor(String hostType, String logFile)
   at GitHub.Runner.Listener.Program.Main(String[] args)
./config.sh: line 79:    44 Aborted                 (core dumped) ./bin/Runner.Listener configure "$@"

进入全屏模式 退出全屏模式

啊,更多的错误!这次权限问题。如果我们检查该目录中文件的权限,我们可以看到所有者是错误的。所有这些文件的所有者应该是 actions 用户:

$ ls -la
total 73676
drwxr-xr-x 4    1001     115     4096 Dec 18 20:41 ./
drwxr-xr-x 1 actions actions     4096 Feb  1 20:43 ../
-rw-r--r-- 1 root    root    75400617 Dec 18 20:44 actions-runner-linux-x64-2.164.0.tar.gz
drwxr-xr-x 2    1001     115    16384 Dec 18 20:41 bin/
-rwxr-xr-x 1    1001     115     2671 Dec 18 20:40 config.sh*
-rwxr-xr-x 1    1001     115      623 Dec 18 20:40 env.sh*
drwxr-xr-x 4    1001     115     4096 Dec 18 20:41 externals/
-rwxr-xr-x 1    1001     115     1666 Dec 18 20:40 run.sh*

进入全屏模式 退出全屏模式

另一个 Dockerfile 更新:

FROM ubuntu

ENV RUNNER_VERSION=2.164.0

RUN useradd -m actions \
    && apt-get update && apt-get install -y wget

RUN cd /home/actions && mkdir actions-runner && cd actions-runner \
    && wget https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
WORKDIR /home/actions/actions-runner

# Here we change owner to user actions on the actions user's home directory
RUN chown -R actions ~actions && /home/actions/actions-runner/bin/installdependencies.sh

USER actions

进入全屏模式 退出全屏模式

最后再次运行:

$ docker build -t actions-image .
Sending build context to Docker daemon  70.66kB
Step 1/9 : FROM ubuntu
 ---> 775349758637
...

$ docker run -ti --rm actions-image

$ ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}

-------------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
-------------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration

Enter the name of runner: [press Enter for 0ccb204b3990] my-runner

√ Runner successfully added
√ Runner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]

√ Settings Saved.

$ ./run.sh

√ Connected to GitHub

2020-02-01 21:22:24Z: Listening for Jobs

进入全屏模式 退出全屏模式

伟大的!现在让我们让它对任何存储库都通用。为此,让我们创建一个entrypoint.sh,如下所示:

#!/usr/bin/env bash

OWNER=$1
REPO=$2
TOKEN=$3
NAME=$4

echo ${NAME} | ./config.sh --url https://github.com/${OWNER}/${REPO} --token ${TOKEN}

./run.sh

进入全屏模式 退出全屏模式

并更新我们的 Dockerfile:

FROM ubuntu

ENV RUNNER_VERSION=2.164.0

RUN useradd -m actions \
    && apt-get update && apt-get install -y wget

RUN cd /home/actions && mkdir actions-runner && cd actions-runner \
    && wget https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
WORKDIR /home/actions/actions-runner

RUN chown -R actions ~actions && /home/actions/actions-runner/bin/installdependencies.sh

USER actions

# Add the script and make it the entrypoint
COPY entrypoint.sh .
ENTRYPOINT ["./entrypoint.sh"]

进入全屏模式 退出全屏模式

让我们构建并测试它:


$ docker run -ti --rm actions-image
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"./entrypoint.sh\": permission denied": unknown.

进入全屏模式 退出全屏模式

哎呀!我忘了使脚本可执行。使脚本可执行以修复:

$ chmod +x entrypoint.sh

$ docker build -t actions-image .
Sending build context to Docker daemon  70.66kB
Step 1/9 : FROM ubuntu
 ---> 775349758637
...
Step 9/9 : ENTRYPOINT ["./entrypoint.sh"]
 ---> Using cache
 ---> a6535399773a
Successfully built a6535399773a
Successfully tagged actions-image:latest

$ docker run -ti --rm actions-image ${OWNER} ${REPO} ${TOKEN} my-runner

-------------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
-------------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration

Enter the name of runner: [press Enter for a05fbb6da3db]
√ Runner successfully added
√ Runner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]
√ Settings Saved.


√ Connected to GitHub

2020-02-01 21:28:51Z: Listening for Jobs

进入全屏模式 退出全屏模式

太好了,一切都按预期工作!然而有几个问题:

  • 您需要为每个要启动的运行器手动运行一个容器。

  • 启动的每一个runner都需要手动清理。

  • 任何启动的运行器都可以在空闲时为新提交执行任何作业,因此清理运行器可能会意外杀死正在进行的构建。

  • 注册令牌很难检索。最近 github 发布了一个 API 来生成这个令牌。在下一篇文章中,我们将自动检索此令牌。

  • 在当前状态下,跑步者不会取消注册,这意味着您必须从 UI 执行此操作。

到目前为止的代码可以在这里看到。

结论

在这篇文章中,我们创建了一个非常简单的 docker 镜像,用于自动化自托管操作运行器注册。在下一篇文章中,我们将通过查看动作运行器源代码来改进这一点,其中包含许多隐藏参数,这些参数将使我们能够实现比目前更多的自动化。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐