安装和试玩 RethinkDB

最近一个项目要用到文档数据库,顺便查了一下 NoSQL 方面的资料。当前几个比较流行的文档数据库引擎有 MongoDB, CouchDB, Couchbase, OrientDB 等,朋友推荐的是 MongoDB 和 RethinkDB,和 MongoDB 类似 RethinkDB 是一个主要用来存储 JSON 文档的数据库引擎(MongoDB 存储的是 BSON),可以轻松和多个节点连成分布式数据库,非常好用的查询语言以及支持表的 joins 和 group by 操作等。

昨天试玩了一下 RethinkDB,在一台虚拟机上测试,插入2500万行记录性能表现很一般,远没有 MongoDB 和 Couchbase 快,不过还算稳定,维持在 1.5K 行到 2K 行每秒之间,RethinkDB 的数据分片(sharding)功能非常简单,一个点击就可以完成。下面的安装和测试在 Ubuntu 12.04.4 LTS Server 版本上完成。

加入 RethinkDB 官方源后安装:

$ sudo apt-get install python-software-properties

$ sudo add-apt-repository ppa:rethinkdb/ppa

$ sudo apt-get update
$ sudo apt-get install rethinkdb

拷贝一个例子配置文件后修改 bind 部分以便可以从其他机器访问:

$ cd /etc/rethinkdb/
$ sudo cp default.conf.sample instances.d/default.conf

$ sudo vi instances.d/default.conf
...
# bind=127.0.0.1
bind=0.0.0.0
...

启动 rethinkdb:

$ sudo /etc/init.d/rethinkdb start
rethinkdb: default: Starting instance. (logging to `/var/lib/rethinkdb/default/data/log_file')

访问 http://192.168.2.39:8080/ 就可以看到 rethinkdb 的管理界面了:

RethinkDB

如果不喜欢在命令行工作,web 界面还提供了 Data Explorer 在线查询工具,支持语法高亮、在线函数提示等,不用额外查帮助文件。

RethinkDB

要用程序的方式和 rethinkdb 打交道的话就需要安装客户端驱动(client drivers),官方支持的驱动有 JavaScript, Ruby 和 Python 3种语言,社区支持的驱动几乎包括了 C, Go, C++, Java, PHP, Perl, Clojure, Erlang 等所有主流编程语言。本人用 Python 多一些,所以这里安装 Python 客户端驱动:

$ sudo apt-get install python-pip
$ sudo pip install rethinkdb

测试一下驱动是否能工作了,如果 import rethinkdb 没有出错基本就可以说明模块安装成功:

$ python
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import rethinkdb
>>>

gene2go.txt 是一个含有基因数据的文本文件,大概1000多万行记录,格式如下:

$ head -2 gene2go.txt
#Format: tax_id GeneID GO_ID Evidence Qualifier GO_term PubMed Category (tab is used as a separator, pound sign - start of a comment)
3702	814629	GO:0005634	ISM	-	nucleus	-	Component

写个简单程序把 gene2go.txt 的数据导入到 rethinkdb 里:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os, os.path, sys, re, csv, string

def csv2db():
    data = csv.reader(open('gene2go.txt', 'rb'), delimiter='\t')
    data.next()

    import rethinkdb as r
    r.connect('localhost', 28015).repl()
    r.db('test').table_create('gene2go').run()
    gene2go = r.db('test').table('gene2go')
    for row in data:
        gene2go.insert({
            'tax_id': row[0],
            'GeneID': row[1],
            'GO_ID': row[2],
            'Evidence': row[3],
            'Qualifier': row[4],
            'GO_term': row[5],
            'PubMed': row[6],
            'Category': row[7]
        }).run(durability="soft", noreply=True)

def main():
    csv2db()

if __name__ == "__main__":
    main()

在 Ubuntu 上搭建 Ghost 博客平台

Ghost 是一款开源的博客平台,基于 Node.js,由前 WordPress UI 主管 John O’Nolan 和 WordPress 开发人员 Hannah Wolfe 创立。网上的开源博客程序众多,去年刚上线的 Ghost 来势汹汹正迅速捕获用户,0.4.1 这么早期的版本就让 Coding Horror 拥抱了 Ghost。Ghost 主题/模版越来越多,一些优秀的 WordPress 主题商,比如 WooThemes 都开始提供 Ghost 主题了

安装 Ghost 非常容易,甚至比 WordPress 还简单。下面的安装步骤在 Ubuntu 12.04.4 LTS Server 版本上测试通过。

切换到 root 账号升级和更新整个系统:

$ sudo -i

# apt-get update
# apt-get upgrade

安装 Node.js 运行环境:

# apt-get install g++ make python python-software-properties
# add-apt-repository ppa:chris-lea/node.js
# apt-get update
# apt-get install nodejs

下载、解压 Ghost 后安装:

# cd
# wget https://ghost.org/zip/ghost-0.4.1.zip
# unzip ghost-0.4.1.zip -d ghost
# cd ghost
# npm install --production

配置 Ghost 使其监听本机上的所有 IP,修改 ‘127.0.0.1’ 为 ‘0.0.0.0’:

# vi config.js
...
       server: {
            // Host to be passed to node's `net.Server#listen()`
            host: '0.0.0.0',
            // Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
            port: '2368'
        }
...

使用 npm 启动 Ghost 程序:

# npm start

> ghost@0.4.1 start /root/ghost
> node index

Ghost is running in development...
Listening on 0.0.0.0:2368
Url configured as: http://my-ghost-blog.com

Ghost 的默认端口是 2368,打开浏览器访问 http://192.168.2.178:2368 就可以看到界面了:

Ghost

登录后台访问 http://192.168.2.178:2368/admin 地址:

Ghost

Ghost 是独立程序,在 nodejs 环境下可以直接运行,在 config.js 文件里修改 Ghost 的监听端口 2366 为 80 就可以了,不过在生产环境我们一般在前端加个 Nginx.

安装和配置 Nginx:

# apt-get install nginx
# rm /etc/nginx/sites-enabled/default

# vi /etc/nginx/sites-available/ghost
server {
    listen 0.0.0.0:80;
    server_name vpsee.com;
    access_log /var/log/nginx/vpsee.com.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header HOST $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://127.0.0.1:2368;
        proxy_redirect off;
    }
}

# ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/ghost

# /etc/init.d/nginx restart

Nginx 接到请求后会 pass 给(proxy_pass)Ghost 服务程序,这时候最好把刚才测试用的 Ghost 配置修改还原成 ‘127.0.0.1’,修改后记得重启 Ghost:

# vi config.js
...
            // Host to be passed to node's `net.Server#listen()`
            host: '127.0.0.1',
...

每次 npm start 太麻烦,为了 Ghost 程序在系统启动后能自动运行,需要加入脚本到 Upstart 里:

# vi /etc/init/ghost.conf
start on startup

script
    cd /root/ghost
    npm start
end script

以后需要启动、重启或者停止 Ghost 就可以用 service ghost start/restart/stop 了:

# service ghost restart
ghost stop/waiting
ghost start/running, process 11619

相比 WordPress 的臃肿 Ghost 要轻爽得多。通过 Markdown 格式、Node.js 的实时和漂亮的界面,Ghost 给用户提供了一种更简单、更纯粹的内容写作发布方式。左边是编辑文章,右边是实时预览:

Ghost

网站日志实时分析工具 GoAccess

GoAccess 是一款开源的网站日志实时分析工具。GoAccess 的工作方式很容易理解,就是读取和解析 Apache/Nginx/Lighttpd 的访问日志文件 access log,然后以更友好的方式把统计信息显示出来。统计的内容包括:访问概况、动态页面请求、静态页面请求(如图片、样式表、脚本等)、访客排名,访客使用的操作系统,访客使用的浏览器,来路域名,404 错误,搜索爬虫,搜索关键词等等。

GoAccess 的性能也不赖,据官方测试,在一台 Intel Xeon CPU @ 2.40ghz CPU, 2GB 内存的机器上处理日志文件的速度是97000行每秒。

Linux 发行版本自带的 GoAccess 一般太老,比如 Ubuntu 12.04 带的是 0.4.2,Ubuntu 13.10 带的是 0.5,而最新的 goaccess 版本是 0.7.1. 所以类似不常用的软件,Linux 发行官方关注也少,为了使用最新的版本,最好采用源代码安装的方式。

在 CentOS 6.5 上安装编译 GoAccess 时需要的工具和库:

# yum groupinstall 'Development Tools'
# yum install glib2 glib2-devel ncurses-devel

在 Ubuntu 12.04 上安装编译 GoAccess 时需要的工具和库:

$ sudo apt-get install build-essential
$ sudo apt-get install libglib2.0-dev libncursesw5-dev

下载 GoAccess 的源代码、编译和安装:

$ wget http://downloads.sourceforge.net/project/goaccess/0.7.1/goaccess-0.7.1.tar.gz
$ tar -xzvf goaccess-0.7.1.tar.gz
$ cd goaccess-0.7.1/
$ ./configure --enable-utf8
$ make
$ sudo make install

运行 GoAccess,选择 NCSA Combined Log Format:

$ /usr/local/bin/goaccess -f /var/log/apache2/access.log


                  +--------------------------------------------------+
                  | Log Format Configuration                         |
                  | [SPACE] to toggle - [ENTER] to proceed           |
                  |                                                  |
                  | [ ] Common Log Format (CLF)                      |
                  | [ ] Common Log Format (CLF) with Virtual Host    |
                  | [x] NCSA Combined Log Format                     |
                  | [ ] NCSA Combined Log Format with Virtual Host   |
                  | [ ] W3C                                          |
                  | [ ] CloudFront (Download Distribution)           |
                  |                                                  |
                  | Log Format - [c] to add/edit format              |
                  | %h %^[%d:%^] "%r" %s %b "%R" "%u"                |
                  |                                                  |
                  | Date Format - [d] to add/edit format             |
                  | %d/%b/%Y                                         |
                  +--------------------------------------------------+

界面如下:

GoAccess

GoAccess 还可以生成 HTML 格式的报告

$ /usr/local/bin/goaccess -f /var/log/apache2/access.log -a > report.html

GoAccess

迁移 KVM/VMware 虚拟机或物理机到 Xen PV 虚拟机

使用 KVM, VMware, XenServer/Xen HVM 这些全虚拟技术的虚拟机之间相互转化比较容易,有的转化一下虚拟机镜像文件的格式就可以了,有的可以借助一些免费的自动转化工具如 VMware vCenter Converter 等。今天要说的是全虚拟机(HVM)或物理机到半虚拟机(PV)的转化,稍微麻烦点。

HVM 到 PV 的转化思路是这样的:

1、把整个系统打包后拷贝到 Xen 服务器;
2、在 Xen 服务器上新建一个磁盘文件,把原系统解压到这个 “磁盘” 里;
3、挂载磁盘,并利用 chroot 更换原系统的内核为支持 Xen 的内核;
4、更改原系统的几个必要文件。

下面的操作是迁移一台 Ubuntu 12.04 物理服务器到 Xen PV 虚拟机,其方法也适用于其他的版本的 Linux.

首先登录到要转化的系统上,用 tar 把整个根文件系统打包,最好关闭系统后挂载硬盘到另一台机器上离线打包,如果一定要给一个正在运行的 Linux 系统在线打包的话务必停止一切服务后(如 Apach, MySQL 等)再执行打包,尽量减少打包过程中造成的数据不一致。给一个在线系统打包需要除去一些系统运行时目录如 /proc, /sys 等:

# tar -cvpzf test.tar.gz --exclude=/test.tar.gz --exclude=/sys --exclude=/dev --exclude=/proc /

把打包好的压缩包传到 Xen 母机上,然后在母机上创建一个磁盘镜像文件、格式化、挂载这个磁盘镜像到 /mnt,最后把压缩包的内容解压(细节可以参考 如何快速创建 Xen 虚拟机镜像):

# dd if=/dev/zero of=test.img bs=1 count=1 seek=10G
# mkfs.ext3 test.img
# mount -o loop test.img /mnt

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

创建一些系统运行时需要的目录,然后 chroot:

# mkdir /mnt/proc
# mkdir /mnt/sys
# mkdir /mnt/dev
# mkdir /mnt/dev/pts
# mount -t proc proc /mnt/proc/
# mount -t sysfs sys /mnt/sys/
# mount -o bind /dev /mnt/dev/
# mount -o bind /dev/pts /mnt/dev/pts/

# chroot /mnt

特别的 Xen 需要特别的内核,所以我们需要给原 Linux 系统换内核,chroot 后更新系统并安装 linux-virtual 内核,当然,不要忘了更新 grub:

# apt-get update & apt-get upgrade

# apt-get install linux-virtual
# apt-get purge grub2 grub-pc
# apt-get install grub
# update-grub

换了内核后还需要更新和配置几个系统文件,menu.lst, fstab, hvc0.conf,以便新内核能在 Xen 虚拟环境里正常启动:

# vi /boot/grub/menu.lst
...
# kopt=root=UUID=4da51cdc-c6e9-42a2-b3c8-6056f334a124 ro
kopt=root=/dev/xvda console=hvc0 ro quiet
...

# update-grub
# vi /mnt/etc/fstab
proc         /proc    proc    defaults                     0    0
/dev/xvda    /        ext3    noatime,errors=remount-ro    0    1
/dev/xvdb    none     swap    sw                           0    0
# vi /etc/init/hvc0.conf
# hvc0 - getty
#
# This service maintains a getty on hvc0 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]

respawn
exec /sbin/getty -8 38400 hvc0

基本上搞定了,退出 chroot 后记得按逆顺序卸载刚才挂载的目录:

# umount /mnt/proc/
# umount /mnt/sys/
# umount /mnt/dev/pts/
# umount /mnt/dev/
# umount /mnt/

创建一个 Xen 虚拟机配置文件,用 xm create 启动虚拟机:

# vi /etc/xen/test
bootloader = "/usr/bin/pygrub"
root = "/dev/xvda ro"
name = "test"
vcpus = "1"
memory = "2048"
disk = [ "file:/root/test.img,xvda,w","file:/root/test.swp,xvdb,w" ]
vif = [ "bridge=xenbr0" ]

# xm create test

在 Linux 上创建 Software RAID 10

昨天重装一台老服务器的时候发现 Intel hardware RAID 控制卡有问题,不能识别所有硬盘,但是安装操作系统过程中可以识别所有硬盘,还有一个问题就是操作系统安装正常,但是安装完后无法启动,某种原因导致 BIOS 不能从硬盘启动系统。所以打算把操作系统安装到一个 USB 盘上,然后从 USB 盘启动系统,并给上面的6块硬盘做成 Software RAID 10 后挂载到系统里用。

做 Software RAID 不要求硬盘都一模一样,但是强烈推荐用同一厂商、型号和大小的硬盘。为啥 RAID 10,不选 RAID0, RAID1, RAID5 呢?答:RAID0 太危险,RAID1 性能稍逊一些,RAID5 频繁写情况下性能差,RAID10 似乎是当今磁盘阵列的最佳选择,特别适合做 KVM/Xen/VMware 虚拟机母机(host)的本地存储系统(如果不考虑 SAN 和分布式存储的话)。

这台服务器上有6块完全相同的硬盘,给每块硬盘分成一个区,分区格式为 Linux software raid:

# fdisk /dev/sda

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-91201, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-91201, default 91201):
Using default value 91201

Command (m for help): p

Disk /dev/sda: 750.2 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0005c259

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1       91201   732572001   83  Linux

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): fd
Changed system type of partition 1 to fd (Linux raid autodetect)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

按照上面的 /dev/sda 的分区例子依次给剩下的5块硬盘 sdc, sdd, sde, sdf, sdg 分区、更改分区格式:

# fdisk /dev/sdc
...
# fdisk /dev/sdd
...
# fdisk /dev/sde
...
# fdisk /dev/sdf
...
# fdisk /dev/sdg
...

分区完成后就可以开始创建 RAID 了,在上面的6个相同大小的分区上创建 raid10:

# mdadm --create /dev/md0 -v --raid-devices=6 --level=raid10 /dev/sda1 /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1 /dev/sdg1
mdadm: layout defaults to n2
mdadm: layout defaults to n2
mdadm: chunk size defaults to 512K
mdadm: size set to 732440576K
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

查看磁盘阵列的初始化过程(build),根据磁盘大小和速度,整个过程大概需要几个小时:

# watch cat /proc/mdstat
Every 2.0s: cat /proc/mdstat                                       Tue Feb 11 12:51:25 2014

Personalities : [raid10]
md0 : active raid10 sdg1[5] sdf1[4] sde1[3] sdd1[2] sdc1[1] sda1[0]
      2197321728 blocks super 1.2 512K chunks 2 near-copies [6/6] [UUUUUU]
      [>....................]  resync =  0.2% (5826816/2197321728) finish=278.9min speed=13
0948K/sec

unused devices: 

等阵列完成初始化后,就可以给 md0 设备创建分区和文件系统了,有了文件系统就可以挂载到系统里:

# fdisk /dev/md0
# mkfs.ext4 /dev/md0p1

# mkdir /raid10
# mount /dev/md0p1 /raid10

修改 /etc/fstab 文件让每次系统启动时自动挂载:

# vi /etc/fstab
...
/dev/md0p1 /raid10 ext4 noatime,rw 0 0

在上面的 /etc/fstab 文件里使用 /dev/md0p1 设备名不是一个好办法,因为 udev 的缘故,这个设备名常在重启系统后变化,所以最好用 UUID,使用 blkid 命令找到相应分区的 UUID:

# blkid
...
/dev/md0p1: UUID="093e0605-1fa2-4279-99b2-746c70b78f1b" TYPE="ext4"

然后修改相应的 fstab,使用 UUID 挂载:

# vi /etc/fstab
...
#/dev/md0p1 /raid10 ext4 noatime,rw 0 0
UUID=093e0605-1fa2-4279-99b2-746c70b78f1b /raid10 ext4 noatime,rw 0 0

查看 RAID 的情况:

# mdadm --query --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Tue Feb 11 12:50:38 2014
     Raid Level : raid10
     Array Size : 2197321728 (2095.53 GiB 2250.06 GB)
  Used Dev Size : 732440576 (698.51 GiB 750.02 GB)
   Raid Devices : 6
  Total Devices : 6
    Persistence : Superblock is persistent

    Update Time : Tue Feb 11 18:48:10 2014
          State : clean
 Active Devices : 6
Working Devices : 6
 Failed Devices : 0
  Spare Devices : 0

         Layout : near=2
     Chunk Size : 512K

           Name : local:0  (local to host local)
           UUID : e3044b6c:5ab972ea:8e742b70:3f766a11
         Events : 70

    Number   Major   Minor   RaidDevice State
       0       8        1        0      active sync   /dev/sda1
       1       8       33        1      active sync   /dev/sdc1
       2       8       49        2      active sync   /dev/sdd1
       3       8       65        3      active sync   /dev/sde1
       4       8       81        4      active sync   /dev/sdf1
       5       8       97        5      active sync   /dev/sdg1

发布一款 Android 文本阅读器:TxtReader

几年前玩 Android 练手的时候开发了一款文本阅读器,主要是因为那个时候好用的文本阅读器几乎没有,仅有的几个要么是内嵌广告,要么就是臃肿肥,那个时候 Android 硬件配置不高,开一个臃肿肥的 app 看一个 10MB 左右的文本文件经常会程序崩溃(一些 app 没有考虑大文件情况,企图打开文件的时候一次性把内容读出来)。总之吧,当时的情况是本人需要一款轻量级、支持大文件的简单、好用的文本阅读器,顺便找个机会学一下 Android 编程~

后来放到 Android Market(现在叫 Google Play)后就没怎么管,默默的、无任何宣传的情况下今天惊讶的发现居然有 5000-10000 的装机量。这里顺便广告一下:

TxtReader 是一款轻量级的免费文本阅读器,只支持 txt 格式。简单介绍一下特点:

  • 支持自动识别编码(中文简体、中文繁体、英文、日文、韩文),不需要手动设置;
  • 支持自动书签,能自动记住阅读位置,启动软件后能自动从上次关闭的地方开始阅读;
  • 支持大文本文件阅读,不会出现文件太大打不开的情况;
  • 支持多语言菜单设置,可选中文、英文、日文;
  • 免费、绿色、小巧、简单,不侵犯隐私,没有垃圾广告,不打扰别人

TxtReader for Android

关闭 Mac 上的虚拟内存

MacBook Pro with Retina display 的标配内存是8GB,这个内存足够日常使用了,考虑到 SSD 硬盘寿命的问题,建议关闭系统的虚拟内存(Swap),避免频繁写入。关闭系统 swap 还可以提高性能(参考 Linux 性能监测:MemoryLinux 性能监测:IO 的 swap 部分)。

查看当前正在使用的虚拟内存:

$ sysctl vm.swapusage
vm.swapusage: total = 1024.00M  used = 354.50M  free = 669.50M  (encrypted)

关闭虚拟内存以后,系统里还保留着这些用作虚拟内存的交换文件,可以删除:

$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist

$ sudo rm /private/var/vm/swapfile*

用了一段时间还没有遇到系统不稳定问题,如果发现系统不稳的话可以重新开启虚拟内存:

$ sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist

在 CentOS 6.5 上安装和配置 Xen

长假回来工作的第一周有点不适应,还在找状态。。。这周把一些老的 Xen 服务器(CentOS 5.2 + Xen 3.1)升级到了 CentOS 6.5 + Xen 4.2,顺便记录一下。

自从 RedHat 在 RHEL 6 放弃 Xen 后,下载 Xen 源码编译安装似乎是在 RHEL/CentOS 6.x 上安装 Xen 的唯一办法。不过,开源世界永远不缺少热情的志愿者,Xen Made Easy 这个项目为我们提供了可用的 Xen 第三方软件源,免去了自己编译源码的痛苦。现在,我们有了更好的官方选择,就是 Xen4CentOS6. Xen4CentOS6 是来自 CentOS, Xen, Citrix, Godaddy, Rackspace 社区和相关团队合作开发的一个开源项目,旨在为 CentOS 6.x 维护一个稳定的 Xen 工具链(Xen hypervisor 和相关 Xen 工具),让 Xen 运行在 CentOS 6 上变得更容易,更可靠。

安装

升级整个系统后重启,然后加入 CentOS 官方 Xen 源(Xen4CentOS6)并安装 Xen 内核及相关工具。需要注意的是,采用 CentOS-6.5-x86_64-minimal.iso 最小化安装的系统没有包括 Perl,Xen 工具需要 Perl 的支持,所以需要安装 perl 先:

# yum update
# reboot

# yum install centos-release-xen
# yum update

# yum install perl
# yum install xen

安装完支持 Xen 的 Linux 内核后需要加新条目到 grub.conf,以便系统能默认启动带 Xen 的 Linux 内核(而不是常规 Linux 内核),这个操作可以通过 grub-bootxen.sh 自动完成,弄完后打开 grub.conf 文件再次确认一下:

# /usr/bin/grub-bootxen.sh

# vi /etc/grub.conf
...
title CentOS (3.10.25-11.el6.centos.alt.x86_64)
        root (hd0,0)
        kernel /xen.gz dom0_mem=1024M,max:1024M loglvl=all guest_loglvl=all
        module /vmlinuz-3.10.25-11.el6.centos.alt.x86_64 ro root=/dev/mapper/vg_node11-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=vg_node11/lv_swap  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rd_LVM_LV=vg_node11/lv_root rhgb quiet
        module /initramfs-3.10.25-11.el6.centos.alt.x86_64.img
...

重启系统后,默认应该进入 Xen 内核,可以通过 uname -r 和 xm info 确认是否安装成功:

# reboot

# uname -r
3.10.25-11.el6.centos.alt.x86_64

# xm info
host                   : xen01.vpsee.com
release                : 3.10.25-11.el6.centos.alt.x86_64
version                : #1 SMP Fri Dec 27 21:44:15 UTC 2013
machine                : x86_64
nr_cpus                : 8
nr_nodes               : 1
cores_per_socket       : 4
threads_per_core       : 1
cpu_mhz                : 2393
hw_caps                : 1febfbff:28100800:00000000:00003f40:80982201:00000000:00000001:00000000
virt_caps              :
total_memory           : 8191
free_memory            : 7073
free_cpus              : 0
xen_major              : 4
xen_minor              : 2
xen_extra              : .3-26.el6
xen_caps               : xen-3.0-x86_64 xen-3.0-x86_32p
xen_scheduler          : credit
xen_pagesize           : 4096
platform_params        : virt_start=0xffff800000000000
xen_changeset          : unavailable
xen_commandline        : dom0_mem=1024M,max:1024M loglvl=all guest_loglvl=all
cc_compiler            : gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
cc_compile_by          : mockbuild
cc_compile_domain      : centos.org
cc_compile_date        : Tue Dec 10 20:32:58 UTC 2013
xend_config_format     : 4

资源

CentOS 5.x 版本可以参看:在 CentOS 5.x 上安装和配置 Xen
Ubuntu 版本可以参看:在 Ubuntu 上安装和配置 Xen
Debian 版本参看:在 Debian 上安装和配置 Xen
OpenSolaris 版本参看:在 OpenSolaris 上安装和配置 Xen
NetBSD 版本参看:在 NetBSD 上安装和配置 Xen.

Merry Christmas & a prosperous 2014

Merry Christmas and a prosperous 2014

在 CentOS 6.4 上安装 CloudStack 4.2

又到年底,下月开始休假,所以这周基本上算今年 “努力” 的最后一周,接下来六周都不会有技术文章更新。

和 OpenStack, OpenNebula 类似,CloudStack 是另一款开源云计算平台。CloudStack 的前身是 Cloud.com 家的一款商业云计算产品(也有开源版本),2011年 Cloud.com 被 Citrix 收购,2012年的时候 Citrix 将收购的云平台 CloudStack 全部捐给了 Apache 基金会,自己则以 Citrix CloudPlatform (powered by Apache CloudStack) 的形式为客户提供商业化的云计算解决方案。

按照《OpenStack, OpenNebula, Eucalyptus, CloudStack 社区活跃度比较》的统计,貌似 CloudStack 项目的活跃程度仅次于 OpenStack. 和大多数云计算、集群软件一样,CloudStack 也是控制节点+计算节点这种架构,控制节点(cloudstack-management)用来统一管理计算节点,提供资源分配和任务,提供 API、GUI、数据库等服务;计算节点(cloudstack-agent)则用来跑虚拟机。我们需要做的是,

  • 在控制节点上安装 cloudstack-management;
  • 在(每个)计算节点上安装 cloudstack-agent 和 kvm.

在控制节点上

安装完 CentOS 6.4 系统后,升级系统并修改 hostname 后重启:

# yum update

# echo "cloudstack.vpsee.com" > /etc/hostname

# vi /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=cloudstack.vpsee.com

# echo "192.168.2.150 cloudstack cloudstack.vpsee.com" >> /etc/hosts

# reboot

添加 cloudstack 软件包的官方源,安装 ntp, cloudstack-management, mysql 数据库服务器:

# vi /etc/yum.repos.d/cloudstack.repo
[cloudstack]
name=cloudstack
baseurl=http://cloudstack.apt-get.eu/rhel/4.2/
enabled=1
gpgcheck=0

# yum update

# yum install ntp
# yum install cloudstack-management
# yum install mysql-server

修改 mysql 配置文件,加入下面几行,启动 ntp, mysql 服务并运行 mysql_secure_installation 给 mysql 设置密码:

# vi /etc/my.cnf
...
[mysqld]
...
innodb_rollback_on_timeout=1
innodb_lock_wait_timeout=600
max_connections=350
log-bin=mysql-bin
binlog-format = 'ROW'

[mysqld_safe]
...


# service ntpd start
# chkconfig ntpd on

# service mysqld start
# chkconfig mysqld on

# mysql_secure_installation

修改 SELINUX 设置,并配置防火墙允许访问 mysql 的 3306 端口:

# vi /etc/selinux/config
...
SELINUX=permissive
...

# setenforce permissive

# vi /etc/sysconfig/iptables
...
-A INPUT -p tcp --dport 3306 -j ACCEPT
...

# service iptables restart

使用 cloudstack-setup-databases 初始化 ClouStack 数据库,完成后运行 cloudstack-setup-management:

# cloudstack-setup-databases cloud:cloud@localhost --deploy-as=root:root -i 192.168.2.150

# cloudstack-setup-management
Starting to configure CloudStack Management Server:
Configure sudoers ...         [OK]
Configure Firewall ...        [OK]
Configure CloudStack Management Server ...[OK]
CloudStack Management Server setup is Done!

控制节点应该和存储分开,这里为了方便,我们把 NFS 也装在这个控制节点上,并自己挂载自己的 NFS 分区:

# yum install nfs-utils
# mkdir -p /export/primary
# mkdir -p /export/secondary

# vi /etc/exports
/export  *(rw,async,no_root_squash,no_subtree_check)

# exportfs -a
# vi /etc/sysconfig/nfs
...
LOCKD_TCPPORT=32803
LOCKD_UDPPORT=32769
MOUNTD_PORT=892
RQUOTAD_PORT=875
STATD_PORT=662
STATD_OUTGOING_PORT=2020
...

# service rpcbind start
# service nfs start
# chkconfig nfs on
# chkconfig rpcbind on
# reboot

# mkdir -p /mnt/primary
# mkdir -p /mnt/secondary
# mount -t nfs 192.168.2.150:/export/primary /mnt/primary
# mount -t nfs 192.168.2.150:/export/secondary /mnt/secondary

修改防火墙配置,开放下面一些端口:

# vi /etc/sysconfig/iptables
...
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p udp --dport 111 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 111 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 2049 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 32803 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p udp --dport 32769 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 892 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p udp --dport 892 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 875 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p udp --dport 875 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p tcp --dport 662 -j ACCEPT
-A INPUT -s 192.168.2.0/24 -m state --state NEW -p udp --dport 662 -j ACCEPT
...

# service iptables restart
# service iptables save

创建虚拟机需要有模版,这个模版可以自己做,也可以下载官方现成的。需要注意的是,官方文档中的 /usr/lib64/cloud/common/… 路径不对,应该是 /usr/share/cloudstack-common/…:

# /usr/share/cloudstack-common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://d21ifhcun6b1t2.cloudfront.net/templates/4.2/systemvmtemplate-2013-06-12-master-kvm.qcow2.bz2 -h kvm -s -F

在计算节点上

为了保持一致,我们在计算节点上也采用 CentOS 6.4. 在每个计算节点上都需要如下的安装和配置。升级系统并修改 hostname、重启:

# yum update

# echo "cloudstack01.vpsee.com" > /etc/hostname

# vi /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=cloudstack01.vpsee.com

# echo "192.168.2.151 cloudstack01 cloudstack.vpsee.com" >> /etc/hosts

# reboot

添加 cloudstack 软件包的官方源,安装 ntp, cloudstack-agent 和 kvm:

# vi /etc/yum.repos.d/cloudstack.repo
[cloudstack]
name=cloudstack
baseurl=http://cloudstack.apt-get.eu/rhel/4.2/
enabled=1
gpgcheck=0

# yum update

# yum install ntp
# yum install cloudstack-agent
# yum install qemu-kvm

修改 libvirt 相关配置文件,去掉下面几行的注释,注意把 auth_tcp 改成 “none”,如果需要 vnc 访问的话别忘了取消 qemu.conf 里面的 vnc_listen 相关注释,重启 libvirtd 服务使配置生效:

# vi /etc/libvirt/libvirtd.conf
...
listen_tls = 0
listen_tcp = 1
tcp_port = "16509"
auth_tcp = "none"
mdns_adv = 0
...

# vi /etc/sysconfig/libvirtd
...
LIBVIRTD_ARGS="--listen"
...

# vi /etc/libvirt/qemu.conf
...
vnc_listen = "0.0.0.0"
...

# service libvirtd restart

别忘了让防火墙开放必要的端口:

# iptables -I INPUT -p tcp -m tcp --dport 22 -j ACCEPT
# iptables -I INPUT -p tcp -m tcp --dport 1798 -j ACCEPT
# iptables -I INPUT -p tcp -m tcp --dport 16509 -j ACCEPT
# iptables -I INPUT -p tcp -m tcp --dport 5900:6100 -j ACCEPT
# iptables -I INPUT -p tcp -m tcp --dport 49152:49216 -j ACCEPT
# iptables-save > /etc/sysconfig/iptables

测试

打开浏览器,访问控制节点 http://192.168.2.150:8080/client/ 就会看到登录界面,默认用户名和密码是 admin/password,登录后修改密码、做一些配置后就可以开始用了:

a docker web ui