最近 TUNA 新增了一台跑着 RHEL7 的服务器,之前我们用的都是 Debian,虽然早年也接触过 CentOS,但是对 RH 系的生态系统还是不太熟练。这篇文章也算是 对头一次在 RHEL7 上折腾的一个备忘。

TUNA 长期使用 LXC 作为容器化技术,当然我们知道 docker 比较红,但是这台服务器的应用要求更接近「虚拟化」而非「应用容器」,所以我们仍然选择 LXC。

然而我们发现 RHEL 7 的 repo 中并没有 LXC,于是使用社区提供的 EPEL 来安装。

建立 /etc/yum.repos.d/epel.repo,内容为

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

之后

yum makecache  # 注意不要受apt-get影响用update
yum install lxc lxc-templates

即可。

如果事情就这么简单的话这篇文章就意义不大了。我们很快发现,lxc-ls 和之前见过的不太一样,首先不支持 lxc-ls --fancy 这种用法,其次 lxc 退出之后,lxc-ls --active 仍然会把原先的给列出来。这就很麻烦,管理员无法轻易得知到底哪些 LXC 正在运行,就容易犯错。

问了下狗哥发现这是因为 lxc 在 configure 的时候没有打开 --with-python 选项,所以只能使用一个比较残的 bash 写的 lxc-ls。进一步发现 lxc 1.0 需要使用 python3 binding,而 RHEL/CentOS 7 都是默认不带 python3 的(仓库里都没有),所以 epel 才会禁掉 python binding.

做为一个有洁的系统管理员,不能被包管理器管理的软件都是隐患,所以我不愿意使用 autotools 编译安装 lxc-1.0.8.tar.gz。优雅的方式应该是下载 lxc 的 SRPM 包修改之后打成 RPM 安装。

所以去 EPEL 下到 lxc-1.0.8-1.el7.src.rpm。这之后需要注意,如果使用 rpmbuild --rebuild lxc.src.rpm 的话,其实只是重新编译一遍,不会有修改SPEC的机会。 正确的方式是使用 rpm -i lxc.src.rpm,这里 CentOS 文档中写明需要使用普通用户权限,不能使用 root (我没有用root尝试,不知是硬性要求还是强烈建议)。 解开的 srpm 包的 SPEC 文件放在了 $HOME/rpmbuild/SPECS 中。这条命令实在很想吐槽,rpm -i 直观的理解应该是安装,为何是解 SRPM 包呢。

进入 SPEC 所在目录,rpmbuild -ba lxc.spec,提示缺少依赖关系,其中一部分是 yum 能直接装上的,有两个包 lua-devellibseccomp-devel RHEL中没有(可能是订阅不太对), 我找了两个 CentOS 的包打上了。

刚才我们提到,需要打开 --with-python,在 SPEC 中是由 %global with_python3 1 来控制的,我们把它打开。此外我们需要安装 python3-devel,但是 epel 中只能装上 python34-devel, 所以需要把 SPEC 中所有依赖 python3-devel 的地方改成 python34-devel

之后再 build 就能通过啦。打好的 rpm 包放在了 $HOME/rpmbuild/RPMS 中,过去 rpm -i 或者 yum install 都可以。这样我们就得到了一个完整功能的 lxc 1.0 啦。

再说下过程中遇到的另一个 RH 系的技巧,build lxc-doc 的时候被迫装上一堆 perl 模块,因为依赖关系太复杂,还不好 yum autoremove 掉。 yum 有个很好的事务特性,使用 yum history list <somepackage> 命令可以找到安装这个包的事务 ID,再运行一下 yum history undo <ID> 即可撤销事务。

参考文献: