在UFS文件系统上构建Thin Jail
我因为 ZFS 非常方便管理和使用,所以大多数FreeBSD和Linux部署时都会采用ZFS作为数据存储文件系统。在 FreeBSD Thin(薄) Jail 甚至 VNET + Thin Jail 也采用ZFS来实践构建。
不过,也有一些环境采用了传统的UFS文件系统,例如,我在阿里云租用的VM,阿里云默认提供的FreeBSD镜像就是采用UFS文件系统。我需要为 FreeBSD系统更新 构建一个反向代理缓存服务器,考虑在租用的VM中构建一个隔离的Thin Jail来运行 Nginx反向代理 。这里记录准备工作,构建一个UFS上的Thin Jail。
主机激活 jail
执行以下命令配置在系统启动时启动
Jail
:
# 配置在系统启动时激活Jail功能
sysrc jail_enable="YES"
# 配置所有jails在后台启动
sysrc jail_parallel_start="YES"
Jail目录树
准备环境变量(方便后续操作);
export jail_dir="data/jails"
export bsd_ver="14.3"
# 在FreeBSD中root用户的shell默认是sh,所以调整 ~/.shrc
echo 'jail_dir="data/jails"' >> ~/.shrc
echo 'bsd_ver="14.3"' >> ~/.shrc
创建RELEASE-base模版目录:
mkdir -p $jail_dir/templates/$bsd_ver-RELEASE-base
和 FreeBSD Thick(厚) Jail 一样下载用户空间:
fetch https://download.freebsd.org/ftp/releases/amd64/amd64/$bsd_ver-RELEASE/base.txz -o /$jail_dir/media/$bsd_ver-RELEASE-base.txz
将下载内容解压缩到模版目录:
tar -xf /$jail_dir/media/$bsd_ver-RELEASE-base.txz -C /$jail_dir/templates/$bsd_ver-RELEASE-base --unlink
将时区和DNS配置复制到模板目录:
cp /etc/resolv.conf /$jail_dir/templates/$bsd_ver-RELEASE-base/etc/resolv.conf
cp /etc/localtime /$jail_dir/templates/$bsd_ver-RELEASE-base/etc/localtime
更新模板补丁:
freebsd-update -b /$jail_dir/templates/$bsd_ver-RELEASE-base/ fetch install
创建一个
skeleton
(骨骼),这里是UFS,所以直接创建目录
skeleton
(骨骼)mkdir /$jail_dir/templates/$bsd_ver-RELEASE-skeleton
执行以下命令,将特定目录移入
skeleton
数据集,并构建base
和skeleton
必要目录的软连接关系
skeleton
数据集mkdir -p /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/home
mkdir -p /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/usr
# 我单独创建一个docs目录用于后续将host主机的docs映射到jail中
mkdir -p /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/docs
# etc目录包含发行版提供的配置文件
mv /$jail_dir/templates/$bsd_ver-RELEASE-base/etc /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/etc
# local目录是空的
mv /$jail_dir/templates/$bsd_ver-RELEASE-base/usr/local /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/usr/local
# tmp 目录是空的
mv /$jail_dir/templates/$bsd_ver-RELEASE-base/tmp /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/tmp
# var 目录有很多预存目录,但是直接mv移动时有报错显示 var/empty 目录没有权限,这会导致目标目录破坏,所以改为rsync同步
rsync -avz /$jail_dir/templates/$bsd_ver-RELEASE-base/var /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/var
mv /$jail_dir/templates/$bsd_ver-RELEASE-base/var /$jail_dir/templates/$bsd_ver-RELEASE-base/var.bak
# root 目录是管理员目录,有基本profile文件
mv /$jail_dir/templates/$bsd_ver-RELEASE-base/root /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/root
执行以下命令创建软连接:
cd /$jail_dir/templates/$bsd_ver-RELEASE-base/
mkdir skeleton
ln -s skeleton/etc etc
ln -s skeleton/home home
ln -s skeleton/root root
ln -s ../skeleton/usr/local usr/local
ln -s skeleton/tmp tmp
ln -s skeleton/var var
# 这里增加一个docs目录用于存放数据(从Host主机映射到jail中)
ln -s skeleton/docs docs
在host上执行 修复
/etc/ssl/certs
目录下证书文件软链接
#cd /$jail_dir/templates/$bsd_ver-RELEASE-base/etc/ssl/certs
cd /$jail_dir/templates/$bsd_ver-RELEASE-skeleton/etc/ssl/certs
# 先保存一份原始列表记录
ls -lh > /tmp/fix_link.txt
# 生成unlink命令
ls | sed "s@^@unlink @" > /tmp/unlink.sh
# 生成fix命令
# 这里不能使用绝对路径链接,否则会报错 link: ffdd40f9.0: Cross-device link
# ls -lh | awk '{print $NF, $(NF-2)}' | cut -c 9- | tail -n +2 | sed "s@^@link @" > /tmp/fix_link.sh
ls -lh | awk '{print $NF, $(NF-2)}' | tail -n +2 | sed 's@^@ln -s ../@' > /tmp/fix_link.sh
# 检查一下 /tmp/fix_link.sh 是否满足要求
# 没有问题在执行以下2条命令
sh /tmp/unlink.sh
sh /tmp/fix_link.sh
在
skeleton
就绪之后,需要将数据复制到 jail 目录(如果是UFS文件系统):
skeleton
数据复制到 jail 目录# 假设这里创建名为dev的jail
jail_name=web
cp -R /$jail_dir/templates/$bsd_ver-RELEASE-skeleton /$jail_dir/containers/$jail_name
创建一个
base
template的目录,这个目录是skeleton
挂载所使用的根目录
skeleton
挂载所使用的根目录# 创建 dev 所使用的nullfs模板目录,这个目录就是jail的根PATH
# 和常规Jail仅命名 ${name} 不同,采用 ${name}-nullfs-base
mkdir -p /$jail_dir/$jail_name-nullfs-base
配置jail
创建所有jail使用的公共配置部分
/etc/jail.conf
(这里使用共享网络模式):
/etc/jail.conf
# STARTUP/LOGGING
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.consolelog = "/var/log/jail_console_${name}.log";
# PERMISSIONS
allow.raw_sockets;
exec.clean;
mount.devfs;
allow.mount;
allow.mount.devfs;
enforce_statfs = 1;
# HOSTNAME/PATH - NullFS
host.hostname = "${name}";
path = "/data/jails/${name}-nullfs-base";
# NETWORK
ip4 = inherit;
interface = vtnet0;
# MOUNT
mount.fstab = "/data/jails/${name}-nullfs-base.fstab";
.include "/etc/jail.conf.d/*.conf";
/etc/jail.conf.d/web.conf
(主机名web
)独立配置部分(这里因为都是公用部分,所以实际上是一个只包含主机名的空配置):
/etc/jail.conf.d/web.conf
web {
}
数据目录(可选)
为了能够将Host主机上的数据目录映射到jail容器内部使用(方便在Host主机上统一管理和备份),执行以下命令:
web
的 /docs
目录mkdir -p /data/docs/web
目录挂载
注意,这里配置引用了一个针对nullfs的fstab配置(主机名
web
),所以还需要创建一个/data/jails/web-nullfs-base.fstab
:
/data/jails/web-nullfs-base.fstab
/data/jails/templates/14.3-RELEASE-base /data/jails/web-nullfs-base/ nullfs ro 0 0
/data/jails/containers/web /data/jails/web-nullfs-base/skeleton nullfs rw 0 0
/data/docs/web /data/jails/web-nullfs-base/skeleton/docs nullfs rw,noatime,nosuid,nocache 0 0
备注
这里将Host主机的 /data/docs/web
目录映射到jail web
中的 /docs
目录,方法和 在多个Jail间共享文件目录 一样
最后启动
web
:
web
service jail start web
通过 jexec web
进入jail
此时在jail web
中检查目录 df -h
显示如下:
web
中检查目录 df -h
Filesystem Size Used Avail Capacity Mounted on
/data/jails/templates/14.3-RELEASE-base 29G 23G 3.7G 86% /
/data/jails/containers/web 29G 23G 3.7G 86% /skeleton
/data/docs/web 29G 23G 3.7G 86% /skeleton/docs
devfs 1.0K 0B 1.0K 0% /dev
其中 /skeleton/docs
对应Host主机的数据目录 /data/docs/web
,就可以在Host主机操作容器数据,方便维护
设置Jail
web
在操作系统启动时启动,修改/etc/rc.conf
:
/etc/rc.conf
jail_enable="YES"
jail_parallel_start="YES"
jail_list="web"
jail_reverse_stop="YES"
备注
这里完成了阿里云FreeBSD虚拟机的 web
jail 运行,下一步来构建一个 Nginx反向代理 实现WEB服务器: