如何快速创建 Xen 虚拟机镜像

在 Linux 上安装完 Xen 服务器后接下来的工作就是如何创建和启动一个虚拟机。这个看似很简单的问题难住了不少人,VPSee 收到不少邮件关于如何快速创建和部署虚拟机镜像的。创建虚拟机的工具有很多,比如 virt-manager, virt-install, virsh, xen-create-image 等等,不过这些工具都要每次重头安装虚拟机的操作系统,需要人机交互、速度慢、不自动,不利于写成脚本。有什么快速的创建/部署/克隆虚拟机的办法呢?可以先做一个模版,然后通过拷贝模版的办法。我们只需要两个步骤:1、创建一个空白文件镜像;2、然后把一个打包好的 Linux 系统模版拷贝过去。通常一个打包好的最小 Linux 系统只要200MB 左右,在高配置的服务器上拷贝基本能瞬间完成,比起拷贝整个虚拟机镜像文件(比如 10GB)要快得多。具体步骤:

1、创建一个磁盘镜像文件:

# dd if=/dev/zero of=test.img bs=1 count=1 seek=10G

2、格式化磁盘:

# mkfs.ext3 test.img

3、挂载刚刚创建的磁盘镜像文件:

# mount -o loop test.img /mnt

4、找个现有 Linux 的文件系统拷贝过去:

# tar -zxSf centos.tar.gz -C /mnt/

需要说明的是,这里的 centos.tar.gz 是提前制作好的,可以在一个干净的虚拟机上手动安装好一个最小的 CentOS 系统,然后配置和优化好,这样就是一个模板,以后如果创建新的 CentOS 虚拟机就可以从这个模板直接拷贝。

5、卸载 /mnt:

# umount mnt

6、创建一个交换分区:

# dd if=/dev/zero of=test-swap.img bs=1M count=256

7、创建和编辑一个 Xen 虚拟机的启动文件:

# vi /etc/xen/test.conf
name            = 'test'
vcpus           = 1
memory          = '256'
disk            = [ 'tap:aio:/home/vpsee/test.img,sda1,w',
'tap:aio:/home/vpsee/test-swap.img,sda2,w',
]
vif             = [ 'bridge=eth0' ]
root            = '/dev/sda1 ro'
on_reboot       = 'restart'
on_crash        = 'restart'
kernel          = "/boot/vmlinuz-2.6.18-194.32.1.el5xen"
ramdisk         = "/boot/initrd-2.6.18-194.32.1.el5xen.img"

8、启动 Xen 虚拟机:

# xm create test

如果把上面的步骤综合起来写在一个脚本里并配上 Xen Shell 控制面板就可以完成 VPS 客户自己快速重装系统的功能。如果把这个脚本加到客户的账单管理系统里(比如 WHMCS)就可以完成客户付款自动开通 VPS 的功能。不过我们的 VPS 不提供客户自助重装功能和自动开通功能,损失了一点方便性,但是换来了稳定和性能还是值得的。如果用 LVM, iSCSI 之类的存储方式的话原理也是一样的。

安装 OpenNebula 基于 Web 的管理控制台

我们一般用 onehost/onevm/onevnet 这些命令行工具来管理 OpenNebula 云计算平台,不过有个项目组开发了 OpenNebula Management Console 管理工具,基于 PHP 和 MySQL,安装和配置也不是很复杂,和配置普通 CMS 系统差不多。上周我们在两台服务器上安装和配置了一个最小的 OpenNebula 云计算平台,我们将在生产环境测试一段时间 OpenNebula,争取能用 OpenNebula 替换我们自己的脚本,并逐步用这个平台来统一管理我们的 Xen 服务器。VPSee 周末试了试这个基于 Web 界面的 OpenNebula 管理工具,界面简单清晰,使用也很方便。这个控制台管理工具(onemc)只能安装在前端(Front-End)服务器上。

安装必备软件包

onemc 是基于 PHP 和 MySQL 的,需要安装一些必要的软件包:

# yum install php php-mysql mysql-server php-curl php-xmlrpc httpd \
php-pear php-devel php-adodb

下载 onemc

下载和解压 onemc-1.0.0.tar.gz 后直接放在 apache 的默认目录里(懒得改 httpd.conf):

# cd /var/www/html
# wget http://dev.opennebula.org/attachments/download/128/onemc-1.0.0.tar.gz
# tar zxvf onemc-1.0.0.tar.gz
# cd onemc

配置数据库

# mysql -uroot -p
Enter password: 
mysql> create database onemc;
mysql> create user 'oneadmin'@'localhost' identified by 'oneadmin';
mysql> grant all privileges on onemc.* to 'oneadmin'@'localhost';
mysql> \q

# mysql -u oneadmin -p onemc < /var/www/html/onemc/include/mysql.sql

配置 onemc

# vi /var/www/html/onemc/include/config.php
...
// vmm: kvm or xen
$vmm = "xen";
...
// ADODB settings
$adodb_type = "mysql";
$adodb_server = "localhost";
$adodb_user = "oneadmin";
$adodb_pass = "oneadmin";
$adodb_name = "onemc";
...

登录

如果系统设置了 http_proxy 环境变量的话一定要先关闭,然后重启 one 和 httpd:

# unset http_proxy
# one stop; one start
# /etc/init.d/httpd restart

打开 http://172.16.39.110/onemc/index.php 页面后就会显示登录信息(172.16.39.110 是 OpenNebula 前端的 IP 地址),用户名和密码是安装和配置 OpenNebula 的时候在 one_auth 中设置的密码(cat "oneadmin:password" > one_auth)。

opennebula management console

在 CentOS 上安装和配置 OpenNebula

我们提到的云计算一般有三种类型:软件即服务(Software as a Service, SaaS),平台即服务(Platform as a Service, PaaS)和基础架构即服务(Infrastructure as a Service, IaaS)。云概念刚出来的时候被人说的云里雾里摸不着头,现在云技术已经深入人心,也许你正在使用云而自己没有察觉呢,比如每天使用的 Gmail 就在 Google 大云上。为了更好理解这三种不同的云,我们可以拿 Google 来举例,刚好这家公司提供了三种形式的云服务,首先看 SaaS,Google Gmail/Docs/Gtalk/Maps 这些 Apps 都运行在 Google 云上,所以他们为普通用户提供了 “软件即服务”;Google 同时提供面向开发人员的 AppEngine,可以让开发人员在他们的平台(Platform)上使用 Python, Java 等语言和他们提供的 API 开发软件和服务,所以他们为开发人员提供了 “平台即服务”;Google 自己内部构建了基于 GFS, BigTable, MapReduce 之上的庞大基础云设施,为自己内部人员提供了 “基础架构即服务”,这就是三种不同类型的云。

OpenNebula 是一套开源的云计算基础管理工具,用来方便管理员在数据中心统一部署、创建、分配和管理大量的虚拟机,企业数据中心可以利用这套工具搭建自己的私有云,为自己内部提供 IaaS 服务,类似的开源产品还有 OpenStack, CloudStack, Eucalyptus, openQRM 等等。以下的安装过程在 VPSee 的两台装有 CentOS 5.5 系统的服务器上完成,一台服务器做 OpenNebula 前端(node00),另一台服务器用来做节点(node01),搭建一个最小的 “云”,如果想扩展这个云的话,只需要逐步增加节点(node02, node03, …)就可以了。如果对其他类似的开源云计算平台感兴趣的话可以看看:在 Ubuntu 上安装和配置 OpenStack Nova,最新的 OpenNebula 4.0 安装看这里:在 CentOS 6.4 上安装和配置 OpenNebula 4.0.

安装和配置前端(Front-End)

增加 CentOS Karan 源:

# cd /etc/yum.repos.d
# wget http://centos.karan.org/kbsingh-CentOS-Extras.repo
# yum update

安装 OpenNebula 需要的软件包以及编译 OpenNebula 源代码所需的工具:

# yum install gcc gcc-c++ make openssl-devel flex bison

# yum install ruby ruby-devel ruby-docs ruby-ri ruby-irb ruby-rdoc
# yum install rubygems
# gem install nokogiri rake xmlparser

# yum install scons
# yum install xmlrpc-c xmlrpc-c-devel

CentOS 自带的 sqlite 版本不行,需要下载和编译 sqlite 3.6.17 版本:

# wget http://www.sqlite.org/sqlite-amalgamation-3.6.17.tar.gz
# tar xvzf sqlite-amalgamation-3.6.17.tar.gz
# cd sqlite-3.6.17/
# ./configure; make; make install

下载和编译 opennebula 2.0.1 源码包后,解压、编译和安装:

# tar zxvf opennebula-2.0.1.tar.gz
# cd opennebula-2.0.1
# scons
# ./install.sh -d /srv/cloud/one

# ls /srv/cloud/one/
bin  etc  include  lib  share  var

启动 OpenNebula 前需要配置 ONE_AUTH 环境变量,这个环境变量从 $HOME/.one/one_auth 这个文件读取,所以要先创建 one_auth 这个文件后再启动 one(OpenNebula 服务程序):

# cd /root/
# mkdir .one
# cd .one/
# echo "oneadmin:password" > one_auth

# one start

OpenNebula 支持 KVM, Xen 和 VMware 三种虚拟技术,我们还需要告诉 OpenNebula 我们想用哪种,并重启 one 以便配置生效:

# vi /etc/one/oned.conf
...
IM_MAD = [
    name       = "im_xen",
    executable = "one_im_ssh",
    arguments  = "xen" ]

VM_MAD = [
    name       = "vmm_xen",
    executable = "one_vmm_ssh",
    arguments  = "xen",
    default    = "vmm_ssh/vmm_ssh_xen.conf",
    type       = "xen" ]
...

# one stop
# one start

安装和配置节点(Compute Node)

需要在每个 node 上都安装 Xen 或 KVM 的虚拟环境,具体请参考:在 CentOS 上安装和配置 Xen在 CentOS 上安装和配置 KVM,还需要 ruby 运行环境:

# yum install ruby 

交换 SSH Key

因为 OpenNebula Front 和 Nodes 之间是通过 SSH 通讯的,所以 front 和 nodes 之间要设置成 SSH 无密码登录避免 front 运行 node 上脚本或克隆镜像的时候输入密码,首先在 front 和 nodes 上配置 sshd:

# vi /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes

# /etc/init.d/sshd restart

在 front (node00) 上创建 key 后拷贝到 node (node01):

# ssh-keygen -t rsa
# ssh-copy-id -i ~/.ssh/id_rsa.pub node01

在1个 node (node01) 上创建 key 后拷贝到 front (node00):

# ssh-keygen -t rsa
# ssh-copy-id -i ~/.ssh/id_rsa.pub node00

onehost

front 和 每个 node 都能无密码 ssh 沟通后,就可以在 front 上 onehost create 命令来逐个加入 node,并用 onehost list 来查看是否创建成功:

# onehost create node01 im_xen vmm_xen tm_ssh

# onehost list
  ID NAME              CLUSTER  RVM   TCPU   FCPU   ACPU    TMEM    FMEM STAT
  1 node01     default    0    400    400    400    3.8G    383M   on

如果执行 onehost create 报错,查看 oned.log 日志发现 sudo: sorry, you must have a tty to run sudo 字样,原因则是 OpenNebula 需要远程 ssh/sudo 执行命令,而 CentOS 的 sudo 选项 requiretty 是默认打开的,ssh 需要一个 tty 才能执行,所以远程 sudo 就会出错,:

# onehost create node01 im_xen vmm_xen tm_ssh

# tail /var/log/one/oned.log 
Tue Feb 22 11:08:58 2011 [InM][I]: Command execution fail: 'if [ -x "/var/tmp/one/im/run_probes" ]; then /var/tmp/one/im/run_probes xen 172.16.39.111; else                              exit 42; fi'
Tue Feb 22 11:08:58 2011 [InM][I]: STDERR follows.
Tue Feb 22 11:08:58 2011 [InM][I]: sudo: sorry, you must have a tty to run sudo
Tue Feb 22 11:08:58 2011 [InM][I]: Error executing xen.rb
...

解决办法就是关闭(注释掉) requiretty 这行:

# chmod 600 /etc/sudoers
# vi /etc/sudoers
#Defaults    requiretty

因为 VPSee 的这两台服务器使用了 HTTP 代理上网,所以 OpenNebula 读取了系统的 http_proxy 环境变量,在 sched.log 日志里发现了 HTTP response 错误,这时候需要关闭 http_proxy:

# cat /var/log/one/sched.log
Tue Feb 22 14:27:39 2011 [HOST][E]: Exception raised: Unable to transport XML to server and get XML response back.  HTTP response: 504
Tue Feb 22 14:27:39 2011 [POOL][E]: Could not retrieve pool info from ONE

# unset http_proxy

onevnet

创建和编辑虚拟网络配置文件,然后创建一个 OpenNebula 虚拟网络:

# vi small_network.net
NAME = "Small network"
TYPE = FIXED

BRIDGE = br0
LEASES = [ IP="192.168.0.5"]
LEASES = [ IP="192.168.0.6"]
LEASES = [ IP="192.168.0.7"]

# onevnet create small_network.net 

# onevnet list
  ID USER     NAME              TYPE BRIDGE P #LEASES
   0 oneadmin Small network    Fixed    br0 N       0

onevm

创建和编辑虚拟机的启动配置文件,这里的 centos.5.5.x86.img 可以从 http://stacklet.com/ 下载(收费)或者自己利用 Xen 工具创建一个:

# wget http://stacklet.com/sites/default/files/centos/
centos.5.5.x86.img.tar.bz2
# tar jxvf centos.5.5.x86.img.tar.bz2
# mv centos.5.5.x86.img /srv/cloud/one/var/images/

# vi centos.one 
NAME   = centos
CPU    = 1
MEMORY = 256

DISK = [
  source   = "/srv/cloud/one/var/images/centos.5.5.x86.img",
  target   = "sda1",
  clone    = "yes",
  readonly = "no" ]

NIC = [ MAC = "00:16:3E:00:02:64", bridge = br0 ]

OS = [ bootloader     = "/usr/bin/pygrub" ]

用 onevm create 命令启动上面的 VM 配置文件,就会在 node01 上创建一个虚拟机,用 onevm list 查看会看到 prol 状态,表示正在创建过程中,创建完毕后状态会变成 runn:

# onevm create centos.one

# onevm list
   ID     USER     NAME STAT CPU     MEM  HOSTNAME        TIME
    1 oneadmin   centos prol   0      0K  node01   00 00:09:09

# onevm list
   ID     USER     NAME STAT CPU     MEM  HOSTNAME        TIME
    1 oneadmin   centos runn   0      0K  node01   00 00:22:17

就这样,我们在 node00 (front) 和 node01 (node) 这两台服务器上部署了一个最小的云,并且在 node01 上运行了一个基于 Xen 的虚拟机实例。

VMware ESXi 上如何使用 CDROM

在 VMware ESXi 上安装操作系统的话一般通过 VMware vShpere Client 上传 iso 文件到 datastore,然后通过挂载 iso 后安装;而且如果 VMware ESXi 需要什么文件可以通过 ssh/scp 传文件,所以在 VMware ESXi 上很少需要用到 CDROM 的时候。不过 VPSee 昨天碰到一个需要用 CDROM 的情况,那么如何在 VMware ESXi 下挂载和使用 CDROM 呢?

加载 CDROM 模块和挂载 CDROM 后就可以和 linux mount 一样使用 CDROM 了,进入 VMware ESXi 控制台(如果想远程登录 VMware ESXi 的话需要先打开 SSH 服务):

~ # vmkload_mod iso9660
Module iso9660 loaded successfully

~ # /sbin/vsish -e set /vmkModules/iso9660/mount mpx.vmhba32:C0:T0:L0
~ # ls /vmfs/volumes/CDROM
A.Z           DRYRUN.CFG    INSTALL.VGZ   OPEN_SOU.TXT  VMKERNEL.GZ
BOOT.CAT      IENVIRON.VGZ  ISOLINUX.BIN  README.TXT
CIM.VGZ       IMAGEDD       ISOLINUX.CFG  SYS.VGZ
CIMSTG.TGZ    IMAGEDD.BZ2   MBOOT.C32     TBOOT.GZ
CUSTOM.CFG    IMAGEDD.MD5   MENU.C32      VMKBOOT.GZ

要卸载 CDROM 的话刚好和挂载相反:

~ # /sbin/vsish -e set /vmkModules/iso9660/umount mpx.vmhba32:C0:T0:L0
~ # vmkload_mod -u iso9660

如何在 OpenVZ 和 Xen VPS 上增加 inode

前几天有位客户问我们 “能不能增加 inode?”,刚开始误解了客户的意思,以为客户问的是 “能不能增加文件数限制?”,因为 inode 是在格式化分区和创建文件系统的时候决定的,不是在运行时可以更改的内核或系统参数,所以很好奇客户为什么会这么问。接着客户问到 “我在 BurstNet 的 VPS 上可以免费增加 inode,为什么你们的 VPS 不能?”,所以 VPSee 在这里有必要解释一下 OpenVZ 和 Xen 在对待 inode 上的区别,以免大家误认为 OpenVZ 很强大。OpenVZ VPS 是一个虚拟环境(容器),与母机(host)和邻居(同母机的其他 VPS)分享计算资源,有较多的限制,OpenVZ VPS 不能使用自己的内核、不能自己添加或卸载内核模块(所以需要服务商介入加载 tun 模块后才能用 vpn)、不拥有自己的文件系统、甚至 inode 这种资源也需要服务商授权来分配,简单的说母机上有什么就只能用什么(除了可以自己安装程序以外)。在 OpenVZ 上 inode 已经由服务商在安装母机(格式化)的时候就决定了系统的总 inode,然后根据每个不同 OpenVZ VPS 的需要来调整 inode 的大小,服务商再打上免费的标签配上一副严肃专业的口气告诉客户这是 “免费” 的,让客户误认为自己占了大便宜。OpenVZ 服务商能监控客户的 “一切” 活动,客户正在运行什么程序、客户的 VPS 还剩下多少内存和硬盘、CPU 状况等。比如,服务商可以通过 vzctl 命令来查看客户 VPS 1 的硬盘和 inode 消耗情况:

# vzctl exec 1 df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/simfs             10G  386M  9.7G   4% /

# vzctl exec 1 df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/simfs            200000   24853  175147   13% /

如果想在 OpenVZ 上增加 inode 的话需要 VPS 服务商的帮助,比如把 VPS 1 的 inode 增加3倍:

# vzctl set 1 --diskinodes $(( 200000*3 )):$(( 220000*3 )) --save
Saved parameters for CT 1

# vzctl exec 1 df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/simfs            600000   24853  575147    5% /

如果想在 Xen 上增加 inode 的话和在独立的 Linux 服务器上增加 inode 是一样的,可以增加硬盘分区的容量、重新格式化分区指定需要的 inode 数目等。VPSee 在这里介绍一个比较简单、不破坏原系统(不用重新格式化硬盘)、不增加 VPS 客户成本(不用购买和增加硬盘容量)的替代办法:可以在自己的 Xen VPS 或 Linux 服务器上创建一个大文件来充当硬盘、用 mke2fs -N 指定 inode 数目并格式化这个硬盘、然后挂载到系统里使用,下面是格式化 vpsee0.img 的 inode 数目为默认值和格式化 vpsee1.img 的 inode 数目为 1572864:

# dd if=/dev/zero bs=1024k count=4096 > vpsee0.img
# dd if=/dev/zero bs=1024k count=4096 > vpsee1.img

# losetup /dev/loop0 vpsee0.img
# losetup /dev/loop1 vpsee1.img

# mke2fs /dev/loop0
# mke2fs -N 1572864 /dev/loop1

# losetup -d /dev/loop0
# losetup -d /dev/loop1

把上面创建好的文件系统(分区)挂载后就可以用 df -i 看到 vpsee1.img 的 inode 比 vpsee0.img 的 inode 扩大了3倍(虽然分区大小是一样的):

# mkdir /mnt0 /mnt1

# mount -o loop vpsee0.img /mnt0
# mount -o loop vpsee1.img /mnt1

# df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
...
/tmp/vpsee0.img        524288      11  524277    1% /mnt0
/tmp/vpsee1.img       1572864      11 1572853    1% /mnt1

开启 VMware ESXi 的 SSH 服务

昨天收到一位 VPS 客户邮件问到一个不相关 VPS 业务的问题(这个问题已经发到相关文章的评论里),请大家把与我们 VPS 业务不相关的技术问题直接发到博客上,这样大家都可以看见和搜索到,我们也不必重复回复类似的问题和邮件了:)问题是这样的,如何把 VMware ESXi 上的虚拟机镜像文件拷贝出来?一种简单的解决办法就是用 ssh 登录 VMware ESXi 服务器,然后到相关目录直接把镜像文件拷贝出来。VMware ESXi 默认是关闭 ssh 的,那么如何开启呢?

在 VMware ESXi 3.5 控制台上直接按 “ALT + F1″ 就可以到 console,输入 “unsupported” 后回车进入 Tech Support Mode 模式,输入 root 用户名和密码登录就进入 console 了,然后编辑 inetd.conf 文件、去掉 ssh 那行注释、保存、然后重启服务就可以了:

~# vi /etc/inetd.conf
ssh stream tcp ...

~# /sbin/services.sh restart

如果是 VMWare ESXi 3.5 Update 2 版本,需要找到 inetd 进程并用 kill 带上 -HUP 选项重启这个服务进程:

~ # ps | grep inetd
5031 5031 busybox              inetd

~# kill –HUP 5031

在 VMware ESXi 4.1 上开启 ssh 功能和 VMware ESXi 3.5 不同,如果直接按 “ALT + F1″ 的话会看见以下提示信息:

Tech support mode has been disabled by your administrator

所以需要先把 Tech support mode 打开,在 VMware ESXi 4.1 上输入密码后进入界面控制台,选择 “Troubleshooting Options”,继续选择 “Enable Local Tech Support” 和 “Enable Remote Tech Support (SSH)”,这样就可以同时开启本地 console 和远程 ssh 登录。

在 VMware ESXi 5.0 上开启 ssh 功能就简单多了,直接在操作界面里 enable 就可以了。

用 ssh 登录 VMware ESXi 后就可以随心所欲了,根目录下就这么些文件和目录,层次清晰,很容易找出虚拟机镜像文件在哪,需要的话把这些镜像文件 scp 拷出来就可以了。

~ # ls /vmfs/volumes/datastore1/minix01/
minix01-d76c0df1.vswp  minix01.nvram      minix01.vmsd       minix01.vmxf
minix01-flat.vmdk      minix01.vmdk       minix01.vmx        vmware.log

用 VNC 访问 VMware ESXi 虚拟机控制台

在 VMware ESXi 上安装 Minix 以后可以通过 ssh/telnet 来访问 Minix,大部分时候这样做都足够了,但是如果我们想做一些 Minix 内核上的修改和实验就要面临内核和系统编译后启动不了的情况,这个时候就需要直接进入 VMware ESXi 控制台来手动启动备用内核。那么有没有可能像 Xen 那样在虚拟机配置文件中加入 vnc 选项让用户可以通过 vnc 客户端来访问自己的虚拟机终端呢?作为虚拟技术的领导产品 VMware ESXi 4.1 当然也有类似的办法。有了 vnc 的支持以后我们就可以在校内的任意一台电脑或者 SunRay 瘦客户端上登录自己的 Minix 虚拟机了,这样就会非常方便我们的操作系统课程教学和学生的实验,这比以前讨论的 SunRay 在 GDM 里直接启动 VirtualBox 那种连接和使用虚拟机的方法要更好一些。VMware ESXi 提供了免费的图形化客户端工具 VMware vShpere Client,很容易操作,用 vShpere Client 连接 VMware ESXi 后关闭虚拟机,然后按照下面步骤编辑虚拟机的配置文件:

  1. 鼠标右击选择 “Edit settings”;
  2. 选择 “Options” 标签页;
  3. 在 “Advanced” 下选择 “General”;
  4. 点击 “Configuration Parameters” 按钮;
  5. 最后加入如下配置参数:
RemoteDisplay.vnc.enabled = "true"
RemoteDisplay.vnc.password = "vpsee.com"
RemoteDisplay.vnc.port = "5900"

vnc setup on vmware esxi

重新启动虚拟机后就可以通过任意一个 vnc 客户端连上虚拟机的控制台了,这样就可以看到整个系统启动过程,可以自己启动和关闭虚拟机。Minix 3 一般会有2个内核,一个是当前内核,一个是备用内核,当修改编译当前内核失败以后可以用第2个选项(2 Start Custom MINIX 3)启动,非常方便修改和开发内核。关闭 Minix 以后可以通过 menu 命令选择内核:

connect vnc to minix

在 CentOS 上安装和配置 OpenVZ

经常有人问到 OpenVZ 和 Xen 哪个好,事实上 OpenVZ 和 Xen 不是同一层面的技术,OpenVZ 是操作系统层面(Operating system-level virtualization)的虚拟产品,和 FreeBSD Jail, Solaris Zone, Linux-VServer 等类似;而 Xen 和 VMware, KVM, Hyper-V 等产品站在同一阵营。OpenVZ VPS 实际上提供的是一个虚拟环境(Virtual Environment/VE),也叫容器(Container);而 Xen VPS 提供的是基于 Hypervisor 的虚拟机(Virtual Machine),这是本质上的不同,现在大家已经习惯用 VPS 这个名字把这两种不同的产品和技术混为一谈了。比起 Xen 专注于企业虚拟化和云计算领域,OpenVZ 最大的应用可能就在低端 VPS 市场,有无数的 VPS 服务商都使用 OpenVZ 提供10美元以下的 VPS 产品。了解一下 OpenVZ 的安装和配置也会对使用 OpenVZ VPS 有所帮助,以下的安装和配置操作在 VPSee 的一台空闲 PC 和 CentOS 5.5 上完成。对 Xen 和 KVM 感兴趣的童鞋请看:在 CentOS 上安装和配置 Xen在 CentOS 上安装和配置 KVM.

安装 OpenVZ

首先加入 openvz 源、升级系统、安装 openvz 内核和 vzctl, vzquota 等工具:

# cd /etc/yum.repos.d
# wget http://download.openvz.org/openvz.repo
# rpm --import http://download.openvz.org/RPM-GPG-Key-OpenVZ
# yum update

# yum install ovzkernel
# yum install vzctl vzquota

调整内核参数

为了能让 VE/VPS 访问外部网络,我们必须启动 ip forwarding;如果内核出错或者运行很慢,我们希望能用特殊按键 dump 一些信息到控制台并结合 log 排错,所以建议打开 kernel.sysrq:

# vi /etc/sysctl.conf
...
net.ipv4.ip_forward = 1
kernel.sysrq = 1
...

为了减少麻烦最好关闭 selinux,selinux 带来的麻烦往往比得到的好处多:

# vi /etc/sysconfig/selinux
...
SELINUX=disabled
...

检查 vz 服务是否自动启动,并重启机器进入 openvz 内核:

# chkconfig --list vz 
vz             	0:off	1:off	2:on	3:on	4:on	5:on	6:off

# reboot

创建和安装 guest

Perl 语言之父 Larry Wall 说过真正优秀的程序员有三大优良品质:偷懒,没有耐性和骄傲自大。所以能利用别人的劳动成果就不要自己重造轮子。我们可以到 http://download.openvz.org/template/precreated/ 下载已经安装好的模版,有 centos, debian, ubuntu, fedora, suse 等几个模版可以选择:

# cd /vz/template/cache
# wget http://download.openvz.org/template/precreated/ubuntu-10.04-x86.tar.gz

有了 ubuntu 10.04 的模版以后就可以用这个模版来创建 guest 系统(VE/VPS)了,以刚下载的 ubuntu-10.04-x86 为模版创建一个 ID 为 1 的 Virtual Environment (VE),并指定 IP 地址、DNS 服务器地址、主机名、磁盘空间等,创建成功后启动 ID 为 1 的 VE,最后修改 root 密码:

# vzctl create 1 --ostemplate ubuntu-10.04-x86

# vzctl set 1 --onboot yes --save
# vzctl set 1 --ipadd 172.16.39.110 --save
# vzctl set 1 --nameserver 8.8.8.8 --save
# vzctl set 1 --hostname vps01.vpsee.com --save
# vzctl set 1 --diskspace 10G:10G --save

# vzctl start 1
# vzctl exec 1 passwd

启动、重启、关闭和断电关闭 ID 为 1 的 VE/VPS:

# vzctl start 1
# vzctl restart 1
# vzctl stop 1
# vzctl destroy 1

查看正在运行中的 VE/VPS:

# vzlist
      CTID      NPROC STATUS    IP_ADDR         HOSTNAME
         1          8 running   172.16.39.110   vps01.vpsee.com

计算 ID 为 1 的 VE/VPS 用到的资源:

# vzcalc -v 1
Resource     Current(%)  Promised(%)  Max(%)
Low Mem          0.06       1.44       1.44
Total RAM        0.19        n/a        n/a 
Mem + Swap       0.08       1.30        n/a
Alloc. Mem       0.11       1.62       3.09
Num. Proc        0.01        n/a       0.32
--------------------------------------------
Memory           0.19       1.62       3.09

进入 guest

VE 成功启动后就可以进入系统了,相当于 xen 的 xm console,不过从 VE 退出来不需特殊按键直接 exit 就可以:

# vzctl enter 1
entered into CT 1
root@vps01:/# exit
logout
exited from CT 1

CentOS 5.5 上升级 Xen 后遇到的一个问题

前几天用 CentOS 5.5 官方源升级我们的一台 Xen 服务器的时候发现一个问题,升级后的 xen 内核和 xend 服务都能正常启动,但是 xm 这类工具用不了:

# uname -a
Linux n46.xen.vpsee.com 2.6.18-194.32.1.el5xen #1 SMP Wed Jan 5 18:44:24 EST 2011 x86_64 x86_64 x86_64 GNU/Linux

# /etc/init.d/xend status
xend is running

# xm list
Error: Unable to connect to xend: No such file or directory. Is xend running?

检查 xen 日志报错如下:

# vi /var/log/xen/xend.log
[2011-01-14 09:54:38 4664] INFO (SrvDaemon:332) Xend Daemon started
[2011-01-14 09:54:38 4664] INFO (SrvDaemon:336) Xend changeset: unavailable.
[2011-01-14 09:54:38 4664] ERROR (SrvDaemon:349) Exception starting xend ((13, 'Permission denied'))
Traceback (most recent call last):
  File "/usr/lib64/python2.4/site-packages/xen/xend/server/SrvDaemon.py", line 341, in run
...
  File "/usr/lib64/python2.4/site-packages/xen/xend/XendNode.py", line 871, in xenschedinfo
    sched_id = self.xc.sched_id_get()
Error: (13, 'Permission denied')

这种 xen/xend 正常,xm 不能用的情况很明显是 xen hypervisor 和 xen tools 之间的匹配问题。这是因为 VPSee 以前用 CentOS 的非官方源升级到了 Xen 3.4.3,造成以前升级的 xen tools 和上面刚刚官方升级的 xen hypervisor 不匹配,所以需要把 /boot/grub/menu.lst 里面刚升级成功的的 kernel /xen.gz-2.6.18-194.32.1.el5 换成原来的 kernel /xen.gz-3.4.3,然后重启一下就可以了:

# vi /boot/grub/menu.lst
title CentOS (2.6.18-194.32.1.el5xen)
        root (hd0,0)
        kernel /xen.gz-3.4.3
        module /vmlinuz-2.6.18-194.32.1.el5xen ro root=LABEL=/
        module /initrd-2.6.18-194.32.1.el5xen.img

如何判断 Linux 是否运行在虚拟机上

在 WebHostingTalk 论坛上有些国外奸商会把虚拟机当作独立服务器卖,去年7月份的时候就有一位中国同胞上当受骗,并在 WHT 上发帖声讨,证据确凿,甚至连服务商自己也承认,回帖达355篇。这家独立服务器/VPS 提供商 HostATree.com 居然大胆的把 OpenVZ VPS 这种一看就知道是虚拟机的虚拟机当作独立服务器卖,晕,至少也要弄个 VMWare/KVM/Xen HVM 吧(更难发现是虚拟机),用 OpenVZ 这种容器也太欺负人了:)昨天恰好收到网友一封邮件问到了如何判断自己买的是独立服务器还是虚拟机的问题。这里 VPSee 简单介绍一下市面上常用虚拟技术(包括容器技术)的判别小技巧。

判断 OpenVZ/Xen PV/UML

判断 OpenVZ/Xen PV/UML 是最容易的,直接检查 /proc 下的相关目录和文件就可以知道,比如 OpenVZ VPS 上会有 /proc/vz 这个文件;Xen PV 虚拟机上会有 /proc/xen/ 这个目录,并且目录下有一些东西;UML 上打印 /proc/cpuinfo 会找到 UML 标志。写了一个简单的 Python 脚本来检测:

#!/usr/bin/python
# check if a linux system running on a virtual machine (openvz/xen pv/uml)
# written by http://www.vpsee.com

import sys, os

def main():
    if os.getuid() != 0:
        print "must be run as root"
        sys.exit(0)

    # check OpenVZ/Virtuozzo
    if os.path.exists("/proc/vz"):
        if not os.path.exists("/proc/bc"):
            print "openvz container"
        else:
            print "openvz node"

    # check Xen
    if os.path.exists("/proc/xen/capabilities"):
        if (os.path.getsize("/proc/xen/capabilities") > 0):
            print "xen dom0"
        else:
            print "xen domU"

    # check User Mode Linux (UML)
    f = open("/proc/cpuinfo", "r"); t = f.read(); f.close()
    if (t.find("UML") > 0):
        print "uml"

if __name__=="__main__":
    main()

判断 VMware/Xen HVM/KVM

如果使用的是 VMware/Xen HVM/KVM 这样的全虚拟就更难判断一些,最准确的办法是读取 CPUID 来判断,Xen 源代码下面有一段检测是否是 Xen 的 C 语言代码 tools/misc/xen-detect.c,这段代码提供了一个很好的例子,VPSee 重写了代码,用宏替代了函数,增加了对 VMware 和 KVM 的识别,用 gcc 编译后就可以运行:

/*
 * check if a linux system running on a virtual machine (vmware/xen hvm/kvm)
 * written by http://www.vpsee.com
 */
#include <stdio.h>
#include <string.h>

#define HYPERVISOR_INFO 0x40000000

#define CPUID(idx, eax, ebx, ecx, edx) \
    asm volatile ( \
        "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid" \
        : "=b" (*ebx), "=a" (*eax), "=c" (*ecx), "=d" (*edx) \
        : "0" (idx) );

int main(void)
{
        unsigned int eax, ebx, ecx, edx;
        char string[13];

        CPUID(HYPERVISOR_INFO, &eax, &ebx, &ecx, &edx);
        *(unsigned int *)(string+0) = ebx;
        *(unsigned int *)(string+4) = ecx;
        *(unsigned int *)(string+8) = edx;

        string[12] = 0;
        if (strncmp(string, "XenVMMXenVMM", 12) == 0) {
                printf("xen hvm\n");
        } else if (strncmp(string, "VMwareVMware", 12) == 0) {
                printf("vmware\n");
        } else if (strncmp(string, "KVMKVMKVM", 12) == 0) {
                printf("kvm\n");
        } else
                printf("bare hardware\n");

        return 0;
}

判断 VirtualBox/Virtual PC

什么?这种家用桌面虚拟机自己装的还会不知道?!如果不知道的话也有办法,在 Linux 下运行 dmidecode 工具然后查找 Manufacturer: innotek GmbH, Manufacturer: Microsoft Corporation 关键字就能对应上 VirtualBox 和 Virtual PC.