前面曾经写过一篇文章介绍在 ubuntu 10.04 上安装 warden,最近又在 ubuntu 12.04 上再次安装。
其实它们的安装过程都是一样的,本文与前文的区别主要在“本文将从源代码层面”告诉你:warden是如何一步步安装,运行,进行交互的。
一. 准备工作
根据官方文档 https://github.com/cloudfoundry/warden/blob/master/warden/doc/getting_started.ubuntu.md 先安装所用到的内核版本。
sudo apt-get install -y linux-image-generic-lts-backport-natty
如安装不了,可以尝试先在/etc/apt/sources.list添加源:
deb http://ubuntu.mirror.cambrium.nl/ubuntu/lucid-updates main
记住安装完成后,要重启一下。
然后再运行安装:
sudo apt-get install -y build-essential # 编译工具
sudo apt-get install -y debootstrap # 安装rootfs时会用到
sudo apt-get install -y quota # 配置container占用disk时会用到
根据需要,可能你还要安装:
sudo apt-get install -y linux-image # ubuntu 12.04请安装此软件
sudo apt-get install -y cgroup-bin # cgroup相关
第一步,到此结束。根据你所使用的操作系统,及其版本不同,使用过程中,可能有所出入,但一般问题不大。
二. 设置warden
按时文档,执行:
sudo bundle exec rake setup[config/linux.yml]
根据官方说明,这里主要是编译 src/ 成可执行文件,最后会成为container的一部分;还有就是会下载一个精简过的Linux操作系统(称之为rootfs)供container使用。
下面就帮你分解一下安装过程,并帮助你理解此条命令。(也许不像上面所说的这么简单)
这条命令实际执行的是 Rakefile 里的脚本。通常,我们不会一次就安装成功,了解一下安装步骤可以让我们少走很多弯路。再细一下
·第一部分
cd xxx && make all
编译 src/ 成可执行文件,src共编译得到7个可执行文件:
closefds #close file descriptor简称。释放文件描述符fd
iomux-link, iomux-spawn #涉及io时的一些锁机制
oom #out-of-memory简称。内存不足时,一种保护机制
repquota #报告disk使用情况。类似setquota,quotacheck等
wsh, wshd #container与外界连接手段,可判断container是否还活着
它们其中的一部分会被复制到 ubuntu 或者 insecure 的 bin/ 目录里,最终会成为container的一部分:
cp src/wsh/wshd root/linux/skeleton/bin
cp src/wsh/wsh root/linux/skeleton/bin
cp src/iomux/iomux-spawn root/linux/skeleton/bin
cp src/iomux/iomux-link root/linux/skeleton/bin
cp src/iomux/iomux-spawn root/insecure/skeleton/bin
cp src/iomux/iomux-link root/insecure/skeleton/bin
这里需要强调的是在编译之前,它会先 make clean all 也就是说“每次设置warden”都要删除原文件,重新编译一次,也是要花时间的(如有需要,可注释,不重新编译)。
·第二部分
第二部分主要做几件事
1. unshare - run program with some namespaces unshared from parent。有点类似clone(),fork()等
sudo -E unshare -m root/linux/rootfs/setup.sh "/tmp/warden/rootfs"
2. debootstrap - Bootstrap a basic Debian system
debootstrap –verbose –include "openssh-server,rsync" "lucid" "/tmp/warden/rootfs" "http://archive.ubuntu.com/ubuntu/"
3. chroot - run command or interactive shell with special root directory。根目录的切换工作
chroot "/tmp/warden/rootfs" env -i PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" /bin/bash
4. chroot 后 apt-get install xxx # 安装软件
用我的话说呐,就是:
- unshare 脱离父子(组织)关系-资源隔离
- debootstrap 白手起家,另起炉灶
- chroot 和 apt-get install 培养自己的势力
到此为止,我们就得到了一个与外界隔离(严格意义上来讲,没有绝对隔离)的操作系统(rootfs)。
一般的,新生成的操作系统在 /tmp/warden/rootfs 通常上面的 chroot 命令可切换进去。
这里需要啰嗦的是 unshare, chroot 以及之后的 apt-get install 我们都容易理解。需要拿出来说的是 debootstrap,它源代码是 https://github.com/ccoss/debootstrap
warden 主要使用到了里面的 scripts/gutsy 使用 debootstrap 最简单的使用方式就是:
debootstrap 发行版代号 安装点 镜像
此外,可以添加一些options来达到我们想要的目的。比如,我们想知道在warden项目中主要安装了哪些软件,可运行:
debootstrap --print-debs "lucid“ . "http://archive.ubuntu.com/ubuntu/"
实际安装过程中,调用的是重要的文件,便是 root/linux/rootfs/ubuntu.sh
由于种种原因,通常我们不会一次就能成功安装warden,但每一次运行“设置warden”都会把我们的 /tmp/warden/ 目录给干掉。
也就是说,从头开始。这做法显然不太合适(在国内,你懂的)。
根据国内的网络环境,及网速。我建议:把 ubuntu.sh 里的
mkdir -p $target/$(dirname $1)
apt-get update
apt-get upgrade -y
有条件的注释或改换掉,因为这个过程容易导致安装失败。从头开始很花费时间。
上面我们新生成的操作系统(理解成虚拟机,那么本地的操作环境就是宿主机)是精简过的,所以有些软件我们可能没有。但又要使用,怎么办?两种方法
1. 用上面提到的 chroot 切换到虚拟机上 apt-get install xxx # 建议先更改一下 /etc/apt/sources.list 里的源
2. 我们可以在本地操作环境(宿主机)上下载软件源代码,然后复制到 /tmp/warden/rootfs 然后用上面提到的 chroot 切换到虚拟机上再编译安装
三. 启动warden
执行:
sudo bundle exec rake warden:start[config/linux.yml]
同样的,其入口也是上面提过的 Rakefile,在里面我们可以看到大致分为:
Warden::Server.setup(config || {})
Warden::Server.run!
我们简单了解一下:
1. Warden::Server.setup(config || {})
setup_server # 还未实现
setup_logging # Steno 记录日志
setup_network # container 的 ip 及其子网掩码相关;Pool::Network -> Warden::Network::Address & Warden::Network::Netmask)
setup_port #(Pool::Port) container 的 port 相关
setup_user #(Pool::Uid)# container 的 uid 相关
最终它们都会涉及到 Warden::Container::Linux
2. Warden::Server.run! # 基于 EM 的机制
这里主要完成了几件事:
- 调用 root/linux/setup.sh
root/linux/setup.sh
{
:env => {
"POOL_NETWORK" => config.network["pool_network"],
"ALLOW_NETWORKS" => allow_networks.join(" "),
"DENY_NETWORKS" => deny_networks.join(" "),
"CONTAINER_ROOTFS_PATH" => container_rootfs_path,
"CONTAINER_DEPOT_PATH" => container_depot_path,
"CONTAINER_DEPOT_MOUNT_POINT_PATH" => container_depot_mount_point_path,
"DISK_QUOTA_ENABLED" => disk_quota_enabled.to_s,
},
:timeout => nil
}
- 挂载cpu, memory部分(cgroup目录树的根):
/tmp/warden/cgroup (也被称为cgroup_path)的生成
# Mount cgroup subsystems individually
for subsystem in cpu cpuacct devices memory
do
mkdir -p $cgroup_path/$subsystem
if ! grep -q "${cgroup_path}/$subsystem " /proc/mounts
then
mount -t cgroup -o $subsystem none $cgroup_path/$subsystem
fi
done
注意:cgroup资源限制以目录树的形式来管理。这里创建的/tmp/warden/cgroup相当于根目录,以后我们 create 出来的container资源限制这部分会在它之下。
- 设置container的网络部分:
./net.sh setup
- 设置container的disk部分:
quotaon“/tmp/warden/containers”
上面这部分,使用到的命令基本上都在 root/linux/setup.sh 里,而且由于各种原因容易报错,特别是到quotaon这里。因此建议,适当的在里面加上一些断点,以便报错时清楚运行到哪了
- 把不符合要求的 container 清除掉
recover_containers(必需在上一步之后)
既然是“启动warden”,自然的就包括了之前已经启动过了,由于某种原因而停止的情况。所以,里面可能已经存在container了。一般来说不符合条件的container有两种:1.没有快照信息,也就是snapshot.json记录文件;2.‘死’了的,比如:超过了设置的glance_time还没有连接或没有run/wshd.sock
涉及 container_grace_time 配置;snapshot.json, run/wshd.sock 文件等。
四. 与 warden 交互
大家知道可以把 warden 做为一个服务,我们可以通过命令行接口,与它交互。
在另一终端窗口,执行:
bundle exec bin/warden
输入 help 查看帮助信息:
warden> help
copy_in Copy files/directories into the container.
copy_out Copy files/directories out of the container.
create Create a container, optionally pass options.
destroy Shutdown a container.
echo Echo a message.
info Show metadata for a container.
limit_disk set or get the disk limit for the container.
limit_memory Set or get the memory limit for the container.
link Do blocking read on results from a job.
list List containers.
net_in Forward port on external interface to container.
net_out Allow traffic from the container to address.
ping Ping warden.
run Short hand for spawn(stream(cmd)) i.e. spawns a command, streams the result.
spawn Spawns a command inside a container and returns the job id.
stop Stop all processes inside a container.
stream Do blocking stream on results from a job.
help Show help.
题外话:你也可以使用https://github.com/silas/vagrant-warden简化warden安装,轻松体验warden。
本文采用知识共享“署名 3.0 中国大陆”许可协议授权。
联系作者:微博@李真宽