理解warden(安装启动)

长平狐 发布于 2013/11/25 18:34
阅读 692
收藏 0

前面曾经写过一篇文章介绍在 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 中国大陆”许可协议授权。

联系作者:微博@李真宽


原文链接:http://blog.csdn.net/restkuan/article/details/10018885
加载中
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部