如何在FreeBSD上设置Buildbot

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Open Internet/Free Speech Fund 来接受捐赠。

介绍

Buildbot是一个作业调度系统,通常用于持续集成(CI)。 CI 是一种软件开发实践,通常包括定期自动构建和测试您的软件,并针对每次更改。 虽然它通常用作 CI 平台,但 Buildbot 也可用于在计算机上运行的任何自动化任务。 Buildbot 的任务执行配置包括四个组件:

  • 更改源:这些检测更改 - 例如 Git 存储库中的更改 - 并通知调度程序它们
  • Scheduler:调度器根据传入的变化触发构建器
  • Builders:这些包含实际的构建步骤,例如软件项目的编译
  • Reporters:记者使用构建结果发送失败邮件或其他通知

Buildbot 通过至少一个 Buildbot master 运行并检查所有构建配置和其他设置,并将实际构建分发给其工作人员。 此外,master 提供了一个基于浏览器的用户界面子组件,如果启用,该子组件用于触发或查看构建以及检查状态报告和其他设置。 还有一个或多个 Buildbot workers 连接到 master 并接收命令,即运行构建。

在本指南中,您将使用 FreeBSD jails 在单独的隔离环境中安装和运行每个 Buildbot 组件。 然后,您将使用 Nginx Web 服务器为 Buildbot 提供服务,并使用本地计算机上的 Web 浏览器访问其 Web 界面。 完成本指南后,您将拥有一个带有示例项目构建的工作设置,可以为您自己的 CI 或其他用例进行扩展。

先决条件

在开始本指南之前,您需要:

  • 运行 FreeBSD 11.2 的服务器,尽管受支持的新旧版本的 FreeBSD 也应该可以工作。 如果您是使用 FreeBSD 的新手,您可能会发现按照我们关于 如何开始使用 FreeBSD 的指南自定义此服务器很有帮助。
  • Nginx 安装在您的服务器上。 按照我们关于 如何在 FreeBSD 11.2 上安装 Nginx 的指南阅读如何设置。

如果您想使用安全的 HTTPS 托管 Buildbot Web 界面,您还需要以下内容:

  • 您拥有和控制的注册域名。 如果您还没有注册域名,您可以在众多域名注册商之一注册一个(例如 Namecheap、GoDaddy 等)。
  • DNS A 记录 将您的域指向您服务器的公共 IP 地址。 这是必需的,因为 Let's Encrypt 如何验证您是否拥有它为其颁发证书的域。 例如,如果您想获得 example.com 的证书,则该域必须解析到您的服务器,验证过程才能正常工作。 您可以按照 这个 DNS 快速入门指南 了解如何添加它的详细信息。 在本教程中,我们将使用 example.com 作为示例域名。
  • 您的域的 SSL/TLS 证书。 按照 How To Secure Nginx with Let's Encrypt on FreeBSD 进行设置。

第 1 步 – 为 Buildbot Master 和 Worker 设置 Jails

由于 Buildbot 允许外部贡献者在您的系统上运行代码,因此建议您隔离其各个组件以防止任意或恶意代码占用您的服务器资源。 在本教程中,您将使用 FreeBSD 监狱执行此操作。

与 LXC、Docker 和其他容器机制类似,FreeBSD 监狱提供与主机系统的轻量级隔离。 在监狱中运行的进程只能访问监狱已被授予访问权限的资源; 否则,它们的行为与任何其他 FreeBSD 环境一样。 Jails 共享相同的内核,但通常运行在具有 FreeBSD 基本系统副本的文件系统上,该副本可能是与主机内核兼容的任何版本的 FreeBSD。 对于大多数工作负载,在主机上运行任务与在监狱中运行任务之间的性能差异并不明显。

存在几个外部软件包来帮助创建和管理 FreeBSD 监狱。 由于它们都不是事实上的标准,我们将使用操作系统内置的监狱配置机制

首先,我们要为系统的监狱创建一个单独的网络接口。 在监狱中,内核将网络连接重写为分配给监狱的第一个 IPv4/IPv6 地址。 例如,如果第一个分配的 IP 地址是公共的,并且监狱中的服务侦听 127.0.0.1:1234,则端口 1234 将可公开访问。 推荐的做法 是为jails 提供一个单独的网络接口。 我们将遵循 克隆 主环回接口 (lo0) 到单独接口 (lo1) 的建议。 我们将使用网络 10.0.0.0/24,但任何其他非重叠网络也可以使用。

首先配置要在引导时创建的克隆接口。 此 sysrc 命令将规则写入 /etc/rc.conf 文件,但不会创建接口本身:

sudo sysrc cloned_interfaces+=lo1

接下来,使用以下命令创建网络接口:

sudo service netif cloneup

您可以使用以下命令检查接口状态和 IP:

ifconfig lo1
Outputlo1: flags=8008<LOOPBACK,MULTICAST> metric 0 mtu 16384
    options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: lo

输出显示接口存在,但尚未列出和附加 IP 地址。 它的标志LOOPBACK表示这个接口只在本地可用,并不代表一个实际的硬件设备。

接下来,使用您喜欢的编辑器为主监狱打开一个新的配置文件。 在这里,我们将使用 ee

sudo ee /etc/jail.buildbot-master.conf

然后将以下内容添加到文件中,这将配置一个名为 buildbot-master 的主监狱:

/etc/jail.buildbot-master.conf

buildbot-master {
    host.hostname = buildbot-master.localdomain;
    ip4.addr = "lo1|10.0.0.2/24";
    path = "/usr/jails/buildbot-master";
    exec.start = "/bin/sh /etc/rc";
    exec.stop = "/bin/sh /etc/rc.shutdown";
    mount.devfs; # need /dev/*random for Python
    persist;
}

此代码在 jail 网络接口 10.0.0.2 上分配一个固定的主机名和 IP 地址,并指定根文件系统 /usr/jails/buildbot-master。 这里使用的 exec.startexec.stop 值声明了 jail 的 startstop 服务的行为类似于启动过程,并使用在/etc/ 目录。 persist 选项可以让监狱继续运行,即使它的所有进程都已完成。

要了解有关可能的主监狱设置的更多信息,请查看 jail(8) 手册页。

添加此内容后,保存并退出编辑器。 如果您使用的是 ee,请按 CTRL+C,键入 exit,然后按 ENTER

主监狱的配置文件与全局监狱配置文件 /etc/jail.conf 是分开的。 因此,您需要将主监狱的名称添加到已知监狱列表中:

sudo sysrc "jail_list+=buildbot-master"

然后启用 jail_list 中列出的任何监狱在启动时自动启动:

sudo sysrc jail_enable=YES

如果您的系统上已经使用 /etc/jail.conf 全局文件配置了 jails,但您之前没有使用过 jail_list,则启用此设置将意味着只有 jail_list 中的 jails 将自动启动,您可能希望将现有的监狱添加到列表中。

注意:如果您使用ZFS文件系统,建议您为jail的文件创建一个单独的数据集,以便以后轻松备份、克隆或销毁它。 以下命令假定您的 zpool 具有标准名称 zroot。 如果您不确定 zpool 的名称,可以使用以下命令找到它:

zpool list

首先,为所有监狱创建父数据集:

sudo zfs create zroot/usr/jails

接下来,创建主监狱的数据集:

sudo zfs create zroot/usr/jails/buildbot-master

接下来,我们将创建主监狱的根目录并解压 FreeBSD 系统。

确保监狱的根文件系统目录存在。 如果您在之前的注释中运行了 ZFS 命令,那么这已经完成,您可以跳过此命令:

sudo mkdir -p /usr/jails/buildbot-master

然后下载 FreeBSD 11.2 基本系统存档。 我们首先安装根证书以信任下载服务器:

sudo pkg install ca_root_nss

此命令将提示您批准安装 ca_root_nss 软件包。 通过按 y 然后按 ENTER 来执行此操作。

接下来,下载存档:

fetch -o /tmp/base.txz "https://download.freebsd.org/ftp/releases/amd64/11.2-RELEASE/base.txz"

将此文件的内容提取为监狱的根文件系统:

sudo tar -x -f /tmp/base.txz -C /usr/jails/buildbot-master

本指南描述了安装一个 worker 的过程——也包含在一个 jail 中——你将以与 master 相同的方式配置它,重用你刚刚下载的基本系统。 使用 ee 命令为工作监狱打开另一个新的配置文件:

sudo ee /etc/jail.buildbot-worker0.conf

将以下内容添加到该文件中:

/etc/jail.buildbot-worker0.conf

buildbot-worker0 {
    host.hostname = buildbot-worker0.localdomain;
    ip4.addr = "lo1|10.0.0.3/24";
    path = "/usr/jails/buildbot-worker0";
    exec.start = "/bin/sh /etc/rc";
    exec.stop = "/bin/sh /etc/rc.shutdown";
    mount.devfs; # need /dev/*random for Python
    persist;
}

查看这些行,请注意工作监狱与主监狱的主机名、IP 和根文件系统目录是如何不同的。 保存并关闭此文件。

同样,因为我们使用单独的监狱配置文件而不是全局 /etc/jail.conf,所以将名称添加到已知监狱列表中:

sudo sysrc "jail_list+=buildbot-worker0"

注意: 与主监狱一样,如果您使用 ZFS 文件系统,建议您为工作监狱的文件创建单独的数据集。 同样,以下命令创建工作监狱的数据集并假设您的 zpool 具有标准名称 zroot

sudo zfs create zroot/usr/jails/buildbot-worker0

解压已经下载的 FreeBSD 11.2 基础系统,就像你对 master 所做的那样:

sudo mkdir /usr/jails/buildbot-worker0
sudo tar -x -f /tmp/base.txz -C /usr/jails/buildbot-worker0

此时,两个jail 都已配置好并包含一个没有安装额外软件包的FreeBSD 基础系统。 让我们开始监狱:

sudo service jail start

通过使用以下命令列出系统上所有正在运行的监狱来检查启动是否成功:

jls

这将返回类似于以下内容的输出,显示当前在您的服务器上运行的监狱:

Output   JID  IP Address      Hostname                      Path
     1  10.0.0.2        buildbot-master.localdomain   /usr/jails/buildbot-master
     2  10.0.0.3        buildbot-worker0.localdomain  /usr/jails/buildbot-worker0

这证实了监狱按预期运行。 但是,此时他们无法访问 Internet,这意味着您将无法在其中安装 Buildbot 软件包。 继续阅读以解决此问题。

第 2 步 – 为监狱设置 Internet 访问

虽然主监狱和工人监狱正在运行,但它们都与互联网隔离。 将它们开放到互联网是必要的,因为它们必须能够安装软件包以及相互通信。

要解决此问题,请将主机的 DNS 解析器配置复制到两个 jails:

sudo cp /etc/resolv.conf /usr/jails/buildbot-master/etc/resolv.conf
sudo cp /etc/resolv.conf /usr/jails/buildbot-worker0/etc/resolv.conf

接下来,路由从监狱传出的互联网流量。 为此,请使用 IPFW(FreeBSD 的内置防火墙)来设置 NAT(网络地址转换)网络规则。 完成此步骤后,流出监狱网络的流量将被转换为您主机的公共 IP 地址。

如果您按照先决条件中的 Let's Encrypt 教程 进行操作,您将已经将防火墙配置为允许访问您的 Web 服务器。 在这种情况下,下面的一些步骤将是多余的,但再次运行它们并没有什么坏处。

警告: 对防火墙配置执行错误更改可能会导致无法通过 SSH 访问远程主机,因此确保您有可用于登录计算机的替代方法非常重要。 例如,如果您使用的是从 DigitalOcean 获得的服务器,您可以通过 “控制台访问” 功能访问它。

要通过此功能启用访问,请使用以下命令设置 root 密码:

sudo passwd

或者,您可以通过键入以下内容为当前用户设置密码:

passwd

使用以下命令在 rc.conf 文件中包含预定义的 workstation 防火墙规则。 workstation 规则保护服务器,但仍然允许基本服务通过,例如 ping 主机或动态主机配置协议:

sudo sysrc firewall_type="workstation"

接下来,允许从外部访问 Web 服务器端口。 以下命令允许通过端口 22 进行 SSH 流量; 端口 80,允许 Buildbot 通过 HTTP 服务; 和端口 443,允许 Buildbot 通过 HTTPS 提供服务。 如果您已使用 Let's Encrypt 保护您的服务器,那么所有这三个端口都是必需的,但如果您还没有并且不打算这样做,那么您可以排除端口 443

sudo sysrc firewall_myservices="22/tcp 80/tcp 443/tcp"

允许从任何 IP 地址访问 firewall_myservices 指令中指定的端口:

sudo sysrc firewall_allowservices="any"

将防火墙配置为在启动时启动:

sudo sysrc firewall_enable=YES

然后使用基本规则启动防火墙。 以下 nohup 命令可避免防火墙启动中断,并将 stderrstdout 重定向到临时日志文件。 这很重要,以免防火墙规则处于不一致的状态,这可能会使您的远程主机无法通过 SSH 访问:

sudo nohup service ipfw start >/tmp/ipfw.log 2>&1

如果您使用 cshtcsh shell,此重定向将导致 Ambiguous output redirect. 出现在您的输出中。 如果您使用这些 shell 中的任何一个,请运行 sudo nohup service ipfw start >&/tmp/ipfw.log 来代替启动 ipfw

此时,防火墙服务将启动并开始保护主机免受与不安全端口的连接。

注意: 如果出现问题或您使用了不同的防火墙类型,防火墙可能还不知道您的 SSH 连接状态,导致您与服务器的连接停止。 你可以通过在 shell 中输入一些东西来找出答案。 在连接停止期间,字符不会打印在远程端。 如果是这种情况,您可以等到 SSH 注意到超时,或者通过依次按下这些键退出挂起的终端:ENTER~、[X176X ]

关闭 SSH 连接后,从本地计算机重新连接到服务器:

ssh freebsd@your_server_ip

如果无法重新建立 SSH 连接,您将需要使用其他方法连接到它。 例如,如果您使用的是 DigitalOcean Droplet,您可以使用其 “控制台访问” 功能以您的 root 用户身份使用您之前设置的密码登录。

一旦您重新获得访问权限,请停用防火墙:

sudo service ipfw stop

防火墙停止后,您将可以自由地调试问题。


接下来,您需要确定连接到 Internet 的主机的网络接口。 通过运行找到它:

ifconfig

该命令可能会输出几个不同的接口。 主机用来连接互联网的那个是包含您服务器的公共 IP 地址的那个。 为了说明,以下示例输出显示 vtnet0 是主机使用的网络接口:

Outputvtnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
    ether 9a:3e:fa:2a:5f:56
    hwaddr 9a:3e:fa:2a:5f:56
    inet6 fe80::983e:faff:fe2a:5f56%vtnet0 prefixlen 64 scopeid 0x1
    inet public_server_ip netmask 0xffffffc0 broadcast broadcast_ip
    inet 10.10.0.23 netmask 0xffff0000 broadcast 10.10.255.255
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    media: Ethernet 10Gbase-T <full-duplex>
    status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
    options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
    inet6 ::1 prefixlen 128
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
    inet 127.0.0.1 netmask 0xff000000
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: lo
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
    options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
    inet 10.0.0.2 netmask 0xffffff00
    inet 10.0.0.3 netmask 0xffffff00
    inet6 fe80::1%lo1 prefixlen 64 scopeid 0x3
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: lo

记下此接口,然后全局配置其名称:

sudo sysrc firewall_nat_interface=vtnet0

打开新的防火墙配置脚本文件:

sudo ee /usr/local/etc/ipfw.rules

然后将以下内容添加到文件中,定义 IPFW 的防火墙规则:

/usr/local/etc/ipfw.rules

#!/bin/sh
set -e

# Add basic rules as defined by firewall_type, firewall_myservices, etc.
. /etc/rc.firewall

# External network interface
ext_if="$firewall_nat_interface"

# The interface we chose for communication between jails
jail_if="lo1"

for interface in "$ext_if" "$jail_if"; do
    if [ -z "$interface" ]; then
        >&2 echo "Missing network interface"
        exit 1
    fi
    if ! ifconfig $interface >/dev/null 2>&1; then
        >2 echo "No such network interface: $interface"
        exit 1
    fi
done

ipfw nat 123 config if $ext_if
ipfw add 1 allow all from any to any via $jail_if
ipfw add 2 nat 123 ip4 from any to any in via $ext_if
ipfw add 501 skipto 20000 udp from any to any 53 out via $ext_if keep-state
ipfw add 502 skipto 20000 udp from any to any 67 out via $ext_if keep-state
ipfw add 503 skipto 20000 tcp from any to any out via $ext_if setup keep-state
ipfw add 504 skipto 20000 icmp from any to any out via $ext_if keep-state
ipfw add 19999 deny all from any to any
ipfw add 20000 nat 123 ip4 from any to any out via $ext_if
ipfw add 20001 allow ip from any to any

以下是脚本的每个部分的作用:

  • . /etc/rc.firewall包含系统预定义的IPFW规则脚本,根据您在/etc/rc.conf中的firewall_*变量配置添加基本规则。
  • 下一个块检查是否所有配置的接口都存在。 这是为了您的安全,如果配置错误,请尽早退出脚本。
  • ipfw 开头的指令添加了实际的防火墙配置和规则。 每条规则——添加到以 ipfw add 开头的行中——都有一个编号。 防火墙使用这些数字按顺序评估规则。 ipfw nat 123 config if $ext_if 创建一个 ID 为“123”的内核内 NAT 工具,以使用面向公众的网络接口转换流量。 ipfw add 1 allow all from any to any via $jail_if 允许监狱之间的所有流量。 请注意,如果允许规则匹配,则规则处理将停止并允许数据包通过。 ipfw add 2 nat 123 ip4 from any to any in via $ext_if 翻译外部接口上所有传入的 IPv4 数据包。 正如 ipfw add 20000... 的解释中所描述的,这是翻译传出数据包所需要的。 ipfw add 501 skipto 20000 udp from any to any 53 out via $ext_if keep-state 并且以下 skipto 规则定义允许哪些出站流量并考虑进行网络地址转换。 如果匹配,则继续处理,跳转到执行 NAT 的规则 20000。 规则编号 501 故意出现在默认环回规则之后,该规则拒绝来自仅限本地网络(127.0.0.0/8 和 ::1)的流量,例如 00300 拒绝从 127.0.0.0/8 到任何网络的 ip。 运行 sudo ipfw list 以查看当前活动的防火墙规则(但请注意,我们尚未应用上述更改)。 除了 skipto 规则外,规则 2 和 19999 之间存在有意的差距,其中 /etc/rc.firewall 脚本插入了某些基本规则。 如果以上 skipto 规则都不匹配,则基本规则将负责允许不同类型的流量,包括环回、传入的 ICMP ping 消息以及由 firewall_myservices 指定的端口。 ipfw add 19999 deny all from any to any 出现在所有基本规则之后,并确保结束非 NAT 规则处理,实质上禁止所有与先前允许规则不匹配的流量。 ipfw add 20000 nat 123 ip4 from any to any out via $ext_if 转换所有离开外部接口的出站 IPv4 数据包的地址。 您在这里只需要 IPv4,因为在本教程中,jail 仅分配了 IPv4 地址。 ipfw add 20001 allow ip from any to any 仅当您关闭了 nat 规则的一次性模式时才需要,在这种情况下,处理将在通过规则 20000 后继续,要求您使用单独的规则明确允许这些数据包通过. 对于默认的一次性模式,防火墙将在 nat 规则处停止处理,因此忽略规则 20001。

保存文件并退出编辑器。

由于我们想用 ipfw.rules 脚本中定义的规则修改预定义的基本防火墙规则,因此我们必须在 rc.conf 文件中指向该脚本。 以下命令将配置脚本以在防火墙启动时执行:

sudo sysrc firewall_script="/usr/local/etc/ipfw.rules"

此设置使用 IPFW 的内核内 NAT 支持,因此您必须告诉系统在引导时加载相应的内核模块。 此外,无需重启即可立即加载模块:

sudo sysrc -f /boot/loader.conf ipfw_nat_load=YES
sudo kldload ipfw_nat

重新启动防火墙以使扩展的防火墙规则脚本生效:

sudo nohup service ipfw restart >/tmp/ipfw.log 2>&1

同样,如果您使用 csh shell 或其派生工具之一(如 tcsh),请运行 sudo nohup service ipfw restart >&/tmp/ipfw.lo 而不是前面的命令来重新启动防火墙:

检查防火墙规则是否已正确加载:

cat /tmp/ipfw.log

这列出了防火墙规则,然后是成功消息:

OutputFlushed all rules.
00100 allow ip from any to any via lo0
[...]
65500 deny ip from any to any
Firewall rules loaded.

您还可以随时使用以下命令查看已安装的防火墙规则:

sudo ipfw list
Output00001 allow ip from any to any via lo1
00002 nat 123 ip from any to any in via em0
[...]
65535 deny ip from any to any

有了所有防火墙规则,您的监狱现在就可以访问互联网了。 您可以通过尝试从监狱中下载网页来进行检查:

sudo jexec buildbot-master fetch -q -o- http://example.com/
Output<!doctype html>
<html>
<head>
    <title>Example Domain</title>
[...]

这样,您就成功地准备好两个监狱,使其像常规操作系统一样运行,为每个监狱设置互联网访问,并启动它们。 本教程接下来的两个步骤将引导您安装主组件和工作组件,然后将它们作为服务运行。

第 3 步 – 安装和运行 Buildbot Master

Buildbot 的组件被分成几个包。 您只需要安装 py36-buildbot 包即可运行主组件,但在本指南中,我们还将介绍如何安装 Web 界面包 py36-buildbot-www

由于我们使用监狱来分割各种组件,因此首先在主监狱中打开一个 root 外壳:

sudo jexec buildbot-master csh

请注意,在本指南中,如果 shell 命令块必须在监狱 shell 中执行,它们会用不同的颜色标记。 此外,命令提示符将反映必须在哪个监狱用户配置文件(root 或非特权 buildbot-master 用户)下运行命令。

安装软件包:

pkg install py36-buildbot py36-buildbot-www

如果您尚未在此监狱中安装或使用 pkg 包管理器,它将提示您确认您允许它自行引导。 为此,请按 y,然后按 ENTER。 然后,通过再次输入 y 来批准 Buildbot 软件包的安装。

接下来,创建一个普通的非特权用户来运行主服务。 以下命令将为该用户分配一个随机密码,但您无需记住它,因为主机(监狱外)的 root 用户可以更改它或成为监狱内的任何用户而无需密码密码:

pw useradd -n buildbot-master -m -w random

在此之后,创建将存储配置的主目录:

mkdir /var/buildbot-master

并将所有权授予服务用户:

chown buildbot-master:buildbot-master /var/buildbot-master

从这一点开始,所有与 master 相关的设置和更改都应该以非特权用户的身份执行,因为这将有助于保持所有权和权限的一致。

切换到非特权用户:

su -l buildbot-master

然后使用内置的 buildbot 实用程序在指定目录下创建目录和配置结构:

buildbot-3.6 create-master /var/buildbot-master

与 Jenkins 等其他 CI 软件不同,Buildbot 的行为直接在其配置文件中定义,并使用 Python 进行解释。 这样可以简化配置的版本控制,而使用脚本语言可以自由编写自定义构建配置并扩展现有的 Buildbot 功能。

Buildbot 包附带一个示例主配置文件,您可以将其用作您自己的配置的模板。 复制示例配置并将其命名为 master.cfg

cp /var/buildbot-master/master.cfg.sample /var/buildbot-master/master.cfg

然后使用您喜欢的文本编辑器打开基本配置文件。 在这里,我们将使用 ee

ee /var/buildbot-master/master.cfg

配置文件包含worker连接到master所需的密码。 用您选择的安全密码替换默认的 pass。 此外,我们的工人的名字将是 worker0,因此在 WORKERSBUILDERS 部分中也将 example-worker 替换为 worker0

完成后,您需要编辑的文件部分将如下所示:

/var/buildbot-master/master.cfg

####### WORKERS

# ...
c['workers'] = [worker.Worker("worker0", "your_secure_password")]
# ...

####### BUILDERS

# ...
c['builders'] = []
c['builders'].append(
    util.BuilderConfig(name="runtests",
      workernames=["worker0"],
      factory=factory))
# ...

保存并关闭此文件,然后运行 exit 命令切换回监狱中的 root 用户:

exit

由于示例配置将 Git 存储库 git://github.com/buildbot/hello-world.git 作为其更改源,因此您还需要安装 Git:

pkg install git-lite

至此,您已经创建了主目录结构和配置,但该服务尚未运行。 要手动运行 Buildbot,可以从主目录 /var/buildbot-master 运行命令 buildbot start。 但是,这不涉及引导时启动或其他系统范围的配置。 相反,我们将使用 rc 脚本,这是 FreeBSD 运行服务的标准方法。 具体来说,我们将使用 service 实用程序来执行此操作。

出于本教程的目的,我们希望使服务能够在每次启动时运行。 在监狱的情况下,这意味着监狱的开始事件。 使用以下命令定义主目录的位置:

sysrc buildbot_basedir=/var/buildbot-master

然后指定服务应该在 buildbot-master 用户下运行:

sysrc buildbot_user=buildbot-master

接下来,使服务在 jail 启动时运行:

sysrc buildbot_enable=YES

在撰写本文时,py36-buildbot 包有一个错误会阻止服务启动(请参阅此错误报告)。 在解决此问题之前,您需要通过在 buildbot-master 监狱中运行以下命令来手动修补启动脚本:

sed -i '' 's|command="/usr/local/bin/buildbot"|command="/usr/local/bin/buildbot-3.6"|' /usr/local/etc/rc.d/buildbot

然后,启动服务:

service buildbot start

该服务应该没有错误地启动。 您可以通过查看日志文件的内容来验证成功:

tail /var/buildbot-master/twistd.log
Output2018-06-08 15:14:52+0000 [-] Starting BuildMaster -- buildbot.version: 0.9.11
2018-06-08 15:14:52+0000 [-] Loading configuration from '/var/buildbot-master/master.cfg'
[...]
2018-06-08 15:14:52+0000 [-] BuildMaster is running

要返回主机外壳,请从监狱外壳运行 exit

exit

您已成功配置并启动 Buildbot 主服务。 第二个组件,worker,是实际运行构建所必需的。 您将在下一部分中在第二个监狱中安装一个工作人员,然后配置其与主服务的连接。

第 4 步 – 安装和运行 Buildbot Worker

尽管 Buildbot master 正在运行,但由于您至少需要一个 worker 运行,因此不会发生任何构建。 此步骤与上一步类似,我们将先设置一个单独的监狱,然后再安装服务。 然而,这一次,Buildbot worker 组件将连接到 master 以侦听命令并报告结果。

此步骤中的说明几乎与 master 设置相同,除了 worker 组件是另一个包的一部分,您将进行的唯一配置更改涉及添加有关将其连接到 master 的详细信息以及有关 worker 本身的一些显示信息。

确保您在主机外壳中,而不是在监狱中。 然后在worker jail中打开一个root shell:

sudo jexec buildbot-worker0 csh

请记住,在本指南中,如果命令块必须在 jail shell 中执行,它们将用不同的颜色标记,并且命令提示符将反映命令应该在哪个用户配置文件下运行。

使用以下命令安装 Buildbot 工作包:

pkg install py36-buildbot-worker

当此命令运行时,它将提示您确认是否要引导 pkg 包管理实用程序。 通过输入 y 来执行此操作。 它还会要求您确认是否批准安装软件包,因此在出现提示时再次输入 y

接下来,创建一个普通的非特权用户来运行 worker 服务:

pw useradd -n buildbot-worker -m -w random

然后创建工作目录。 这是 Worker 的配置、显示信息和构建目录将存储的位置:

mkdir /var/buildbot-worker

将所有权授予服务用户:

chown buildbot-worker:buildbot-worker /var/buildbot-worker

从此时起,所有与工作人员相关的设置和更改都应以非特权用户身份执行。 为此,切换到 buildbot-worker 用户:

su -l buildbot-worker

使用内置的 buildbot-worker 实用程序在 /var/buildbot-worker 目录中创建目录和配置结构。 指定 master jail 的 IP 地址 - 10.0.0.2,我们在上一步中选择了该地址,以便工作人员可以连接到它并将 pass 替换为您在主配置文件中定义的密码:

buildbot-worker-3.6 create-worker /var/buildbot-worker 10.0.0.2 worker0 'pass'

要完成设置,请填写有关系统管理员和工作人员目的的一些详细信息:

echo 'Your Name <your.email.address@example.com>' >/var/buildbot-worker/info/admin
echo 'Description of this worker' >/var/buildbot-worker/info/host

在此之后,运行 exit 命令切换回监狱中的 root 用户:

exit

由于示例配置克隆了 Git 存储库 git://github.com/buildbot/hello-world.git 来构建示例项目,因此您还需要在此 jail 中安装 Git。 请注意,Buildbot master 也需要 Git,因为更改源在 master 上运行。 此外,构建器使用了一个名为 trial 的测试运行器,它是 py27-twisted 包的一部分,因此请与 git-lite 一起安装它:

pkg install git-lite py27-twisted

运行worker的内置机制是buildbot-worker start,它应该从worker目录运行,/var/buildbot-worker。 但是,这并没有处理引导时的启动,也不能确保它会在正确的用户下运行。 正如您对主服务器所做的那样,通过使用 service 实用程序来利用打包的 rc 脚本来管理服务。

使用以下命令定义工作目录以及服务应在其下运行的用户和组:

sysrc buildbot_worker_basedir=/var/buildbot-worker
sysrc buildbot_worker_uid=buildbot-worker
sysrc buildbot_worker_gid=buildbot-worker

接下来,使服务在 jail 启动时运行:

sysrc buildbot_worker_enable=YES

在撰写本文时,py36-buildbot-worker 包有一个错误会阻止服务启动(请参阅此错误报告)。 在解决此问题之前,您需要通过在 buildbot-worker0 监狱中运行以下命令来手动修补启动脚本:

sed -i '' 's|command="/usr/local/bin/twistd"|command="/usr/local/bin/twistd-3.6"|' /usr/local/etc/rc.d/buildbot-worker

最后,启动worker组件:

service buildbot-worker start

该服务应该没有错误地启动。 您可以通过查看日志文件的最新条目来验证它是否成功:

tail /var/buildbot-worker/twistd.log

如果服务启动成功,日志文件中会出现类似Connected to 10.0.0.2:9989; worker is ready的信息。 如果您在此步骤之前忘记指定新密码,服务将无法连接到主服务器。 在这种情况下,编辑文件/var/buildbot-worker/buildbot.tac,然后运行service buildbot-worker restart来解决这个问题。

一旦服务正确启动,通过从 jail shell 运行 exit 命令退出到主机 shell:

exit

至此,第二个监狱已配置完毕,您拥有运行 Buildbot 所需的所有基本组件。 为了方便您的用户使用,建议您还设置基于 Web 的用户界面。 这样做将使您能够更方便地控制 Buildbot 并查看构建结果。

第 5 步 – 设置 Buildbot Web 界面

Buildbot 具有基于 Web 的用户界面,可显示构建概述和结果,并允许您在配置“强制”调度程序时手动触发构建,如示例配置中的情况。

您的主配置已设置 www 组件以通过端口 8010 提供 HTTP。 在生产环境中,您不会提供未加密的 HTTP 或向外部开放非标准端口 8010,因为这会使您的系统面临安全漏洞。 此外,可以从任何 URL 路径提供 Web 界面,这意味着它不需要是您域上的唯一应用程序。 例如,您可以向用户提供构建输出或日志。 因此,我们将使用单独的 Web 服务器 - Nginx 为用户提供 UI,以支持 HTTPS、保护内部端口并获得与 Buildbot Web 界面一起提供其他内容的能力。

打开 Nginx 配置文件进行编辑:

sudo ee /usr/local/etc/nginx/nginx.conf

在文件的现有 server 块中添加以下突出显示的 location 块:

/usr/local/etc/nginx/nginx.conf

 . . .
http {
 . . .
    server {

 . . .
        location / {
            root /usr/local/www/nginx;
            index index.html index.htm;
        }

        location /buildbot/ {
            proxy_pass http://10.0.0.2:8010/;
        }
        location /buildbot/sse/ {
            # proxy buffering will prevent sse to work
            proxy_buffering off;
            proxy_pass http://10.0.0.2:8010/sse/;
        }
        # required for websocket
        location /buildbot/ws {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass http://10.0.0.2:8010/ws;
            # raise the proxy timeout for the websocket
            proxy_read_timeout 6000s;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/local/www/nginx-dist;
        }

                . . .

    }
}

此配置将 URL 路径 /buildbot/ 下的所有请求转发到 Web 界面并启用 WebSocket 支持,界面使用它来接收将显示的更新,例如正在运行的构建的日志输出。

保存并关闭 Nginx 配置文件。 然后,重新加载 Nginx 服务:

sudo service nginx reload

在本地计算机上打开您首选的 Web 浏览器,然后通过以下 URL 访问 Buildbot Web 界面:

https://example.com/buildbot/

或者,如果您没有为服务器设置域名,则需要输入服务器的公共 IP 地址 http://your_server_ip/buildbot/

当您到达界面时,您将看到类似于以下内容的概述:

主页可能会显示 Buildbot URL 配置错误的警告。 如果 nginx.conf 文件中提供的主机名与主 Buildbot 配置中列出的主机名不匹配,则会发生这种情况。 由于默认情况下构建结果电子邮件包含指向 Buildbot Web 界面的链接,因此主服务器必须知道可以访问它的正确 URL。

请注意,在我们的示例配置中,我们尚未设置此电子邮件服务。 如果您对此感兴趣,请参阅 Buildbot 的 关于记者 的文档以获取更多信息:

话虽如此,要解决警告并发送包含正确内容的电子邮件,请编辑 Buildbot 主配置以指向您的域。

sudo ee /usr/jails/buildbot-master/var/buildbot-master/master.cfg

找到以 c['buildbotURL'] 开头的行并将默认选项替换为您的域名,然后是 /buildbot/

/var/buildbot-master/master.cfg

####### PROJECT IDENTITY
# ...
c['buildbotURL'] = 'https://example.com/buildbot/'
# ...

保存并关闭文件。 然后,要应用新配置,重新加载 buildbot 服务:

sudo jexec buildbot-master service buildbot reload

在浏览器中刷新 Buildbot Web 界面,警告将消失。

持续集成服务器通常用于 CI 之外的其他目的。 例如,CI 服务器可能会通过 HTTPS 为 FreeBSD 包或日志提供构建输出。 因此,建议您为 Web 界面保留 URL 路径 /buildbot/。 这允许您在不同路径下托管更多应用程序。 目前,我们将创建一个重定向到 Web 界面的简单主页。 为 Web 服务器实现更多用例后,您可以添加更多链接。

运行以下命令在您的 Web 根目录中打开一个索引文件 - 将 example.com 替换为您自己的域 - 以创建到 Buildbot Web 界面的自动重定向:

sudo ee /usr/local/www/example.com/html/index.html

注意:如果你没有按照先决条件Nginx教程为你的Nginx配置创建一个新的web根目录,你需要在下面创建一个索引文件通过运行 sudo ee /usr/local/www/nginx/index.html 来默认 Nginx Web 根目录。


将任何现有文件内容替换为以下行:

/usr/local/www/nginx/index.html

<html>
<body>
<a href="/buildbot/">buildbot</a>
<script>
    // Auto-redirect while only the web interface should be served
    window.location.href = "/buildbot/";
</script>
</body>
</html>

保存并关闭此文件,然后在浏览器的 URL 栏中输入您的域名或 IP 地址。 它应该会自动将您重定向到 Buildbot 界面。

您已完成所有 Buildbot 组件的安装,包括其基于 Web 的控制和查看界面。 完成所有这些后,让我们按照我们为 master 设置的示例配置中指定的方式运行实际构建。

该构建器默认配置了一个“强制”调度程序,它允许您触发您的第一个构建。 在网页界面,点击 Builds > Builders > runtests > force > Start Build构建运行。 如果您看到任何错误,请检查服务器的 Internet 连接以及是否按照前面所述安装了所有依赖包。

通过查看构建目录的内容,您可以从该构建(和其他构建)中找到工件:

ls /usr/jails/buildbot-worker0/var/buildbot-worker/runtests
Outputbuild

您已经成功配置了一个永久运行的多功能 CI 系统,现在可以开始实施您自己的构建。

结论

通过完成本教程,您练习了创建 FreeBSD 监狱并学习了 Buildbot 自动化框架的一些基础知识,从而获得了即用型安装。 要了解有关 Buildbot 及其配置的更多信息,我们鼓励您通读 官方 Buildbot 文档

从这里,您可以自由地实施自己的持续集成和自动化实践。 为了在生产环境中使用安全、稳定和高性能的设置,您可能需要执行以下可选配置步骤:

  • 仅使用 HTTPS(如本教程中所述)
  • 在本教程中,您为 jails 使用了一个单独的主机内部网络 lo1。 在本指南中,我们将 ipfw 用于 NAT 目的,但其他防火墙也具有此功能。 查看有关 可用防火墙 的 FreeBSD 文档。 除非您的用例另有要求,否则建议通过使用 NAT 或其他机制使监狱网络无法从外部访问。
  • Buildbot 的 Web 界面默认不需要登录或检查用户权限。 要实现这些,您必须启用 用户身份验证