在阅读本文之前,作者假设您先对warden的安装过程有所了解,最好已经在自己的机器上安装好了可以使用的warden。因此,建议先阅读http://kelby.writings.io/articles/21
一,3个概念rootfs container warden
warden安装后,会生成1个目录 /tmp/warden,在这下面又有3个子目录:cgroup containers rootfs
下面先来介绍第1个概念rootfs,也就是对应的/tmp/warden/rootfs
首先,从前文中我们知道 rootfs 的来源:
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 培养自己的势力
debootstrap
源代码: https://github.com/ccoss/debootstrap
基本用法:debootstrap 发行版代号 安装点 镜像
显示安装了哪些软件:
debootstrap --print-debs "lucid" . "http://archive.ubuntu.com/ubuntu/"
至此,我们得到一个与外界隔离(严格意义上来讲,没有绝对隔离)的操作系统。为方便理解,暂切把我们安装warden的本地操作系统称之为“宿主机”,而这个新生的操作系统称之为“基本文件系统”
rootfs大小:304M
bin boot dev etc home lib lib64 media mnt opt proc root sbin selinux srv sys tmp usr var
从它的产生过程,我们就大概知道它能起到一定的资源隔离的作用,在一定程度上还起到了安全作用。
但从以上所述,我们也不得不承认rootfs是需要占用大量时间和系统资源的。在我们的PaaS环境中,显然是不合理的。由此,我们引入另一个重要概念container
这就意味着……。
container的创建、删除所需要的时间,以及里面所包含的软件是很少的!
container大小:3.2M
换句话,我们可以很容易的创建、删除一个container,而且基本上用不了多少时间。
那么,container包含了什么?
container = src + skeleton + mini rootfs
- src 指的是warden源代码里的src部分。src编译后会得到几个可执行文件,其中的 iomux-link, iomux-spawn, wsh, wshd则成为container的一部分。
- skeleton 指的是warden源代码里的root/linux/skeleton部分。在我们‘create container’时,会原封不动的复制过来,成为container的又一部分。
- mini rootfs 这是我自己提出的概念,为了是与上文提到的rootfs区分开来,并且说明它们之间又有一定联系。
在每个container目录下,都会有一个mnt目录。它从上面我们提到的rootfs而来,根据我们使用的操作系统版本,执行:
lucid|natty|oneiric
mount -n -t aufs -o br:tmp/rootfs=rw:$rootfs_path=ro+wh none mnt
precise
mount -n -t overlayfs -o rw,upperdir=tmp/rootfs,lowerdir=$rootfs_path none mnt
而mini rootfs则是根据操作系统及其版本将读写部分(不包含只读)copy或者mount这个mnt中的 dev, etc, home, sbin, tmp ,成为container的另一部分。用大白话说就是container中的一部分软件从rootfs而来的。
mini rootfs大小:1.1M
dev etc home sbin var
48K ./var/log
52K ./var
960K ./sbin
52K ./etc
16K ./home/vcap
20K ./home
4.0K ./dev/pts
8.0K ./dev
接下来,我们来说说warden
先来看看,我们执行 bin/warden 进入与warden交互部分,有哪些可用命令:
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.
从上面加粗的部分,我们基本可以知道:warden就是这些container的管理控制器。通过它,我们可以增、删、查、改container的一些基本信息,还有复制文件进出、网络进出、限制container内存硬盘大小等。
题外话:这些交互命令中,一部分用于warden管理container,另一部分用于container本身的自管理。对于刚接触warden组件的人来说,很容易误导他们混淆warden,container之间的概念。
二,container-资源隔离与限制
首先,来说说container是如何创建的。这是一个复杂的过程,说得不好,大家不要见怪。
我们在交互的命令提示行里输入:
warden> create
handle : 17527e1o5nv
1. 复制skeleton目录(包含了编译后的src。上文提到过container的构成)
/tmp/warden/containers/17527e1o5nv$ ls
bin destroy.sh etc jobs lib mnt net_rate.sh net.sh run setup.sh snapshot.json start.sh stop.sh tmp
2. 执行自管理命令setup.sh
包含了:
- container及warden相关网络的设置
$ ifconfig
w-17527e1o5nv-0 Link encap:Ethernet HWaddr 4a:69:e5:90:4d:7c
inet addr:10.254.0.157 Bcast:10.254.0.159 Mask:255.255.255.252
inet6 addr: fe80::4869:e5ff:fe90:4d7c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:328 (328.0 B) TX bytes:238 (238.0 B)
- mini rootfs的生成(上文提到过container的构成)
/tmp/warden/containers/17527e1o5nv$ ls tmp/rootfs/
dev etc home sbin var
- 一些零散的文件权限设置
- 默认vcap用户的创建
useradd -mU -u 10000 -s /bin/bash vcap
上面提到container有一个mini rootfs,那么我们可以通过chroot切换进mini rootfs,并且执行一些操作包括创建用户。默认的container会创建一个vcap用户供我们使用,我们执行 bin/warden 进入与warden交互部分,在里面执行的:run, spawn, stream等命令都是以vcap用户的身份来运行的。
3. 以hook(钩子)的形式完成其它一些操作
包括但不限于:
- wshd文件的创建(前文提到过,判断container的死活它起到很大的作用。除此之外,它还有很大作用,详情请看源代码……。)
- cgroup相关部分的创建
warden有用到cgroup来做资源限制,但出乎我们意料的是:使用得很少!
创建container时默认使用:
# Add new group for every subsystem
for system_path in /tmp/warden/cgroup/*
do
instance_path=$system_path/instance-$id
mkdir -p $instance_path
if [ $(basename $system_path) == "cpuset" ]
then
cat $system_path/cpuset.cpus > $instance_path/cpuset.cpus
cat $system_path/cpuset.mems > $instance_path/cpuset.mems
fi
if [ $(basename $system_path) == "devices" ]
then
# disallow everything, allow explicitly
echo a > $instance_path/devices.deny
# /dev/null
echo "c 1:3 rw" > $instance_path/devices.allow
# /dev/zero
echo "c 1:5 rw" > $instance_path/devices.allow
# /dev/random
echo "c 1:8 rw" > $instance_path/devices.allow
# /dev/urandom
echo "c 1:9 rw" > $instance_path/devices.allow
# /dev/tty
echo "c 5:0 rw" > $instance_path/devices.allow
# /dev/ptmx
echo "c 5:2 rw" > $instance_path/devices.allow
# /dev/pts/*
echo "c 136:* rw" > $instance_path/devices.allow
fi
echo $PID > $instance_path/tasks
done
也就是大小默认都是从cgroup目录树的根继承而来的。在后面我们可以通过limit_memory等命令来管理,但可管理项也很少。
三, 小结
PaaS中资源的限制与隔离是一个很大的话题,容器技术由于对资源的利用率高,创建、删除方便快速,管理容易等特点,在PaaS中起到很大的作用。
还是用warden来做例子吧。
通过前面提到的unshare, debootstrap, chroot等命令我们得到了一个相对隔离的环境,起到了一定的安全作用。
然后又在此基础上使用:setquota, iptables, tc, cgroup等限制硬盘、网络、流量、cpu、内存等资源。
…………
……。
。
预告:
warden里执行copy_in、copy_out,net_in、net_out,run等命令,大概是什么意思?
warden的整体架构,及源代码阅读建议。
下一篇文章讲解。
本文采用知识共享“署名 3.0 中国大陆”许可协议授权。
联系作者:微博@李真宽