DMTCP 分布式多线程检查点工具

高性能计算/分布式计算等大量计算需要程序运行几天、几周甚至几个月,如果期间因为电力或者不可避免的问题导致程序中断会浪费大量的时间和人力,还有超级计算机在这段时间里运行的电力成本。我们没有遇到过电力问题,不过我们最近遇到的场景是实验室需要做强制安全检查,要求关闭所有电脑,所以我们需要一种工具能设置断点暂停程序、把状态保存到硬盘、再按照要求恢复,就像程序员用 IDE 调试程序一样,设置断点、单步跟踪(或恢复运行)。

在多主机、多线程的复杂分布式计算环境,给程序设置断点不是一件容易的事情,因为程序的某部分可能在其他主机上运行。DMTCP: Distributed MultiThreaded CheckPointing 是我们目前正在考察的一个工具之一,我们喜欢它的一个原因是它不需要修改 Linux 内核,不依赖内核和内核模块。

安装

先安装一些编译 DMTCP 需要用到的软件包:

$ sudo apt-get install build-essential

下载 DMTCP 源代码后,解压、配置、编译、安装:

$ wget http://ufpr.dl.sourceforge.net/project/dmtcp/dmtcp/1.2.7/dmtcp-1.2.7.tar.gz
$ tar zxvf dmtcp-1.2.7.tar.gz
$ cd dmtcp-1.2.7
$ make
$ sudo make install

我们先来看一个例子程序,转到 dmtcp-1.2.7 里的 test 目录运行 dmtcp1,这个例子很简单,按照顺序输出 1 2 3 … 数字:

$ cd test
$ ./dmtcp1
  1   2   3   4   5   6 ^C

接下来我们要试验的是,中断这个例子程序,然后看看能不能恢复它。步骤是:

  1. 启动控制端 dmtcp_coordinator;
  2. 用 dmtcp_checkpoint 运行这个 dmtcp1 程序;
  3. 强制中断 dmtcp1;
  4. 恢复运行 dmtcp1.

使用

开另外一个窗口或者 screen 运行控制端 dmtcp_coordinator,用 l 查看当前节点状态:

$ dmtcp_coordinator
dmtcp_coordinator starting...
    Port: 7779
    Checkpoint Interval: disabled (checkpoint manually instead)
    Exit on last client: 0
Type '?' for help.

?
COMMANDS:
  l : List connected nodes
  s : Print status message
  c : Checkpoint all nodes
  i : Print current checkpoint interval
      (To change checkpoint interval, use dmtcp_command)
  f : Force a restart even if there are missing nodes (debugging only)
  k : Kill all nodes
  q : Kill all nodes and quit
  ? : Show this message

l
Client List:
#, PROG[PID]@HOST, DMTCP-UNIQUEPID, STATE
[7845] NOTE at dmtcp_coordinator.cpp:1039 in onConnect; REASON='worker connected'
     hello_remote.from = b51cf8-7846-516fbedc(-1)

然后重新用 dmtcp_checkpoint 运行 dmtcp1 这个例子程序:

$ dmtcp_checkpoint ./dmtcp1
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  1   2   3

回到控制端,l 一下就会看到多了条结点状态,dmtcp1 程序[进程号 7846]运行在主机名为 vpseedev 的主机上。

l
Client List:
#, PROG[PID]@HOST, DMTCP-UNIQUEPID, STATE
1, dmtcp1[7846]@vpseedev, b51cf8-7846-516fbedc, RUNNING

现在我们在控制端设置一个检查点(checkpoint),用 c 命令:

c
[7845] NOTE at dmtcp_coordinator.cpp:1315 in startCheckpoint; REASON='starting checkpoint, suspending all nodes'
     s.numPeers = 1
[7845] NOTE at dmtcp_coordinator.cpp:1317 in startCheckpoint; REASON='Incremented Generation'
     UniquePid::ComputationId().generation() = 1
[7845] NOTE at dmtcp_coordinator.cpp:643 in onData; REASON='locking all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:678 in onData; REASON='draining all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:684 in onData; REASON='checkpointing all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:694 in onData; REASON='building name service database'
[7845] NOTE at dmtcp_coordinator.cpp:713 in onData; REASON='entertaining queries now'
[7845] NOTE at dmtcp_coordinator.cpp:718 in onData; REASON='refilling all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:747 in onData; REASON='restarting all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:919 in onDisconnect; REASON='client disconnected'
     client.identity() = b51cf8-7846-516fbedc

然后用 Ctrl + c 强制中断这个正在运行的 dmtcp1:

$ dmtcp_checkpoint ./dmtcp1
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  1   2   3   4   5   6   7   8 ^C

这样在当前目录 test 下会生成一个临时文件用来保存程序镜像(稍后会看到就是通过这个文件来恢复程序的):

$ ls -l ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp
-rw------- 1 vpsee vpsee 2532431 Apr 18 09:37 ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp

用 dmtcp_restart 恢复就会看到 dmtp1 这个例子程序(从它中断的地方)继续运行了:

$ dmtcp_restart ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  9  10  11  12 ^C

DMTCP 甚至允许我们把运行了一半的程序暂停、保存到硬盘、拷贝到其他服务器上、继续运行,很酷吧~

Xen 半虚拟化安装 NetBSD 虚拟机(domU)

很久以前我们开始提供 NetBSD 的 VPS,期间陆续有朋友写信询问怎么制作 NetBSD/FreeBSD 的半虚拟化(PV)Xen 镜像,今天以安装最新的 NetBSD 6.0.1 版本为例演示一下,随便说一下制作 FreeBSD PV 虚拟机方法是类似的。Xen 全虚拟化方式(HVM)安装 NetBSD 虚拟机就不说了,和安装其他操作系统 Linux, Windows 差不多,毕竟全虚拟化不用考虑内核,安装要简单得多。考虑到性能,半虚拟化依然是 Xen 的强项,所以我们的 VPS 都是采用半虚拟化的,不过随着硬件的发展和 CPU 厂商的大力支持,半虚拟化的优势正渐渐消失。

这里演示的是安装 NetBSD domU,如果想了解安装 NetBSD dom0 的话看这里:在 NetBSD 上安装和配置 Xen.

准备

新建一个目录,然后下载一些东西,netbsd-INSTALL_XEN3_DOMU.gz 是安装 NetBSD 时候用的内核,netbsd-XEN3_DOMU.gz 是运行 NetBSD 用的内核,不要弄混了;NetBSD-6.0.1-amd64.iso 是我们需要的安装光盘。

$ mkdir netbsd
$ cd netbsd

$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/iso/NetBSD-6.0.1-amd64.iso

$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz
$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/amd64/binary/kernel/netbsd-XEN3_DOMU.gz

安装

首先制作一个大小为 5GB 的硬盘:

$ dd if=/dev/zero of=netbsd.disk bs=1024k count=1 seek=5000

然后新建一个 Xen domU 配置文件,并输入以下内容,:

$ vi netbsd
name = "netbsd"
memory = "256"
kernel = "/home/vpsee/netbsd/netbsd-INSTALL_XEN3_DOMU.gz"
disk = [ 'file:/home/vpsee/netbsd/netbsd.disk,xvda,w', 'file:/home/vpsee/netbsd/NetBSD-6.0.1-amd64.iso,ioemu:hdc:cdrom,r' ]
vif = [ 'bridge=xenbr0' ]
vcpus = "1"

使用 root 帐号启动这个名为 netbsd 的虚拟机开始 NetBSD 安装过程,这一步需要注意的是在选择安装介质的时候选择从 CD-ROM 安装并使用设备名 xbd0a (device [xbd1a]: xbd0a):

$ su

# xm create netbsd -c

NetBSD 安装界面如下,顺着屏幕提示安装即可,没有难度:

google apps directory sync

安装完毕后关闭这个虚拟机,修改 netbsd 的 Xen 配置文件,然后用新的配置文件启动虚拟机:

# xm destroy netbsd

# vi netbsd
name = "netbsd"
memory = "256"
kernel = "/home/vpsee/netbsd/netbsd-XEN3_DOMU.gz"
disk = [ 'file:/home/vpsee/netbsd/netbsd.disk,xvda,w' ]
vif = [ 'bridge=xenbr0' ]
vcpus = "1"

# xm create netbsd
Using config file "./netbsd".
Started domain netbsd

虚拟机启动后用 xm list 确认一下,然后就可以从控制台登陆 NetBSD 虚拟机了:

# xm list
Name                                      ID Mem(MiB) VCPUs State   Time(s)
Domain-0                                   0     1024     4 r----- 279689.0
netbsd                                   242      256     1 -b----      0.6

# xm console netbsd

剩下的配置 NetBSD 环境、IP 地址等这里就不用赘述了~

迁移 LDAP 用户到 Google Apps 平台

人手和精力不足的情况下自己维护邮件服务器实在是件头疼的事情,我们打算把这件吃力不讨好的事交给 Google,有免费的 Google Apps for Education 为啥要自己弄呢?Gmail 要比自己搭建的 SquirrelMail 和 roundcube 界面好用多了,而且还有免费的 Google Docs, Google Drive, Google Chat 可用,非常适合我们现在的情况。

我们的用户信息都保存在一台 LDAP 服务器上,要把全部用户信息(用户名、密码、Email、电话等)迁移到 Google Apps 的话需要迁移工具(没人想手动输入500个用户和电话!)。自己用 Python-LDAP 和 Google Apps Administrative APIs 写个 LDAP 到 Google Apps 的转换工具应该不难,不过要更懒一点,找现成工具。。。

Google 为帮助我们这些懒人和企业用户把数据迁到云端开发了不少工具,Google Apps Directory Sync 正是我们要找到,一个用于同步 LDAP 活动目录到 Google Apps 的好工具。

步骤

1、首先登陆到 Google Apps 平台,在自己帐号里的 Domain settings 的 User settings 页面选择 “Enable provisioning API”;

google apps directory sync

2、下载 Windows 或 Linux 版本的 Google Apps Directory Sync 工具并安装;

3、打开 Google Apps Directory Sync 工具,在里面依次配置 General Settings, Google Apps Configuration, LDAP Configuration, User Accounts, Notifications 等,LDAP 配置支持 MS Active Directory, OpenLDAP, Lotus Domino,我们的 LDAP 服务器用的是 OpenLDAP;

4、如果一切正常,在 Sync 里的 Validation Results & Sync 会看到 “打勾” 状态;

5、在真正同步(Sync & apply changes)之前先模拟(Simulate sync)一遍,点击下面蓝色的 “Simulate sync” 会出来结果报告;

google apps directory sync

6、查看上面的模拟结果,如果符合自己的要求的话就可以点击红色的 “Sync & apply changes” 开始实际操作了。

如何在 Xen dom0 下判断 domU 的硬盘使用率?

在 Xen 环境下我们可以很容易在 dom0 上通过 xm top 命令得到 domU 的当前运行状态信息,比如 domU 的 CPU 使用率,占用内存,IO 读写,网络等,但是无法知晓 domU 硬盘的使用情况,用了多少 inode、多少空间,还剩多少,是否快爆满、是否应该通知客户升级 Xen 硬盘等。这时候需要一种办法能得到 domU 上的硬盘信息,不一定要特别准确,只要不太离谱就行。我们使用 dumpe2fs 这个工具来打印客户的硬盘使用率,需要注意的是这个工具只针对 ext2/ext3/ext4 文件系统格式有效,也就是说只能用在那些使用 ext2/3/4 文件系统的 domU 中。

如果 Xen domU 使用的是文件格式的镜像:

# dumpe2fs -h /var/vps/images/vpsee.img
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:   
Last mounted on:          
Filesystem UUID:          e1f1f647-2098-4cfa-a1a3-9a44d4f93348
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal resize_inode dir_index filetype needs_recovery sparse_super large_file
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              2567264
Block count:              5120256
Reserved block count:     256012
Free blocks:              2674639
Free inodes:              1018476
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      621
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         16352
Inode blocks per group:   511
Filesystem created:       Sat Nov  7 06:25:55 2009
Last mount time:          Sat Sep  8 13:37:54 2012
Last write time:          Sat Sep  8 13:37:54 2012
Mount count:              3
Maximum mount count:      21
Last checked:             Fri Mar 23 12:34:20 2012
Check interval:           15552000 (6 months)
Next check after:         Wed Sep 19 12:34:20 2012
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:		  128
Journal inode:            8
First orphan inode:       1242758
Default directory hash:   tea
Directory Hash Seed:      a62d3cd5-9789-49bf-86c7-efee3d0286d4
Journal backup:           inode blocks
Journal size:             128M

如果 Xen domU 使用的是 LVM 格式的镜像:

# dumpe2fs -h /dev/vol-vps/vpsee_img 

从上面的 Inode count, Block count, Free blocks, Free inodes, Block size 等就可以判断出硬盘的使用率情况。

在 Ubuntu 上安装 SLURM 集群资源管理器

SLURM 是一个类似 Sun Grid Engine (SGE) 的开源分布式资源管理软件,用于超级计算机和大型计算节点集群,可高度伸缩和容错。SUN 被卖给 Oracle 后,好用的 SGE 变成 Oracle Grid Engine 并且从 6.2u6 版本开始成为商业软件了(可以免费使用90天),所以我们不得不另寻其他的开源替代方案,SLURM 是上次在德班高性能会议的时候一位陌生人介绍的,听上去不错。

SLURM 通过一对冗余集群控制节点(冗余是可选的)来管理集群计算节点,是由一个名为 slurmctld 的管理守护程序实现的,slurmctld 提供了对计算资源的监视、分配和管理,并将进入的作业序列映射和分发到各个计算节点上。每个计算节点也有一个守护程序 slurmd,slurmd 管理在其上运行的节点,监视节点上运行的任务、接受来自控制节点的请求和工作、将工作映射到节点内部等等。图示如下:

slurm architecture

官方网站提供的 Super Quick Start 安装文档一点都不 quick,看了头大。以下步骤使用两台服务器演示:主机名为 slurm00 的服务器用作控制节点;主机名为 slurm01 的服务器用作计算节点。

在控制节点和计算结点分别安装 slurm 包,这个包里面既含有控制节点需要的 slurmctld 也含有计算结点需要的 slurmd:

# apt-get install slurm-llnl

控制节点和计算结点之间需要通信,通信就需要认证,slurm 支持两种认证方式:Brent Chun’s 的 authd 和 LLNL 的 MUNGE,MUNGE 是专为高性能集群计算打造的,这里我们选用 MUNGE,生成 key 后启动 munge 认证服务:

# /usr/sbin/create-munge-key
Generating a pseudo-random key using /dev/urandom completed.

# /etc/init.d/munge start

使用 SLURM Version 2.3 Configuration Tool 在线配置工具生成配置文件,然后把配置文件拷贝控制节点以及各个计算结点的 /etc/slurm-llnl/slurm.conf(是的,控制节点和计算结点使用同一个配置文件)。

有了配置文件和启动了 munge 服务后就可以在控制节点启动 slurmctld 服务了:

# /etc/init.d/slurm-llnl start
 * Starting slurm central management daemon slurmctld                             [ OK ]

把控制节点生成的 munge.key 拷贝到各个计算结点:

# scp /etc/munge/munge.key ubuntu@slurm01:/etc/munge/

登陆计算节点后启动 munge 服务(注意需要改变 munge.key 的 owner 和 group 为 munge,否则会启动失败)和 slurmd 服务:

# ssh ubuntu@slurm01

# chown munge:munge munge.key 
# /etc/init.d/munge start
 * Starting MUNGE munged                                                           [ OK ]

# slurmd

在控制节点上(slurm00)测试一下是否顺利连接到计算结点(slurm01),并且简单运行一个程序 /bin/hostname 看看效果吧:

# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
debug*       up   infinite      1   idle slurm01

# srun -N1 /bin/hostname 
slurm01

在 Ubuntu 12.04 上安装 Open vSwitch

云计算时代人类已经成功虚拟化了服务器硬件,现在大大小小的数据中心有无数的虚拟机跑在服务器硬件上,看上去很美好,但是任务还没有完成,这么多的虚拟机都依赖物理服务器(所在)的网络端口、网络和交换机(除了物理依赖还依赖这些硬件上的软件配置),这让底层变动成为一个大问题,比如我们想改变服务器 A 上的网络设置(192.168.2.0 改成 172.16.2.0)或者物理移动服务器 A 到另一数据中心,那么服务器 A 上运行的虚拟机怎么办呢?逐个改动配置是很麻烦的。有没有一种办法能把虚拟机所在的网络和物理服务器的网络隔开呢(虽然可以用 VLAN,但是还是不够)?这正是网络虚拟化正在做的,通过软件的方式形成交换机部件(vSwitch),让各个虚拟机和虚拟交换机连接起来而不用去理会真实物理机和物理交换机。比如,让 Host A 上的 VM02 和 Host B 上的虚拟机 VM10 连成一个网络而不用理会虚拟机(VM)所在服务器(Host)的网络设置。

网络虚拟化或者软件定义网络(Software Defined Network, SDN)的应用远不止这些,任何了解 SDN 的人都不会怀疑 SDN 的未来,这也是为啥 VMware 愿意花12亿美金买 Nicira(软件定义网络的先驱)。

要使用 SDN/OpenFlow 就必须有支持 OpenFlow 协议的物理(或软件)交换机,OpenvSwitch 就是这么一个支持 OpenFlow 协议的开源虚拟交换机。我们从安装虚拟交换机 Open vSwitch 开始来慢慢了解网络虚拟化吧。

安装必要软件包:

$ sudo -i
# apt-get install kvm libvirt-bin openvswitch-controller openvswitch-brcompat openvswitch-switch openvswitch-datapath-source

启动 Open vSwitch 服务,如果报错 FATAL: Error inserting brcompat_mod 模块错误则需要编译和加载 brcompat_mod 这个模块,这个模块是 openvswitch 为了兼容 linux bridge 而来的,有些程序使用 Linux bridge(比如 brctl),这些程序为了能在 openvswitch 下继续使用将需要这个 brcompat_mod 兼容模块,这个模块为那些慢慢迁移到 openvswitch 的程序提供了方便:

# service openvswitch-switch start
FATAL: Error inserting brcompat_mod (/lib/modules/3.2.0-30-generic/updates/dkms/brcompat_mod.ko): Invalid module format
 * Inserting brcompat module
Module has probably not been built for this kernel.
For instructions, read
/usr/share/doc/openvswitch-datapath-source/README.Debian
FATAL: Error inserting brcompat_mod (/lib/modules/3.2.0-30-generic/updates/dkms/brcompat_mod.ko): Invalid module format
 * Inserting brcompat module

# module-assistant auto-install openvswitch-datapath

编译模块后再次尝试启动服务:

# service openvswitch-switch restart
 * Killing ovs-brcompatd (1606)
 * Killing ovs-vswitchd (1603)
 * Killing ovsdb-server (1594)
 * Starting ovsdb-server
 * Configuring Open vSwitch system IDs
 * Starting ovs-vswitchd
 * Starting ovs-brcompatd
 * iptables already has a rule for gre, not explicitly enabling

 # service openvswitch-controller restart
 * Restarting ovs-controller ovs-controller                                              Sep 12 13:46:46|00001|stream_ssl|INFO|Trusting CA cert from /etc/openvswitch-controller/cacert.pem (/C=US/ST=CA/O=Open vSwitch/OU=switchca/CN=OVS switchca CA Certificate (2012 Sep 12 13:42:19)) (fingerprint 46:5b:14:1f:13:56:b0:b0:a7:4d:10:39:ee:68:18:d4:39:3c:4b:d0)
                                                                                  [ OK ]

编辑配置文件,取消注释并设置 BRCOMPAT 为 yes 以便启动后能使用 brcompat_mod 模块:

# vi /etc/default/openvswitch-switch
# This is a POSIX shell fragment                -*- sh -*-

# FORCE_COREFILES: If 'yes' then core files will be enabled.
# FORCE_COREFILES=yes

# BRCOMPAT: If 'yes' and the openvswitch-brcompat package is installed, then
# Linux bridge compatibility will be enabled.
BRCOMPAT=yes

重启一下系统,验证一下是否模块被自动加载:

# reboot

# lsmod | grep brcom
brcompat_mod           13512  0 
openvswitch_mod        83993  1 brcompat_mod

使用 openvswitch 增加网桥 br0 并把网络接口 eth0 加入 br0:

# ovs-vsctl add-br br0
# ovs-vsctl add-port br0 eth0

# ovs-vsctl show          
a23c503b-bfbe-4646-8738-a7f69e5d69a0
    Bridge "br0"
        Port "eth0"
            Interface "eth0"
        Port "br0"
            Interface "br0"
                type: internal
    ovs_version: "1.4.0+build0"

配置网桥 br0 和网络接口 eth0(和用 bridge-utils 工具配置的时候一样,不同的是这里用更先进的 openvswitch/brcompat_mod 替换了 bridge-utils):

# ifconfig eth0 0
# ifconfig br0 192.168.2.45 netmask 255.255.255.0
# route add default gw 192.168.1.1 br0

为了保存网络设置,最好把上面的配置写到 /etc/network/interfaces 里:

# vi /etc/network/interfaces
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
address 192.168.2.45
netmask 255.255.255.0
gateway 192.168.2.1

auto eth0
iface eth0 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down

VMware vSphere Client 访问虚拟机控制台无故断开问题

安装在 Windows Server 2008 R2 上的 VMware vSphere Client 在查看虚拟机 console 的时候出现如下问题,无法访问和看到虚拟机的控制台:

vmrc console problem

解决办法是打开 Windows 程序管理器,终止 vmware-vmrc.exe 进程(通常有2个):

kill vmware-vmrc.exe

然后重启 VMware vSphere Client 后重新连接 VMware vSphere 服务器。如果还有问题杀掉 vmware console 和 vmware converter 相关进程后再试一下,还不行就卸载 vmware converter 后再试试。

Xen 和 KVM 下如何关闭 virbr0

安装 Xen安装 KVM 后都会发现网络接口里多了一个叫做 virbr0 的虚拟网络接口:

# ifconfig
...
virbr0    Link encap:Ethernet  HWaddr d2:91:97:b8:3d:fc  
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
...

这是由于安装和启用了 libvirt 服务后生成的,libvirt 在服务器(host)上生成一个 virtual network switch (virbr0),host 上所有的虚拟机(guests)通过这个 virbr0 连起来。默认情况下 virbr0 使用的是 NAT 模式(采用 IP Masquerade),所以这种情况下 guest 通过 host 才能访问外部。

virtual network switch (virbr0)

大多数时候我们虚拟机使用的是 bridge(网桥)直接连到局域网里,所以这个 virbr0 不是必须的(注:不要搞混淆了,bridge 和这里的 virbr0 bridge 是互不相干的)。如何关掉这个 virbr0 呢?先 net-destroy 然后 net-undefine,最后别忘了重启 libvirtd 让设置生效:

# virsh net-list
Name                 State      Autostart
-----------------------------------------
default              active     yes

# virsh net-destroy default
Network default destroyed

# virsh net-undefine default
Network default has been undefined

# service libvirtd restart
Stopping libvirtd daemon:                                  [  OK  ]
Starting libvirtd daemon:                                  [  OK  ]

如何在 KVM 虚拟机上运行 KVM

上次讨论了如何在 VMware ESXi 虚拟机上运行 KVM 问题,前不久有读者想 “在 kvm 上面创建个虚拟机安装 rackspace 的 openstack” 问到 “如何开启虚拟机上的 CPU VT 功能以便在 KVM 上运行 KVM”,又是一个嵌套应用虚拟机的问题:在 KVM 虚拟机上运行 KVM 虚拟机。以下步骤在 Ubuntu Server 12.04 LTS 64 bit 上测试通过。

首先检查 KVM host(母机)上是否打开了嵌套虚拟机功能(默认是开启的):

# modinfo kvm_intel | grep nested
parm:           nested:bool

# cat /sys/module/kvm_intel/parameters/nested
Y

如果上面的显示结果不是 Y 的话需要开启 nested:

# modprobe -r kvm-intel
# modprobe kvm-intel nested=1
# cat /sys/module/kvm_intel/parameters/nested
Y

然后在 KVM guest(虚拟机)的 xml 配置文件中加入 vmx 选项,并启动虚拟机(这里用的是 Ubuntu 官方发布的 Ubuntu KVM 镜像 ubuntu-12.04-server-cloudimg-amd64-disk1.img):

# vi nestedvm.xml
...
<cpu match='exact'/>
   <model>core2duo</model/>
   <feature policy='require' name='vmx'//>
</cpu/>
...

# virsh create nestedvm.xml

启动虚拟机后登陆并安装 KVM,执行 kvm-ok 和 modinfo 均出现错误:

# apt-get install ubuntu-virt-server

# kvm-ok
INFO: /dev/kvm does not exist
HINT:   sudo modprobe kvm_intel
INFO: Your CPU supports KVM extensions
KVM acceleration can be used

# modinfo kvm_intel
ERROR: modinfo: could not find module kvm_intel

这是因为我们使用的是 ubuntu-12.04-server-cloudimg-amd64-disk1.img 这个官方虚拟机镜像,这个镜像使用的是 linux 3.2.0-23-virtual 内核,缺少 KVM 模块(kvm-intel.ko),所以我们需要改为 generic 内核:

# uname -a
Linux test 3.2.0-23-virtual #36-Ubuntu SMP Tue Apr 10 22:29:03 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

# apt-get install linux-generic

重启后进入虚拟机执行 kvm-ok 和 modinfo 均成功:

# kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

# modinfo kvm_intel
filename:       /lib/modules/3.2.0-30-generic/kernel/arch/x86/kvm/kvm-intel.ko
license:        GPL
author:         Qumranet
srcversion:     3BAF54F96ECD4B02292CAA0
depends:        kvm
intree:         Y
vermagic:       3.2.0-30-generic SMP mod_unload modversions 
parm:           vpid:bool
parm:           flexpriority:bool
parm:           ept:bool
parm:           unrestricted_guest:bool
parm:           emulate_invalid_guest_state:bool
parm:           vmm_exclusive:bool
parm:           yield_on_hlt:bool
parm:           fasteoi:bool
parm:           nested:bool
parm:           ple_gap:int
parm:           ple_window:int

现在应该可以在这个虚拟机上创建另一个虚拟机了。

用 MultiTail 查看多个 OpenStack 日志

使用 OpenStack 特别是排错的时候需要查看多个日志来定位错误,如果用 tail 会开很多 Terminal.app 程序切换查看,不方便;如果用 screen 会用 ctrl+A+N 在多个窗口切换也不方便。啥工具能在一个屏幕上跟踪多个日志文件呢?MultiTail 就是这样的一个工具,可以在一个窗口实时显示多个文件内容的更新情况,并提供了配色方案,垂直、水平分割屏幕等方便阅读和查看的功能。

在 Ubuntu/Debian 上安装 multitail:

$ sudo apt-get install multitail

在 CentOS/RHEL/Fedora 上安装 multitail:

# wget http://pkgs.repoforge.org/multitail/multitail-5.2.9-1.el6.rf.x86_64.rpm
# rpm -ivh multitail-5.2.9-1.el6.rf.x86_64.rpm

运行 multitail 在一个屏幕同时监控 nova-schedule, nova-compute, nova-network 日志:

$ multitail -s 2 /var/log/nova/nova-scheduler.log \
/var/log/nova/nova-compute.log \
/var/log/nova/nova-network.log

这里为了控制截图大小不得不把窗口弄小,理想情况是把这个 Terminal 窗口投放到外接显示器上并同时显示8个日志,这样排错会很有效率~

multitail

如果使用 DevStack 脚本安装 OpenStack 的话,日志会显示在 screen 会话里,使用 screen -x 连接后就可以 ctrl+A+N 切换看日志,不过这个日志是没有保存的,所以没法直接用 multitail 打开日志,需要先保存日志。要保存日志文件则需要在安装 OpenStack 前就配置 DevStack 脚本告诉 DevStack 把 OpenStack 运行日志写到 /opt/stack/logs/screen 下:

$ vi devstack/localrc
...
DEST=/opt/stack
SCREEN_LOGDIR=$DEST/logs/screen
...

然后运行 multitail:

$ multitail -s 2 /opt/stack/logs/screen/screen-n-sch.log \
/opt/stack/logs/screen/screen-n-cpu.log \
/opt/stack/logs/screen/screen-n-net.log