如何在 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

在 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

如何判断 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.

几种开源虚拟产品的性能比较

周末看了一篇 Virtualization of Linux servers,这篇论文测试了当前几个主要开源虚拟产品的性能,刚好配合前段时间看的几种不同虚拟技术的隔离性能。虚拟机的性能和隔离性都是虚拟技术非常重要的性能指标,大面积测试和比较不同的产品需要消耗大量的时间和精力,这篇文章在前人的基础上较全面测试了 Linux 下不同虚拟产品的性能,涉及到的有 KQEMU、KVM、Linux-VServer、OpenVZ、VirtualBox、Xen.

测试方法

整个测试在一台 IBM/Lenovo Desktop PC 上进行,这台 PC 配有 Intel Core 2 Duo 6300 处理器,4GB 内存和 80GB SATA 硬盘。服务器(host)操作系统是 Ubuntu 7.10,内核是 2.6.22-14,虚拟机(guest)操作系统是 Ubuntu 6.10. 网络部分的测试则通过另外一台 PC 来进行。使用的测试软件和参数如下:

Kernel Build
$ make defconfig
$ date +%s.%N && make && date +%s.%N
$ make clean

Dbench
$ /usr/local/bin/dbench -t 300 -D /var/tmp 100

Netperf
$ netserver # server side
$ netperf -H # client side

Rsync
Experiment 1:
$ date +%s.%N && rsync -av ::kernel /var/tmp && date +%s.%N # client side
# where ’kernel’ is the linux-2.6.22.14 file tree (294M)
$ rm -fr /var/tmp/*
Experiment 2:
$ date +%s.%N && rsync -av ::iso /var/tmp && date +%s.%N # client side
# where ’iso’ is ubuntu-6.06.1-server-i386.iso (433M)
$ rm -fr /var/tmp/*

Dd
Experiment 1:
$ dd if=/opt/iso/ubuntu-6.06.1-server-i386.iso of=/var/tmp/out.iso
$ rm -fr /var/tmp/*
Experiment 2:
$ dd if=/dev/zero of=/dev/null count=117187560 # 117187560 = 60G

Bzip2
$ cp /opt/ubuntu-6.06.1-server-i386.iso .
$ date +%s.%N && bzip2 -9 ubuntu-6.06.1-server-i386.iso && date +%s.%N
$ rm ubuntu-6.06.1-server-i386.iso.bz2

SysBench
$ mysql> create database sbtest;
$ sysbench –test=oltp –mysql-user=root –mysql-host=localhost –debug=off prepare
$ sysbench –test=oltp –mysql-user=root –mysql-host=localhost –debug=off run

测试结果

  • kernel build:内核编译是个长时间重负荷的 CPU 处理过程,期间还会涉及到多线程处理和小文件的读写操作。使用 OS-level 和 para-virtualization 技术的虚拟产品性能较好,接近 Linux.
  • dbench:是个文件系统测试工具,用来测试文件服务器的负载,Linux-VServer 在这项测试中大比分胜出,VirtualBox 则在这项测试中不明原因的 crash,其余产品的测试结果均比 Linux 低约30%.
  • netperf:是用来测试网络性能的工具,使用 TCP 包流来测试网络数据交换的性能。这项测试中基于 QEMU 的虚拟产品性能较差,VirtualBox 在这项测试中表现较好,可能和 VirtualBox 使用一个特别的网络驱动有关。
  • rsync:也是用来测试网络。OpenVZ 最好,KVM 最差,其余几个差不多。
  • dd:用来测试磁盘 I/O 的性能,不用涉及太多的 CPU. Xen 和 KVM 性能较好,OpenVZ 明显很慢。
  • bzip2:压缩也是个重负荷 CPU 的工作,但是不用磁盘频繁 IO 操作。除了 KQEMU 和 OpenVZ 外,其余几个虚拟机性能接近 Linux.
  • sysbench:数据库服务器测试。在这个测试中,Linux-VServer 和 Xen 性能接近 Linux,而 KVM 和 OpenVZ 性能只有他们的一半。
  • scale:在最后一项也是最考验虚拟技术的 scale 测试中(sysbench at scale),Xen 表现优异,其他几个虚拟产品在虚拟机数目达到32个的时候,性能大大降低,只有 Xen 能在扩大虚拟机数目的同时保持较好的性能损失。KVM 在8个虚拟机的时候表现最好,VirtualBox 在16个的时候表现最好,其余产品在虚拟机数目达到4个的时候表现最好。

sysbench-at-scale

总的来说,Xen 除了在 dbench 文件系统测试中有点落后外,在其余所有的测试中都表现不俗,尤其是在最后的 scale 测试中表现惊艳。

几种不同虚拟技术的隔离性能

周末看了一篇 paper:Quantifying the Performance Isolation Properties of Virtualization Systems,这篇论文测试了几种不同虚拟技术的隔离性能,隔离性是虚拟机性能的重要指标,尤其是对商业 hosting,如 VPS、VDS 等来说,虚拟机能否把各个 VPS 合理的隔开并让物理机器上的每个 VPS 能按照事先约好的定义(如 CPU/RAM/DISK 等)公平而且充分的利用物理服务器资源很重要。这篇论文测试了目前市场上使用最普遍的几种虚拟技术以及相关代表产品,有代表 full virtualization 技术的 VMWare Workstation,代表 para virtualization 技术的 Xen,代表 operating system level virtualization 技术的 OpenVZ 和 Solaris Containers,提出的问题就是看看这些不同的虚拟技术和产品能不能、以及能在多大程度上隔离和保护每个物理机器上的虚拟机,比如能否保护好每个 VPS,能有效为不同 VPS 用户分割资源,不让 “不良” 用户超过计算额度、过分抢占其他用户的资源。

测试方法

这篇论文描述的实验方法是,首先确定一些 baseline 数据,然后做 stress 测试。

  1. 把1台物理机器分成4个虚拟机,每个虚拟机上运行1个 apache web server + SPECweb 2005 组合来得到 baseline 数据。
  2. 然后做 stress 测试,同样是上面的1台物理机器和4个虚拟机,也同样在运行1个 apache web server + SPECweb 2005 组合,只不过这个时候在其中1台虚拟机上增加了 stress test,来测试这个 stress 加上去以后是否对原有的虚拟机有影响、有多大影响。这样测试结果就可以和前面4台虚拟机没有 stress 测试的数据做比较。

主要测试了以下一些性能参数,以及测试每种参数用到的方法:

  • CPU Intensive:让虚拟机不停的做整数计算操作;
  • Fork Bomb:不停的 fork 进程;
  • Memory Intensive:不停的分配、使用内存,而不 free 掉内存空间;
  • Disk Intensive:用 IOzone 工具,开10个线程,每个线程不停的进行交替读写操作(iozone -i0 -i1 -r 4 -s 100M -t 10 -Rb);
  • Network Intensive (Transmit):开4个线程,每个线程不停的发送 60K 大小的 UDP 包;
  • Network Intensive (Receive):开4个线程,每个线程不停的接受 60K 大小的 UDP 包。

测试结果

测试结果如下图所示,0代表结果最好,DNR(Do Not Response) 代表最差。测试结果和理论上预料的一致,Full virtualization 技术能完全模拟一台计算机,不需要修改 guest 操作系统就可以直接在其上运行,由于其技术的优越性隔离性能最好;para virtualization 需要修改 guest 才能运行,隔离效果其次;最后是 operating system level virtualization,在操作系统层面虚拟,不能运行不同的操作系统,隔离不彻底,其隔离性能也最差。同一虚拟技术的不同产品,如 OpenVZ 和 Solaris Containers 也表现出了差异。

the performance isolation of virtualization systems

VPSee 只对 Xen 和 OpenVZ 有兴趣,这里省略了 Solaris Containers 的测试数据和图片,大家如有兴趣可参考原文。

如何查看 OpenVZ 的内存状态?

openvz

有了 VPS 以后第一件事情就是登录上去看看软硬件配置信息,操作系统版本,CPU,内存等。在 Xen 下看内存使用和在 OpenVZ 下有点不同,主要是因为它们使用的虚拟技术不同。在 Xen 的 VPS 可以用 free 得到 mem,swap,buffer 等有用信息,就和在独立机器上一样。如下面所示:

$ free
             total       used       free     shared    buffers     cached
Mem:         65704      57628       8076          0       3016      17664
-/+ buffers/cache:      36948      28756
Swap:       131064      43464      87600

不过如果是 OpenVZ VPS 主机的话,free 给出的信息不是很有用,如下面 swap,buffer,cached 显示是0:

# free
             total       used       free     shared    buffers     cached
Mem:        364544     247764     116780          0          0          0
-/+ buffers/cache:     247764     116780
Swap:            0          0          0

/proc/user_beancounters

这个时候需要查看 /proc/user_beancounters 以获得更多信息。user_beancounters 包括了 OpenVZ VPS 的系统资源分配和使用信息。下面列出我的一个 228M VPS 主机上的 user_beancounters:

继续阅读 »