it work on my machine
前几天, 我的 github action 突然就出现了测试失败的错误, 并且报错也也极具迷惑性, 他的报错是数据库连接关闭, 我还以为是我的数据库配置出问题了, 最后在几个不同发行版下测试, 甚至还在生产环境跑了一遍, 基本上可以判断是 github action 的问题.
我怎么发现的?这就说来话长了, 都快可以再水一篇了(
总之, 不知道什么原因 github action 导致我的代码出现级联故障, 也就是数据库连接被关闭的根本原因. (因为 github action 是商业软件, 既不开源也不可以在本地运行,鬼知道我调了多久. 更正, github action 的 runner 是部分开源的, 这部分可以自部署, 但是 action 服务端依旧是闭源的)
woodpecker CI
why woodpecker CI?
因为我之前因为受到一篇文章的影响, 把代码库迁移到了完全开源的 codeberg 平台, 而 codeberg 使用的 CI是 woodpecker, 于是我决定使用 woodpecker 来作为 github action 的替代品. (什么是 CI? 简单来说就是提交代码之后就会自动运行的一个脚本, 你可以在 red hat 的这篇文章里找到更详细的解释)
但是 codeberg 提供的 woodpecker 是志愿者自发提供的, 也不太好意思白嫖, 正好手里也有闲置的机器, 于是就自己搭一个吧.

赞美太阳! (也赞美开源社区)
首先, 一个完整的 woodpecker 是分成两部分的, 一部分是一个中心化的控制面板 woodpecker server, 一部分是执行 CI 工作流的 woodpecker agent.
首先, 他与 github action 有那些不同呢?
github action 的每次工作流都是在同一台机器 (虚拟机?) 的同一个环境下运行的, 但是 woodpecker 不是, woodpecker 工作流的每一次操作步骤 (step) 都是由一个单独的容器来进行操作的, 这个容器会挂载 git 拉下来的代码到容器里的工作区, 然后再进行操作. 一般来说这个工作区目录是 /woodpecker/src.
经常用容器的应该知道, 这样的方法就意味着每个步骤之间运行时环境都是相互隔离的. (而 githun action 在系统中安装的运行时会集成到下一个步骤, 因为都是同一个虚拟机) 所有的更改只有在 /woodpecker/src 目录下的才会被继承到下一个步骤. (熟悉 k8s 的同学应该不会陌生这种需要容器来进行操作的方式, 跟 pod 编排很像)
这看起来是一个负面 buff?
不不不, 这当然不是 (至少对于我来说不是). 回头想想我的 CI 环境是怎么炸的? 虽然我也不是很清楚, 但是怀疑是 github action 更新了某个东西. (自从 ms 接手 GitHub 之后就一直不太稳定, uptime 经常是五颜六色的)
但是基于镜像的工作流就没有这种问题, 容器镜像都是唯一确定的, 不会存在像我之前遇到的那样, 明明昨天能跑, 但是今天就炸了的情况. 只要用的是同一个镜像, 就可以实现 "working in anywhere". (相当于通过引入镜像的不可变性, 来实现 CI 的可复现功能. 怎么感觉这么说反而更绕了)
说到可复现性, 那就不得不提:

woodpecker CI 的配置文件总体上跟 github action 很像, 所以这次迁移也没有花太大的力气, 具体的语法可以去官方文档上看, 我就不再复述了. (或者可以直接把文档丢给 AI 让他帮你迁移, markdown 格式的文档可以直接在 git 仓库里找到)
install
我的 woodpecker server 部署在 k3s 集群中, 官方在文档里提供了一行命令安装的方式, 直接 helm install 就可以装上.

(呜呜, 别骂了, 但是 GUI 界面确实很好用)
而 woodpecker agent 我则是部署在 k3s 集群外的 docker 环境中的 (因为这个机器与 其他的延迟太高了, 加入集群反而影响性能).
那么这样的话, 可能也会有一个问题, 关于 agent 的, 容器套容器的方式可能会有那么亿点点 (指尖宇宙.png) 权限问题.
因为我的工作流涉及容器构建, 但是容器构建又是通过再创建一个类似于容器的东西来进行安全隔离的, 这一步可能会因为容器中没有这么高的权限而被系统拒绝. 这涉及 Linux 内核的很多安全机制, 比如说挂载 overlayfs 来进行容器的镜像层堆叠, 创建 namespace 隔离构建环境, 使用 cgroup 进行资源限制等. 其中的原理太复杂了, 感兴趣的话可以自己去研究一下.

以及, 以 rootless 著称的 podman 在鼓捣了一圈之后 buildah (podman 的构建引擎) 能够在我的开发机上的容器环境中正常运行, 但是到服务器上之后又不行了. 悲(
所以, 最简单的方式, 开特权容器. 在启动容器的时候可以设置 privileged 为 true, 这样可以拉起一个几乎没有什么限制的容器. 但是代价是, privileged 四舍五入跟 root 权限没有什么区别. 所以, 必须在你信任, 并且没有公共 pr 触发的工作流中使用.
(或者, 可以直接使用宿主机的 docker/podman 来进行构建, 不过这样也要挂载 docker.sock/podman.sock, 其实跟特权容器也差不了多少, 但是因为构建缓存的原因会更快一点)
但是, 我的工作流还是有点问题的, 因为我的构建的服务器配置实在是太差了, 一次构建需要花费差不多 20 分钟, 而在 github action 上只需要一分钟. 再也不买劣质服务器了, 呜. 主要我的性能比较高的服务器 16G 内存用了 13G, 实在是不太适合再跑什么其他的服务了.
唯一值得注意的, 大概就是 gRPC 了, 虽然 Cloudflare CDN 支持 gRPC, 但是并不能长时间创建连接, 超过两分钟就会被 cf 掐网. 所以得想个办法绕过 cf 的 CDN, 我就是直接在 hosts 文件里指定了服务器的 IP 来绕过的, 反正我的源服务器也有 TLS 证书. 咕~
Python
鼓捣了这么多云原生相关的东西, 我要提出一个暴论, python -- 云原生界的鸡煲.

何以见得?
- 鸡煲启动速度很快, 只需要一张 "创造性AI"; 而 python 的编译速度也很快, 以 0s 的速度直接杀死比赛(
- 鸡煲的启动周期长, 容易暴毙; python 启动也需要加载几十上百兆的 site-packages (第三方库), 容易 OOM (Out-of-Memory)
- 鸡煲实力强劲, 尖塔战力排名前五; python 也是世界上最流行的编程语言之一, 近几年从没跌出过前三
- 鸡煲在尖塔人气很高, 拥有大批忠实玩家; python 也有很多忠实用户,
比如说我, 要我来背一段 PEP20 来证明一下吗.
(仅供娱乐)