Fedora koji构建系统详细教程之二 -- 构建

写在前面

本篇文章是上一篇文章的继续,由于koji里面的内容实在是太多,都塞进一篇文章里会显得很臃肿,于是我就拆成了两部分。在上一篇文章里,我们已经部署好了Fedora koji系统,此时kojihub已经运行、可以通过kojiweb或koji命令去访问,并且也打开了kojira和kojid,这时候你已经具备构建的能力了。在这篇文章里,我会在x86_64上构建x86_64的rpm包,然后再进行RISC-V rpm包的构建,因为这涉及到一个RISC-V虚拟机部署问题,实际上内容和问题也不少。这篇文章仍然需要慢慢完成,内容也比较多,请大家仔细观看。

一些资料:

  1. Mock配置
  2. leapmotion的文章
  3. Mock辅助编译
  4. RISC-V构建机builder


一、构建前准备

1、创建标签并配置

koji里的标签称为tag,这个tag就是某一个Linux发行版的所有软件包的集合的名称。比如说我要创建一个f40_x86_64这个标签,意思就是说这个标签代表了Fedora40 x86_64这个发行版它所规定的所有软件包集合的名称叫做f40_x86_64.实际上这个名字你是可以随便取的,不过最好是取得要规范。名称只是一个象征,真正重要的是你导入的软件包名和版本信息,它们会和你所创建的这个标签绑定。不仅仅是Fedora可以这样,比如说openEuler你也可以这样,只要你获得了或者自己制作了这个软件包信息的txt文件,就可以创建一个名叫openEuler24.03_x86_64这样一个标签去代表这么一个24.03openEuler的发行版。

甚至于说比如我喜欢LFS,那么我就可以自己制作一个属于自己的Linux发行版。我举个例子,比如我想基于LFS制作一个April Linux发行版,那么我就可以自己弄一个april_pkg_list.txt,然后创建April_x86_64标签,这么构建出来的一套软件包再发行出去。那么我的这个April Linux操作系统就可以发布出去让大家都使用了!

我以iscas的kojiweb展示出来的信息为例,就是说每一个Linux发行版对应一个tag,你每需要一个仓库就得来一个标签。同一发行版如果版本不同,也需要独自创建一个tag.

不知道大家对这个标签tag的概念是否已经清楚,标签代表着某个release(或者基于这个release的变体/开发版本)所包含的所有软件包集合。

koji add-tag f40_x86_64

# koji add-tag 标签名      增
# koji remove-tag 标签名   删
# koji list-tags          查

koji的命令总是一类命令,如果你的标签创建错误也不用怕,删掉重新创建就好。

添加(package)软件包列表(只是包名)到这个tag:

cat f40_pkg_list.txt | xargs -n 1024 koji add-pkg --owner kojiadmin f40_x86_64

大家还记得f40_pkg_list.txt吧,这个就是在第一篇文章里从Fedora project的kojihub里获取到的信息,因为那时候april_zhao用户的koji命令默认指向Fedora官方的koji ,所以获取到这个文件是比较容易的。但是你一旦部署好了之后,让其指向你自己部署的kojihub,那么这个文件你就获取不到了,所以我把这部分放在第一篇的最前面。但是如果说你当时没有通过Fedora的kojihub获取到这个文件也没有关系,你可以开另一台Fedora设备然后安装koji ,获取到这两个文件之后再使用scp命令从局域网传递到做实验用的虚拟机里。

不过最快速一点的方法是你可以开一个Fedora的docker,这样会很快。我会在后面RISC-V架构打包的环节演示这个过程。

批量导入包名到标签里。在导入的过程中可能出现database outage的问题,因为postgresql会莫名其妙不太稳定,所以你可以重启一下数据库然后重新执行导入包名的命令。

sudo systemctl restart postgresql koji-sweep-db

一旦你导入了这些包名,那么你的Summary统计信息就不会像以前那样光秃秃的了,而是会把这些信息展示在这里,你可以对比一下Fedora和iscas的kojiweb是不是也是这样。

这里大家可以对比观察现象,就是说你每做一步操作,就去kojiweb里看看有什么地方不一样。眼见为实,你实践过了,就不会觉得这些概念很抽象了。


2、创建构建标签并配置

koji add-tag --parent f40_x86_64 --arches "x86_64" f40_x86_64_build

从这里面我们可以看出来,f40_x86_64这个标签是f40_x86_64_build的父标签(parent tag).

构建标签(build tag)代表基于其父标签的一个构建环境。意思就是说我们做任何操作都使用这个f40_x86_64_build子标签,这样就不会破坏父标签的信息。

导入组信息
1) fedora功能分组信息
koji import-comps fedora-comps/comps-f40.xml f40_x86_64_build

comps-f40.xml 文件定义了软件包组的列表和描述,这些组可能包括特定的应用程序、工具和库。通过导入这些信息,可以帮助在构建过程中正确选择和安装需要的软件包组,确保构建环境的完整性和一致性。

2) 导入koji编译系统特定的分组信息
koji import-comps comps_f40_koji.xml f40_x86_64_build

comps_f40_koji.xml在第一篇文章里也已经得到了。

comps_f40_koji.xml 文件定义了一系列与构建和打包相关的软件包组,例如 appliance-buildbuildkiwi-buildlivecd-buildlivemedia-buildsrpm-build。这些组包含了一些必需的工具和库,用于特定类型的构建任务,如构建 SRPM 包等。


3、创建构建目标

koji add-target f40_x86_64_build_target f40_x86_64_build f40_x86_64


# koji add-target <target name> <build tag> <des tag>   添加构建目标
# koji remove-target <target name>                      删除构建目标
# koji list-targets List the build targets              列出构建目标

构建目标(build target),描述的是一个构建的过程,其中包含你已经创建的前两个标签:tag和build tag。


4、添加构建仓库(外挂仓库)

koji add-external-repo -t f40_x86_64_build base-external-repo https://mirrors.ustc.edu.cn/fedora/releases/40/Everything/x86_64/os/

我们在这里添加一个外部仓库到构建标签,由于我们是要构建Fedora40的rpm包,所以添加的仓库也应该是Fedora40的,名称只是方便我们去表达含义,本质还是这个外挂仓库的地址。ustc源是一个稳定源。

如果需要添加多个外部仓库,koji 会给每个仓库以先入先出(FIFO)的顺序指派一个优先级。这就可能导致更新包可能由于旧包所在的仓库优先级高(数字越小优先级越高)而不可见。

1) 加入构建组
koji add-group f40_x86_64_build build
koji add-group f40_x86_64_build srpm-build
koji add-group f40_x86_64_build appliance-build

实践中构建标签(build tag)必须的 build组信息有build、srpm-build、appliance-build

  • build 组:

    • 这个组是构建 RPM 软件包的核心组。它通常包含用于编译、构建、打包和测试软件的基本工具和依赖项。例如,C/C++ 编译器、构建工具(如 makecmake)、调试工具以及其他构建过程中可能需要的软件包。
  • srpm-build 组:

    • 这个组专门用于构建 SRPM(Source RPM)包。SRPM 是包含软件源代码和构建脚本的 RPM 包,通常用于生成可分发的二进制 RPM 包。srpm-build 组中的工具和依赖项确保可以正确地从源代码构建出 SRPM 包。
  • appliance-build 组:

    • 这个组用于构建虚拟设备或系统镜像(appliance),通常包括将软件和操作系统打包成一个可部署的设备映像所需的工具。这个组中的工具通常涉及到系统镜像的创建、虚拟化工具(如 qemu)以及用于创建引导加载器和文件系统映像的软件。

2) 添加meta包

这一步就是把package添加到对应的group里面去

koji add-group-pkg f40_x86_64_build build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep
koji add-group-pkg f40_x86_64_build srpm-build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep


到目前为止,我们已经实践过添加tag、添加target、添加外部仓库,我们需要注意的是:最为kojiadmin管理员用户,我们需要对这些已有的信息了如指掌。对于tag和target ,我们可以在kojiweb界面查看,所以很方便,但是外部仓库有哪些就不是那么方便查看了。所以我们现在来复习一下,用koji命令行去查看已有的一些信息。

 

koji子命令作用
list-api打印 XML-RPC API 列表
list-buildroot列出 buildroot 中使用或内置的 rpm
list-builds打印构建列表
list-channels打印频道(host的权限)列表
list-external-repos列出外部存储库
list-groups打印组列表
list-history显示历史数据
list-hosts打印主机列表
list-permissions列出用户权限
list-pkgs打印标签或所有者的软件包列表
list-tag-inheritance打印标签的继承信息
list-tagged列出标签中的构建或 rpm
list-tags打印标签列表
list-targets列出构建目标
list-untagged列出未标记的构建
list-volumes列出存储卷

然后我们可以举一反三,把其中的list改成add就变成添加,改成remove就变成删除。其中list由于数量不会唯一,所以后面的参数为复数形式,比如hosts、targets、tags这样带有s.

其中有些参数我们可能并不熟悉和了解,不过你也可以打印出来看看。


6、createrepo权限与重建仓库信息

我们现在需要重建仓库,但是host默认的defaut权限是无法进行这个操作的,需要createrepo权限才可以,所以我们需要给我们唯一的host(kojibuilder1)添加这一权限。

koji add-host-to-channel kojibuilder1 createrepo

# koji add-host-to-channel host名 channel权限名
# koji remove-host-from-channel host名 channel权限名

可以在命令行如此操作,也可以在kojiweb里点击添加。

koji regen-repo f40_x86_64_build

这也是我们首次提交任务,当你执行这行代码之后,就会在Tasks界面里提交两个任务。

由于我第一次提交任务之前忘记给予kojibuilder1 createrepo权限了,所以我手动把任务1和任务2取消并重新创建。

如图所示,现在kojihub已经自动安排我们的kojibuilder1也就是本机上的kojid进行工作了,因为此时Load负载不为0,并且这个任务本身不难,所以没有把4.0的总负载给占满。

运行一段时间之后,regen-repo成功,我建议的话是这个regen-repo操作就让有权限访问/mnt/koji(这个可以由你来设置)的机器来完成就好。因为它涉及到一个文件系统的访问,如果让其他设备上的kojid来运行可能会没有足够的访问权限、导致regen-repo失败。也就是说regen这些操作由“本机”来做,让对这个目录有读写权限的那台机器来做,给予那台机器对应的kojibuilder这个createrepo权限,这样是最稳妥的。



二、开始构建第一个rpm包

1、设置allowed_scms参数

这是kojid配置文件里面的一个重要参数,koji在构建的时候需要从远程下载源代码,但是不是所有的url都是可信的,所以我们需要设置一个scm白名单,告诉koji我这个url里面的源代码是安全的。

如果不设置的话会报出这个错误。

sudo vim /etc/kojid/kojid.conf
allowed_scms = src.fedoraproject.org:/rpms/*

把allowed_scms取消注释,并写入如上代码,信任fedoraproject的源代码。

sudo systemctl restart kojid

SCM,全称Software Configuration Management,中文翻译为软件配置管理,用于控制和追踪软件的变化,其核心是版本控制和baseline的确立。简单理解就是那几个版本控制工具都和scm有关(git ,svn 等)。这里就是使用版本控制工具进行管理。

如果你不是直接给koji一个链接,而是给它本地指定了一个.src.rpm那就不用这个scm允许,因为在本地就默认是安全的了。我们就从最简单的.src.rpm开始构建,这样会比较容易。


2、下载rpm源码包并开始构建

这里我是构建从pkgs.org里下载的neofetch.src.rpm源码包,把它通过koji构建成rpm包。

neofetch页面icon-default.png?t=O83Ahttps://fedora.pkgs.org/40/fedora-x86_64/neofetch-7.1.0-12.fc40.noarch.rpm.html

wget https://dl.fedoraproject.org/pub/fedora/linux/releases/40/Everything/source/tree/Packages/n/neofetch-7.1.0-12.fc40.src.rpm 
koji build f40_x86_64_build_target neofetch-7.1.0-12.fc40.src.rpm


提交任务后在执行期间很有可能出现问题,其中Result是执行结果,Output里面是重要的日志。

构建成功后会在Output的地方出现*.rpm ,然后你点击就会下载它,它的实际位置是在/mnt/koji/packages/ 这个目录里。

并且在kojiweb的Builds界面出现了第一个包,这就是我们构建出来的第一个rpm包!


三、RISC-V架构的rpm包构建

我们在构建x86_64架构的rpm包的时候其实非常简单,在本机操作就好,因为本机本身就是x86_64架构的。而如果取构建其他指令集的rpm包的时候,是需要该架构的机器在运行并且打开了kojid与kojihub所在机器进行交互。那么这个RISC-V的机器可以是虚拟机也可以是实体机,我们最简单的就是在kojihub所在的机器上开启一个RISC-V架构的虚拟机,这样部署起来也会比较方便。还有一点我们必须明白:那就是我们现在一直在虚拟机里,哪怕弄坏了什么也完全不用急,一切都可以重来的。

1、准备阶段

1) 安装必要的软件包
sudo dnf install libvirt libvirt-client qemu qemu-img qemu-system-riscv gdisk

sudo systemctl enable --now libvirtd

我们需要在虚拟机里安装上述软件包,也就是要在虚拟机里开虚拟机,这样会降低一点效率,不过能实现才是目前最重要的事情。也就是从现在开始,你的虚拟硬盘的空间占用将会大大增加,所以之前我在创建Fedora虚拟机的时候推荐你最好给多一点空间(80GB左右)。

2) 下载镜像等文件

这一步大体和前面“跟我学RISC-V”中使用RISC-V虚拟机是一样的。你可以使用iscas做的专门用于RISC-V包构建的Fedora镜像,当然你也可以使用别的镜像,只是这个镜像允许你批量部署 -- 一台设备上批量开启多台Fedora risc-v虚拟机。并且这个虚拟机是使用virsh工具来开启/关闭/自启动等操作,并且使用xml文档来描述虚拟机硬件等信息。所以我们必须理解这个xml文档,并且还要根据自己的实际情况去改写它。

koji_builder仓库icon-default.png?t=O83Ahttps://openkoji-bj.isrc.ac.cn/pub/dl/riscv/qemu/koji_builder/

cd
mkdir riscv
cd riscv
wget https://openkoji-bj.isrc.ac.cn/pub/dl/riscv/qemu/koji_builder/fedora-riscv64-image-builder-latest.raw.xz
wget https://openkoji-bj.isrc.ac.cn/pub/dl/riscv/qemu/koji_builder/fw_dynamic.bin
wget https://openkoji-bj.isrc.ac.cn/pub/dl/riscv/qemu/koji_builder/riscv64_builder_template.xml
wget https://openkoji-bj.isrc.ac.cn/pub/dl/riscv/qemu/koji_builder/u-boot.bin


#下载后解压缩
xz -d fedora-riscv64-image-builder-latest.raw.xz

3) 把文件放置到合适的位置并创建数据盘
sudo cp fedora-riscv64-image-builder-latest.raw u-boot.bin fw_dynamic.bin /var/lib/libvirt/images/qemu_riscv64__001.data.raw

因为libvirt和virsh这一套会有这样的规定要放置在这个目录里,你的Fedora虚拟机的镜像也会放置在你的宿主机的相同目录里。

su -
cd /var/lib/libvirt/images

#创建raw格式磁盘
qemu-img create -f raw qemu_riscv64__001.data.raw 20G

#创建分区表
sgdisk --clear -g --new=1:4096:0 \
    --change-name=1:"kb_data" \
    --typecode=1:EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 \
    qemu_riscv64__001.data.raw
#加载nbd模块到内核
sudo modprobe nbd max_part=16

#把虚拟磁盘当成物理磁盘使用
qemu-nbd -f raw --connect /dev/nbd8 qemu_riscv64__001.data.raw

#格式化(当成实际的磁盘那样使用)
mkfs.ext4 /dev/nbd8p1

#文件系统检查
fsck -vf /dev/nbd8p1

#断开nbd
qemu-nbd --disconnect /dev/nbd8p1

exit

NBD 允许你将远程服务器上的存储设备当作本地磁盘来使用,尽管这个磁盘实际上位于网络另一端的远程计算机上。所以在这里用nbd有点大材小用了。

4) 修改xml文件并启动虚拟机
BUILDER_NAME_PREFIX=qemu_riscv64_
NUM=001
OPENSBI_PATH=/var/lib/libvirt/images/fw_dynamic.bin
UBOOT_PATH=/var/lib/libvirt/images/u-boot.bin
STORAGE_POOL=/var/lib/libvirt/images

cp riscv64_builder_template.xml  ${BUILDER_NAME_PREFIX}_${NUM}.xml


#对xml文档进行修改
sed -i \
-e "s|@@builder_name@@|${BUILDER_NAME_PREFIX}_${NUM}|g" \
-e "s|@@opensbi_bin@@|${OPENSBI_PATH}|g" \
-e "s|@@uboot_bin@@|${UBOOT_PATH}|g" \
-e "s|@@image_builder_OS@@|${STORAGE_POOL}/${BUILDER_NAME_PREFIX}_${NUM}.raw|g" \
-e "s|@@image_builder_data@@|${STORAGE_POOL}/${BUILDER_NAME_PREFIX}_${NUM}.data.raw|g" \
${BUILDER_NAME_PREFIX}_${NUM}.xml

你可能会对这个名字感觉很奇怪,为什么要把好好的xml文档名字改成qemu_riscv64__001.xml这个样子。其实很好理解,因为virsh启动的虚拟机是有名字的,使用名字来表示这个虚拟机的名字,你在对虚拟机进行操作的时候也都是要用到这个名字,所以我们要在名字里表明这台虚拟机的性质和作用。然后出现数字的意思是,这是第一台虚拟机,因为koji构建系统通常来说不会只有一个builder,正式的环境里可能有几十几百个builder,所以我们需要对虚拟机进行一个编号。总之,给xml改名的理由就是为了好区分。

然后,我们需要打开这个xml文档并进行修改:

vim qemu_riscv64__001.xml

由于我在创建Fedora虚拟机的时候总共才分配了12GB内存,所以这里的16GB是根本无法分配的,我们应该写的小一点。比如我设置成4GB就写4194304就好。

5) 启动虚拟机

一切准备就绪之后我们就可以开启虚拟机了,就使用virsh命令就好。

cd ~/riscv
sudo virsh define qemu_riscv64__001.xml


# 定义一个域
virsh define ***.xml

# 取消定义一个域
virsh undefine ***

# 如果你修改了xml配置文件想重新起一个虚拟机,就要先取消定义然后再重新定义

至此,我们的第一台RISC-V虚拟机builder就创建好了,接下来就可以启动了。这一步是在定义

sudo virsh console qemu_riscv64__001.xml

注意:virsh命令中对系统文件有修改操作的,是需要root权限的如果你不加sudo,会导致无法获得域。

经过一段时间的探索,我们终于在Fedora虚拟机里启动了Fedora risc-v虚拟机。

账号:root

密码:riscv

这个fedora-riscv镜像是定制的,它的作者并不打算对系统中的rpm包进行升级,所以根目录只有一2.8GB空间。其中的/dev/vdb就是我们自己创建的20GB磁盘,我这里写20GB,实际上你多写一点也没事。它会自动挂在并把挂载点给设置好,大家无需担心。

# 查看已启动的域
➜  ~ sudo virsh list
[sudo] april_zhao 的密码:
 Id   名称   状态
-------------------


# 查看所有域(虚拟机)
➜  ~ sudo virsh list --all
 Id   名称                状态
--------------------------------
 -    qemu_riscv64__001   关闭

等到你把fedora risc-v给配置好之后,也就是当你打开了kojid并且成功和kojihub通信之后,你就可以把qemu_riscv64__001这个虚拟机设置为开机自启动,这样你就不用每次开机都start一次。

# 设置为开机自启动
sudo virsh autostart qemu_riscv64__001


# 取消开机自启动
sudo virsh autostart --disable qemu_riscv64_001

如果设置为开机自启动,那么每次你开关虚拟机的时间会大大增加,因为在开关的时候还要顺便把fedora risc-v也给开关,对内存和CPU的占用也会增加。

用命令行来管理其实也挺方便的,不过你要是觉得这样还是很麻烦,你甚至可以在fedora里安装virt-manager,然后使用图形界面来管理fedora risc-v.

就和你在宿主机使用virt-manager来管理fedora一样。


2、配置fedora risc-v

由于这个镜像是专门为构建而准备的,所以它是自带了koji和mock这些工具,不需要你自己安装了。但是我们也能看到这些包的版本是非常老旧的,无法直接使用,需要更新。但是这个镜像偏偏体积并不大,也就是说你根本没有足够的磁盘容量用于rpm包的更新。所以我在这里要进行一下扩容。

poweroff

先把fedora-riscv给关掉,然后在fedora里执行一下命令。

su -
cd /var/lib/libvirt/images
qemu-img resize -f raw qemu_riscv64__001.raw 30G
exit

我在这里设定为30GB,应该是够用了。

然后重新进入fedora-riscv

sudo virsh list --all
sudo virsh start qemu_riscv64__001
sudo virsh console qemu_riscv64__001
parted /dev/vda
resizepart 2 100%
quit
partprobe
resize2fs /dev/vda2
partprobe

把多出来的空间全部分配/dev/vda2

现在的占用仅仅只有6%,可以说是非常充足了。

它自带一个fedora38的源但这并不适合我们,我们的fedora用的是40版本,那么在fedora-riscv里也需要40版本,只有版本对上,kojid访问kojihub的时候才不会出现版本不一致导致的问题。koji不同版本间差异挺大的,很容易出现接口不匹配的问题。

不过问题不大,我们只要换源即可。

cd /etc/yum.repo.d
mv fedora-riscv-koji.repo backup
vi fedora40-riscv-koji.repo
[fedora40-riscv-koji]
name=Fedora40 RISC-V Koji
baseurl=https://openkoji-bj.isrc.ac.cn/kojifiles/repos-dist/f40/latest/riscv64/
enabled=1
gpgcheck=0

vi fedora-riscv-koji.repo
[fedora-riscv-koji]
name=Fedora RISC-V Koji
baseurl=http://fedora.riscv.rocks/repos/f40-build/latest/riscv64/
enabled=1
gpgcheck=0

写入如上源信息,注意这两个源缺一不可,否则会出现缺包问题。然后

rpm --rebuilddb
dnf clean all
dnf update -y

注意依赖问题:

在更新的这个过程中很容易受到一些软件包的阻拦,比如这里的grubby-deprecated这个软件包会出现依赖问题阻断更新,把它remove掉就好。把这个包移除掉就好了,继续更新。整个更新过程会持续比较长的一段时间,因为我们虚拟机里开fedora-riscv虚拟机效率并不高,性能相对较弱,如果你的宿主机本身性能不是很强的话。

所有的rpm包更新好了之后再重启,然后我们查看koji和mock的版本。

mock版本要低一级,不过koji的版本是都对上了。

dnf install vim

整个环境都更新好了之后可以安装一些你常用的软件包,在测试环境里不用这么节省空间。


3、新建host

这里创建host和前面创建x86_64的host是类似的,只不过这里我们要把kojibuilder2设置为riscv64架构。

koji add-host kojibuilder2 riscv64

以后我们的这台fedora-riscv就作为kojibuilder2了。


4、生成并传递证书

我们要使fedora-riscv和fedora进行交互,需要打开kojid ,但是kojid是需要携带证书才能正常运行的,否则就会无权限访问kojihub.

大家还记得怎么颁发用户证书吧。我们每多一个要访问kojihub的用户就要创建这么一个证书。然后把这个证书放到fedora-riscv虚拟机的kojid对应位置。我们使用scp命令把文件从fedora传递到fedora-riscv.

传递前要在fedora-riscv里把允许ssh访问以root权限打开

vim /etc/ssh/sshd_config

systemctl restart sshd

重启ssh服务。

首先查看fedora-riscv的IP地址

scp /etc/pki/koji/kojibuilder2.pem root@192.168.124.213:/etc/kojid/client.crt
scp /etc/pki/koji/koji_ca_cert.crt root@192.168.124.213:/etc/kojid/serverca.crt
scp /etc/pki/koji/koji_ca_cert.crt root@192.168.124.213:/etc/pki/ca-trust/source/anchors/serverca.crt

然后传递.

再在fedora-riscv中执行

update-ca-trust

提到IP地址,我们必须在fedora risc-v里也做一个映射,让fedora risc-v能够访问到kojihub.

vim /etc/hosts
192.168.122.59 koji.april.com

上面的ip地址是fedora的IP地址,在第一篇文章里我们也修改过hosts文件,可以看成了本地的DNS。这样,fedora risc-v就能够通过url知道要去哪个ip地址访问了。同样地,如果你的kojibuilder不是虚拟机而是实体机(比如你有100块高性能开发板),那么也是要让你的开发板能够通过url访问到kojihub那台机器的实际IP地址,就是说这个映射是非常重要的。只要能够访问得到,那么kojid会自动和kojihub进行通信,并且文件传递(源码包从kojihub机器传递到builder机器,rpm包从builder机器传递到kojihub机器)都是由kojid来完成,不需要软件构建者多做什么额外的工作了。


5、配置并打开kojid

vim /etc/kojid/kojid.conf

[kojid]
; The number of seconds to sleep between tasks
; sleeptime=15

; The maximum number of jobs that kojid will handle at a time
maxjobs=10

; Time after successfully finished task's buildroot is deleted (2 minutes in seconds)
; Some logs and directories are left in place until buildroot_final_cleanup_delay
; buildroot_basic_cleanup_delay=120


; Time after successfully finished task's buildroot is deleted completely (1 day in seconds)
; buildroot_final_cleanup_delay=86400

; The minimum amount of free space (in MBs) required for each build root
minspace=8000

; The directory root where work data can be found from the koji hub
topdir=/mnt/koji

; The directory root for temporary storage
workdir=/mnt/storage/koji

; The temporary directory in buildroot
chroot_tmpdir = /chroot_tmpdir

; The directory root for mock
mockdir=/var/lib/mock

; The user to run as when doing builds
mockuser=root

; The vendor to use in rpm headers
; vendor=Koji

; The packager to use in rpm headers
; packager=Koji

; The distribution to use in rpm headers
; distribution=Koji

; The _host string to use in mock
; mockhost=koji-linux-gnu

; Timeout for build duration (24 hours)
rpmbuild_timeout=86400

; Install timeout(seconds) for image build
; Default value is 0, which means using the number in /etc/oz/oz.cfg,
; supported since oz-0.16.0
; oz_install_timeout=7200

; The URL for the xmlrpc server
server=https://koji.april.com/kojihub

; The URL for the file access
topurl=https://koji.april.com/kojifiles

; use createrepo_c rather than createrepo
; use_createrepo_c=True

; for faster repo regeneration reuse last repodata for given repo
; createrepo_update=True

; for createrepo tasks believe that rpms were not changed and
; we don't even need to stat them again. Turn off if some rewrites are expected.
; createrepo_skip_stat=True

; same as createrepo_skip_stat but for distrepo tasks. Here is the expectation
; different as distrepo can be run with different signing keys. So, tasks can refer
; to different binary versions of rpms. Turn on if you're sure that the task will
; be always run in same way. Not recommended
; distrepo_skip_stat=False

; copy old repodata if there is no apparent change
; copy_old_repodata = False

; A space-separated list of tuples from which kojid is allowed to checkout.
; The format of those tuples is:
;
;     host:repository[:use_common[:source_cmd]]
;
; Incorrectly-formatted tuples will be ignored.
;
; If use_common is not present, kojid will attempt to checkout a common/
; directory from the repository.  If use_common is set to no, off, false, or 0,
; it will not attempt to checkout a common/ directory.
;
; source_cmd is a shell command (args separated with commas instead of spaces)
; to run before building the srpm. It is generally used to retrieve source
; files from a remote location.  If no source_cmd is specified, "make sources"
; is run by default.
allowed_scms=scm.example.com:/cvs/example git.example.org:/example svn.example.org:/users/*:no

; If use the option allowed_scms above for allowing / denying SCM, default: true
; allowed_scms_use_config = true

; If use hub policy build_from_scm for allowing / denying SCM, default: false
; notice that if both options are enabled, both assertions will be applied, and user_common and
; source_cmd will be overridden by the policy's result.
; allowed_scms_use_policy = false

; A directory to bind mount into Source RPM creation so that some
; credentials can be supplied when required to fetch sources, e.g.
; when the place the sources are fetched from requires all accesses to
; be authenticated in order to satisfy auditing requirements.
;
; The directory specified here will turn up in the SRPMfromSCM chroot
; as /credentials. It is up to whatever implements "make_source_cmd"
; to make appropriate use of any credentials supplied.
;
; Be aware that this means "make_source_cmd" has access to these
; credentials and could steal them; any credentials supplied
; should be easily disabled, and not used for other purposes.
; scm_credentials_dir = /etc/kojid/scmcredentials

; The mail host to use for sending email notifications
smtphost=koji.april.com

; SMTP user and pass (uncomment and fill in if your smtp server requires authentication)
;smtp_user=user@example.com
;smtp_pass=CHANGEME

; The From address used when sending email notifications
from_addr=april <april@qq.com>

;configuration for Kerberos authentication

;the format of the principal used by the build hosts
;%s will be replaced by the FQDN of the host
;host_principal_format = compile/%s@EXAMPLE.COM

;location of the keytab
;keytab = /etc/kojid/kojid.keytab

;configuration for SSL authentication

;client certificate
cert = /etc/kojid/client.crt

;certificate of the CA that issued the HTTP server certificate
serverca = /etc/kojid/serverca.crt

;if set to True, failing subtask will not automatically cancel other siblings
;build_arch_can_fail = False

;if set to True, tag extra 'mock.bootstrap_image' can be used
;mock_bootstrap_image = False

;image build with raw-xz type will use following xz options
;xz_options=-z6T0

;if set to True additional logs with timestamps will get created and uploaded
;to hub. It could be useful for debugging purposes, but creates twice as many
;log files
;log_timestamps = False

;enabled plugins, base koji installation has access to runroot and save_failed_tree
;none of these is enabled by default
;plugin = 

;path where builder plugins are located, there could be multiple paths delimited by :
;pluginpath = /usr/lib/koji-builder-plugins

;allow passing noverifyssl option to anaconda for image builds
;allow_noverifyssl = False

;allow password in SCM url
;allow_password_in_scm_url = False

其中的minspace是你每次执行构建时的最小空间,它的大小是不能够超越/var/lib/mock/目录所能容纳空间的大小,也就是minspace必须小于前面我们设置的20GB数据盘的大小,当然数据盘你可以做得大一些都无所谓。

systemctl enable --now kojid

# 在fedora上执行
sudo systemctl restart firewalld

# 如果还不行那就关掉防火墙
sudo systemctl stop firewalld

这里要特别注意:fedora-riscv上的kojid守护进程需要和fedora进行通信,我们需要关闭或者重启防火墙,否则的话二者是无法通信的。

sudo systemctl restart kojid

注意防火墙关闭之后必须在fedora risc-v里重启kojid守护进程,让它和fedora kojihub重新建立通信。这个通信机制也很值得研究!

打开kojid守护进程之后,我们回到fedora的kojiweb页面

ID为2就是我们刚才创建的kojibuilder2 host ,现在它的Ready?状态也变成了✅。由于你把fedora risc-v以及kojid都设置为开机自启动,所以你每次打开fedora虚拟机并访问kojiweb的时候,过一段时间这里的kojibuilder2的Ready才能打开,因为fedora risc-v开机本身就需要一段时间。不过,一旦部署到了生产环境,kojihub会跑在服务器上,大家知道服务器是不会轻易重启(关机)的,所以也不用在意这一点延迟的时间。

大家可以高兴一下了,接下来我们就进入RISC-V的rpm包构建的环节!


6、构建前准备

由于这一步的x86_64的步骤已经在前面演示过了,所以在这里我就不多赘述,把这个过程给展示一下。大家要是看不懂某一步就去前面找。

我们现在回到fedora里使用koji命令如法炮制创建tag和target,只不过这一次是RISC-V架构的,我这次构建rv的包就以F41为例了。由于我们要构建F41的包,所以我们需要用到F41的package列表和comps文件,但是我们之前只获取了F40的。一旦kojihub打开,那么你再使用那几个命令就访问不到fedoraproject的kojihub了,所以我这里演示一下怎么在kojihub打开了也获取。

你可以在你的实体机上安装docker,也可以在Fedora虚拟机上安装docker,安装好之后我们拉去fedora镜像,在这个docker容器的fedora里我们获取信息就好了。由于docker占用资源极少,所以你可以一开始就开一个docker container来专门用来获取信息。

docker pull fedora:latest
docker run -it fedora

这样很快就进入了一个新的fedora环境,我们需要先安装几个基础包。

dnf install postgresql-server mod_ssl httpd koji-hub koji-web koji-utils ncurses iproute openssh-clients

koji list-tagged --latest --rpms --arch src f41 > f41_src_list.txt
cat f41_src_list.txt | sed "s/-[^-]*-[^-]*.src$//g" > f41_pkg_list.txt
koji show-groups --comps f41-build > comps_f41_koji.xml

获取到这些信息后,再使用scp命令传递进kojihub所在的fedora里就好,或者干脆就在kojihub的fedora里开这个docker container。


koji add-tag f41_riscv64
cat f41_pkg_list.txt | xargs -n 2048 koji add-pkg --owner kojiadmin f41_riscv64
koji add-tag --parent f41_riscv64 --arches "riscv64" f41_riscv64_build
koji import-comps fedora-comps/comps-f41.xml f41_riscv64_build
koji import-comps comps_f41_koji.xml f41_riscv64_build
koji add-target f41_riscv64_build_target f41_riscv64_build f41_riscv64
koji add-external-repo -t f41_riscv64_build f41_riscv64-external-repo https://openkoji.iscas.ac.cn/kojifiles/repos/f41-build/latest/riscv64/
koji add-group f41_riscv64_build build
koji add-group f41_riscv64_build srpm-build
koji add-group f41_riscv64_build appliance-build
koji add-group-pkg f41_riscv64_build build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep
koji add-group-pkg f41_riscv64_build srpm-build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep
koji regen-repo f41_riscv64_build

代码看似比较多,其实都是前面内容合并起来了,基本上你只要修改那个架构信息,从x86_64改为riscv64即可。这里面有一个外挂仓库openkoji,这个就是iscas的risc-v仓库,你拿来用就好了。

由于regen-repo需要一段时间,大家可以去kojiweb里的tasks里查看这个任务完成了没有,如果已经完成,那么你就可以看第七节了。


7、构建 RISC-V架构的rpm包

一切准备就绪,我们马上就要做最后也是最重要的一步了,方法和前面一样,只不过架构做了一下改变。不知道大家是否好奇ARM架构的rpm包能否也这么去构建,大家就稍稍期待一下吧。

wget  https://dl.fedoraproject.org/pub/fedora/linux/releases/40/Everything/source/tree/Packages/m/make-4.4.1-6.fc40.src.rpm
koji build f41_riscv64_build_target make-4.4.1-6.fc40.src.rpm

这回我不去构建neofetch了,我构建了一下make.

最终构建出来了make的RISC-V64架构的rpm包,也是成功了。并且在这一过程中进行观察,发现fedora risc-v机器上确实长时间运行cc1进程,确实是努力地在构建。所以我这一次对koji的研究可以说是比较圆满完成啦。哈哈哈哈哈哈。

不过构建的过程时间是比较长的,我们现在毕竟是在虚拟机里的虚拟机里跑cc1,到时候可以试试拿高性能开发板来做这个构建,我还是会把成果给分享出来。

这也是在大量红色(报错)的基础上才总结出来的一个通用的经验,写成了这一篇比较简明的教程,大家且看且珍惜。


四、同时构建多架构rpm包

虽然我们现在已经具备了分别构建x86_64架构和riscv64架构的rpm包的能力,实际上aarch64架构的话你只要如法炮制就好,道理都是一样的。现在我们对于koji的使用已经有了一些经验,但是我们毕竟不能“闭门造车”,我们需要把当前已经得到的一些信息和官方的koji进行一个对比,这样才知道我们的koji到底差在了哪里。

1、标签问题

上图是fedoraproject的koji标签界面,我们可以看到fedora的标签可就多了去了,可能有几万个几十万个。我们查看一下它的命名规则,比如f38-openjdk ,f38-updates-testing.这个标签名里没有架构信息,而是专注与包或者源的本身。

我们再来看看iscas的openkoji里的标签名:

也是类似的,前面是发行版简称,后面是标签作用或源的名字。

但是我们之前的那几个标签是 发行版简称_指令集架构名,这样去标记。实际上这样并不好,因为一个标签并不是只能用来构建一个指令集的rpm包。

这个f39_build的标签可以用来构建这么多个架构呢,我们需要修改以前的一些思维。

也就是说标签名就不要带有架构信息了,我们专注于发行版和发行用途就好了。

2、target问题

和tag一样的思路,由tag创建出来的target同样不需要携带架构名这些信息。那么,好的思路、正确的做法我们应该学习起来,以前的那种比较“粗略”的做法(标签区别架构)大家可以摒弃了。

3、同时构建多架构rpm包

由此可见,一个标签用来构建某一个指令集的包是非常低效的,因为现在的指令集有很多,不需要每次都操作一遍。我们把架构信息放进同一个标签里,只要使用这个标签去构建一个包,那么所有架构的rpm包都会出现。现在我们来实践一下。

在开始之前,查看一下目前已经添加了哪些外部仓库:

刚好Fedora40有两个仓库,分别是x86_64和riscv64,所以我们就以F40为这个例子。

koji add-tag f40
cat f40_pkg_list.txt | xargs -n 2048 koji add-pkg --owner kojiadmin f40
koji add-tag --parent f40 --arches "x86_64" f40_build
koji import-comps fedora-comps/comps-f40.xml f40_build
koji import-comps comps_f40_koji.xml f40_build
koji add-target f40_build_target f40_build f40
koji add-external-repo -t f40_build base-external-repo
koji add-external-repo -t f40_build f40_rv64_build-external-repo
koji add-group f40_build build
koji add-group f40_build srpm-build
koji add-group f40_build appliance-build
koji add-group-pkg f40_build build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep

koji add-group-pkg f40_build srpm-build tar gcc-c++ redhat-rpm-config redhat-release \
     which xz sed make bzip2 gzip gcc coreutils unzip \
     shadow-utils diffutils cpio bash gawk rpm-build \
     info patch util-linux findutils grep
koji regen-repo f40_build

请注意这其中在添加外部仓库的时候,由于Fedora40 risc-v在上一次构建的时候已经添加了f40_rv64_external-repo这个仓库了,所以你这一次不需要再写这个url,而是直接把名字给写进来就好。

在设置构建标签的架构的时候,我暂时设置成了"x86_64",我们可以在kojiweb界面里再加上"riscv64"。

如图所示:

就像这样,然后你再使用koji build提交任务的时候,kojihub就是把任务分配给x86_64设备和riscv64设备,它们都会构建自己架构的rpm包。


五、总结

这个总结也许是本篇文章的结束,也许是搭建整个koji构建环境并做出自己的Linux发行版、发行自己的软件包的开始。我会再一次总结这几个部件之间的联系,这样能够更好地理解koji构建系统。

如图所示:这次我们主要看下半部分,因为上半部分上一篇文章已经分析了。kojihub仍然是整个koji构建系统的核心,这次它作为生产者不断产生任务,而任务由kojibuilder来解决,我们现在只有2个builder,实际上在正式的生产环境中应该有几十上百个hosts。也就是说每一个服务器都能开几十个虚拟机,每个虚拟机都打开kojid守护进程。这样你的hosts就会非常非常多。因为一个Linux发行版它要构建的包本身就很多,而有的激进的发行版则每天都要构建一个小版本,任务越重,越需要builders.

比如:

我们查看fedoraproject的hosts,从ID来看疑似有500多个host,虽然不是每一个都Ready.

这里需要注意一下:那就是host只能创建而不能删除,也就是说比如你创建了kojibuilder10,而kojibuilder10机器刚好坏掉了,那么你也没有办法删掉这个host,只能说设置把它设置成disabled,也就是不再使用。实际上哪怕机器坏掉了永远无法启动,你也可以拿另一台机器作为kojibuilder10,只要携带了kojibuilder10的证书。

iscas的openkoji也有不少的hosts.

学过操作系统理论的会知道,任务一多并且并发调度起来就会涉及到一个“负载均衡”的概念,就是说这个任务分配不是乱分配的,不会给一个本身就很忙碌的机器再分配任务,也不会让一个正在空闲的机器一直空闲下去。最好是“平均施力”,这样才好收益最大化

我会在后面的文章里阐述该任务是如何调度,如何把任务分配给host.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

April__Zhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值