2014年3月27日星期四

利用virsh和virt-install安装管理虚拟机

配置环境+构建思想:

1 宿主机采用kvm做虚拟化
2 网络采用bridge模式
3 硬盘采用lvm管理
4 根据宿主机配置,每台宿主机上分配12个计算单元,根据计算单元计算虚拟机使用的内存,cpu个数,lv数量
5 宿主机初始化的时候创建12个lvfree-XX命名的lv,假定虚拟机使用4个部署单元
6 创建虚拟机的时候,删除4个lvfree-XX,创建一个lvused-XX-4
7 根据统计lvfree-XX的个数,可以知道宿主机的剩余资源
8 虚拟机下线的时候,删除配置文件,删除lvused-XX-4,创建4个lvfree-XX

 

宿主机安装:

前期基本与普通机器安装相同,所有操作在ks的%post 阶段处理。

1 创建bonding和桥,配置:

内核启动参数加上biosdevname=0,避免将网卡识别为em

ifcfg-eth0:
DEVICE=eth0
ONBOOT=yes
MASTER=bond0
SLAVE=yes

ifcfg-bond0:
DEVICE=bond0
ONBOOT=yes
BONDING_OPTS="''"
BRIDGE=br0

ifcfg-br0:
DEVICE=br0
ONBOOT=yes
TYPE=Bridge
IPADDR=192.168.0.1
NETMASK=255.255.255.0
STP=off
DELAY=0
BRIDGING_OPTS="max_age=0 ageing_time=0"

/etc/modprobe.d/bond0.conf
alias bond0 bonding
options bond0 miimon=100 mode=1 primary=eth0

a) bonding 配置需要加入到modprobe.d 中,否则网络有问题
b) BRIDGE需要加入max-age和ageing-time的配置,否则虚拟机安装时,dhcp无法取得地址

2 创建lvm

vgcreate pool /dev/sda1
for i in `1 12`; do lvcreate -n free$i -L120G pool ; done

3 启动messagebus和libvirtd服务

 若使用默认网络配置libvirtd还依赖avahi-daemon服务,并会同时启动dnsmasq
/etc/init.d/messagebus start
/etc/init.d/libvirtd start

4 删除默认的nat网络

virsh net-destroy default
virsh net-undefine default

5 初始化 storage-pool,设置pool自动启动,pool-refresh中,lv自动转化为storage volume.

virsh pool-create-as pool logical --target /dev/pool
virsh pool-dumpxml pool >pool.xml
virsh pool-define pool.xml
virsh pool-autostart pool
virsh pool-refresh pool

6 添加virsh console支持

echo ttyS0 >>/etc/securetty

7 宿主机内核参数调整:

for i in /proc/sys/net/bridge/bridge-nf-*; do echo 0 >$i  ; done

宿主机安装完毕,重启即可。
 

虚拟机安装

假定虚拟机使用4个计算单元

1 删除lvfree,创建lvused

for i in `seq 1 4`; do  virsh vol-delete --pool pool lvfree$i  ;done
virsh vol-create-as --pool pool --name lvused-XX-4 --capacity=480G

2 virt-install

virt-install --hvm                                        #全虚拟化
--wait=-1                                                 #virt-install运行时的超时时间,不设置为-1,虚拟机安装完毕无法自动启动
--graphics vnc,listen=0.0.0.0,port=5900      #vnc设置
--virt-type=kvm                                         #虚拟化软件
--autostart                                                #宿主机启动后,虚拟机自动启动
--noautoconsole                                        #安装时候不连接console
-n guest_v1                                               # virsh list 时候显示的名字,为方便,直接设置为主机名
-r 4096                                                     #内存4G
--vcpus 8                                                  #使用 8个cpu
--disk vol=pool/lvused-XX-4,bus=virtio         #硬盘格式为storage volume,指定方式为 POOL/VOLUME,使用virtio驱动,在虚拟机中识别为vda
--mac==00:16:3e:aa:bb:cc                        #mac地址
--network bridge=br0,model=virtio              #网络采用桥接,使用virtio驱动
-l http://192.168.0.1/repo/rh62-x86-64        #指定安装源,系统会自动寻找kernel和initrd文件
-x "console=ttyS0 serial pip=192.168.1.1 phn=guest_v1 ks=http://192.168.0.1/ksconf/rh62-x86-64.cfg papp=guest" #内核额外参数,console保证可以连接;后面设置了ip,主机名,ks.cfg路径,以及ks安装的时候采用的应用配置

3 虚拟机调整/etc/adjtime 最后一行由LOCAL为UTC

虚拟机下线

删除lvused,创建lvfree

virsh destroy guest_v1
virsh undefine guest_v1
virsh vol-delete --pool pool lvused-XX-4
for i in `seq 1 4`; do  virsh vol-create-as --pool pool --name lvfree-$i --capacity=120G

其他

1 virt-install 高版本支持--clock=LOCAL参数,加此参数后,无需调整虚拟机的/etc/adjtime
2 virt-install 和 virsh加入--connect=qemu+ssh://192.168.1.2/system 后,可以通过ssh通道远程安装和管理虚拟机,除了采用ssh外,还可以采用TLS验证,原理是证书验证,需要下发server和client证书

2012年4月17日星期二

DNS 主从同步的NOTIFY机制

DNS的NOTIFY机制是主从同步使用的,master所控制的zone的序列号变动了以后,会主动通知slave更新,详情可见rfc1996 

1 过程
master slave使用 udp 53端口进行通讯,首先 master 向 slave 的udp53发送一个NOTIFY请求包,slave接收后,向master的udp53发送一个NOTIFY响应包,然后 slave 连接到 master 查询SOA信息,根据序列号判断是否请求进行IXFR传输。

2 相关配置
NOTIFY 的对象默认是有变动的zone的所有NS记录。除此之外,在bind中还通过配置also-notify 指定需要将NOTIFY请求发送到哪些服务器,这些服务器被称为 Stealth Server。bind中还有个配置选项notify,取值可以为yes,no,explicit。yes是默认选项,no表示不发送NOTIFY请求,explicit表示仅发送NOTIFY请求给also-notify中的服务器。

master如果配置了多个IP,则可以通过 notify-source 指定源IP地址。否则如果slave配置了其它的IP为自己的master,则会造成slave误以为收到了错误的NOTIFY请求而无法同步。(rfc1996 3.10)为保证安全,还可以配置allow-notify,来限制哪些master可以向本机发送NOTIFY请求。

如果使用udp进行通讯,master为了避免同时并发量太高,会间隔一段时间(60秒)再发送NOTIFY请求,如果发送请求次数超过5次,则不再向slave发送NOTIFY请求。但是在bind中,我未发现配置选项。

如果配置了多个master,这些master数据由于延时原因可能会不一致,因此slave会向发送NOTIFY请求的master进行同步。

slave 收到相同的NOTIFY请求后,在本次更新结束前,将暂缓响应其它的NOTIFY请求。

2012年4月8日星期日

shell 按行读取变量的值或者命令的输出

shell 中可以使用 while 按行读取一个文件,同时也可以使用 while 按行读取一个变量的值,或者一个命令的输出。方法有以下4种,分别是进程替换,管道,here document 和here string(来自chinaunix: http://bbs.chinaunix.net/thread-3699672-2-1.html):
  1. #! /bin/bash

  2. var=$(cat urfile)

  3. echo "Process Substitution"
  4. while read line
  5. do
  6.         echo "$line"
  7. done < <(echo "$var")

  8. echo "Pipe"
  9. echo "$var" | while read line
  10. do
  11.         echo "$line"
  12. done

  13. echo "Here Document"
  14. while read line
  15. do
  16.         echo "$line"
  17. done <<!
  18. $var
  19. !

  20. echo "Here String"
  21. while read line
  22. do
  23.         echo "$line"
  24. done <<< "$var"

  25. exit

2012年3月18日星期日

Xwindow 的相关概念

为了躲避赛门铁克的摧残,一直使用openSUSE,对桌面环境等概念都是模模糊糊的。前几天DBA要在图形界面下装oracle,不耻下问,结果我不知道他说的那个命令是神马东西(其实现在也不知道),只告诉他用VNC去搞搞。最近看了下鸟哥私房菜,把概念搞清楚了,总结一下。

X 就像http,ftp一样是个网络协议,目前的版本是11,release号是7。该协议同样具有Server和Client的概念。X Server的作用是接收客户的请求,绘制客户请求的图形,并把客户的消息传递给X Client端。即X Server的用途是绘图,具体该如何绘制,则是由X Client端提供了绘图数据。根据X Server接收请求和绘制图形这两个功能,可以清楚的看出X Server管理的是客户的输入设备(鼠标键盘)和输出设备(显示器)。所以运行在本地机器上的程序是X Server,远程服务器上的程序是X Client。

设想如下情况:用户点击了FireFox的关闭按钮之后的事情:X Server 通知 FireFox(Client端),客户点击关闭按钮了,你不打算做点神马事情?FireFox 于是开始执行退出命令,并告诉X Server,让我消失吧。于是X Server 不再显示FireFox的窗口。

再设想如下情况:用户通过ssh到远程服务器A,启动一个 X Client 程序(比如FireFox),让该程序通过网络连接到本地的X Server绘制图形;然后用户通过ssh到远程服务器B,启动一个X Client程序(比如xterm),也让该程序通过网络连接到本地的X Server绘制图形。这时,用户可以在自己的终端上同时看到A机器的FF和B机器的xterm。

X Client只提供了绘图数据,至于窗口在显示器的什么位置,X Client是完全不知道的。同时启动两个X client后,X Server 该如何排列窗口呢?这就需要Window Manage了。 最简单的Window Manage是twm。

以上是概念,openSUSE 使用的 XServer是 Xorg,配置文件在/etc/X11/xorg.conf.d,使用的WM是Kwin。X client 就很明显了,进行图形输出的程序都是X client。

可以运行 startx 启动 X server。 startx 是个shell脚本,主要用来读取 Xserver 和 X Client 的配置,然后调用 xinit 启动X server 和 X Client。读取参数的顺序:
  • X server 的参数方面:
    1. 使用 startx 后面接的参数;
    2. 若无参数,则找寻使用者HOME目录的文件,亦即 ~/.xserverrc
    3. 若无上述两者,则以 /etc/X11/xinit/xserverrc
    4. 若无上述三者,则运行 /usr/bin/X
  • X client 的参数方面:
    1. 使用 startx 后面接的参数;
    2. 若无参数,则找寻使用者家目录的文件,亦即 ~/.xinitrc
    3. 若无上述两者,则以 /etc/X11/xinit/xinitrc
    4. 若无上述三者,则运行 xterm
分析openSUSE的 /etc/X11/xinit/xserverc 文件,可以看出实际就是调用X命令来启动X Server的,只是在调用命令前,又通过读取一些文件,配置了环境变量。调用 X 启动 X Server 后,Xorg 会去读取 /etc/X11/xorg.conf 这个配置文件。单纯的 X 启动时,会看到画面漆黑,中心有个可以移动的鼠标的光标。

分析openSUSE的 /etc/X11/xinit/xinitrc 文件,可以看出最后实际调用startkde 或者 gnome-session 来启动桌面环境。

直接调用 X 命令自行启动X Server:X :1 &。:1 表示将X Server启动在哪个终端上,调用该命令后,通过切换终端可以看到一个黑色背景加一个光标。
运行 xterm -display :1 &,可以在终端上看到一个xterm,但是这个xterm没有标题栏,无法移动,可以在里面敲几个命令观察一下。
再次运行 xterm -display :1 &,可以在终端上看到一个全新的xterm,这个xterm覆盖了第一次启动的xterm,同样没有标题栏,无法移动,第一次启动的xterm找不到了。
可以通过启动一个窗口管理器(如twm)来解决此问题。运行twm -display :1 &,可以看到xterm有了标题栏,可以关闭,拖动等等。
这就是X Server,X Client 和 WM 之间的关系。

本地的 X Server 和 X Client 通过socket来通讯,因此6000端口默认是看不到开放的。

更详细的可以参考鸟哥:http://vbird.dic.ksu.edu.tw/linux_basic/0590xwindow.php



2012年3月1日星期四

主从dns服务器view中的数据利用Tsig同步

TSIG同步有两个要点,搞清楚这两个要点,就不会配置错了。
1 每个view需要match一个不同的key,并且allow-transfer中也配置此key。
2 slave的ip不能在master的任何一个view中(any这个view例外)。原因:slave在同步的时候会向master查询对应zone的SOA序列号,如果slave的ip在master中的某个view中,将导致每次查询的soa记录都是此view中的记录,而并非对应的key的view中的记录,因此可能造成无法同步数据,或者同步了其它view中的数据。
 
简单的方式可以这么做:master 的 match-clients 只有 key 而没有任何 ip。这种情况下 master 只能用来更新dns记录并传输记录,而不能作为授权 dns 或者 local dns 使用。这样就避免了在master的match-clients中配置多个诸如 !10.0.0.1 这种acl了。

EXAMPLE:

Master 10.20.149.60
Slave 10.20.149.36

主dns配置:
view "view1" {
        match-clients {key idc-key;};
        allow-transfer {key idc-key;};
        allow-update {key idc-key;};
        also-notify {10.20.149.36;};
        server 10.20.149.36 { keys {idc-key;}; };
        zone "example.com" IN {
        type master;
        file "view/idc/hosts.example.com";
    };
};

从dns配置:
view "view1" {
        match-clients {key idc-key; 10.0.0.0/8; };
        allow-transfer {key idc-key;};
        server 10.20.149.60 {keys idc-key;};
        zone "example.com" IN {
        type slave;
        masters { 10.20.149.60; };
        file "view/idc/hosts.example.com";
    };
};

从dns也可以如此配置:
view "view1" {
        match-clients {key idc-key; 10.0.0.0/8; };
        allow-transfer {key idc-key;};
        zone "example.com" IN {
        type slave;
        masters { 10.20.149.60 keys idc-key;};
        file "view/idc/hosts.example.com";
    };
};

2012年2月25日星期六

在linux下创建winpe启动环境


1 配置dhcp服务,下载ris-linux-0.4(略)

2 配置smb服务,配置文件大概如下:
[reminst]
path = /opt/kickstart/tftpboot
public = yes
browsable = true
read only = no
guest ok = yes

3 配置tftp服务,由于linux对大小写敏感,需要将所有以大写字母命名的文件转换成小写字母命名,转换脚本如下:

find ./ -depth |perl -ne 'chomp;m</[^/]*$>;$d=$`;$_=$f=$&;''s/([\x80-\xFF].)|(\w)/$1\l$2/g;system "mv",$d.$f,$d.$_ if $f ne $_'

配置/opt/kickstart/tftpboot/rules文件,对文件名进行映射,内容如下:
[root@linux_install /opt/kickstart/tftpboot]
#cat rules
ri ^[a-z]: # Remove ¡°drive letters¡±
rg \\ / # Convert backslashes to slashes
rg \# @ # Convert hash marks to @ signs
rg /../ /..no../ # Convert /../ to /..no../
rg A a
rg B b
rg C c
rg D d
rg E e
rg F f
rg G g
rg H h
rg I i
rg J j
rg K k
rg L l
rg M m
rg N n
rg O o
rg P p
rg Q q
rg R r
rg S s
rg T t
rg U u
rg V v
rg W w
rg X x
rg Y y
rg Z z
r ^/(.*) \1

启动tftp服务时,需要指定-m参数:
/opt/kickstart/hpa-tftp/sbin/in.tftpd -l -v -s /opt/kickstart/tftpboot/ -m /opt/kickstart/tftpboot/rules

创建winpe的启动环境:
1 找到 STARTROM.N1_ 文件,并重命名为/opt/kickstart/tftpboot/winpe.0
2 运行sed -i -e 's/NTLDR/peldr/gi' /opt/kickstart/tftpboot/winpe.0
3 找到setupldr.exe 文件(i386目录下),并重命名为/opt/kickstart/tftpboot/peldr
4 运行sed -i -e 's/winnt\.sif/winpe\.sif/gi' /opt/kickstart/tftpboot/peldr
5 运行sed -i -e 's/ntdetect\.com/ntdetect\.wpe/gi' /opt/kickstart/tftpboot/peldr
6 找到NTDETECT.COM文件(i386目录下),并重命名为/opt/kickstart/tftpboot/ntdetect.wpe
7 运行 ris-linux-0.4/fixloader.py /opt/kickstart/tftpboot/peldr (此处仅为pxe启动winpe使用,如配置WinXP的安装源则无需这一操作)
8 配置/opt/kickstart/tftpbootwinpe.sif文件如下:

[Intranet root@KickStart /opt/kickstart/tftpboot]
#cat winpe.sif
[SetupData]
OsLoadOptions = "/fastdetect /minint"
SetupSourceDevice = "\Device\LanmanRedirector\10.20.129.9\reminst\windows\winpe"
[UserData]
ComputerName = WindowsPE

KickStart关于%include的使用方法


我们可以将ks文件中相同的内容独立出来写在同一个文件common当中,然后通过ks中的%include /tmp/ks/common选项包含进来。但是common文件的位置该如何处理呢?
首先解释一下ks文件被安装程序anaconda解析的过程:
1pre脚本运行之前,anacondaks文件进行解析,这个时候anaconda会忽略掉所有它不能找到的文件。
2 运行pre脚本。
3 重新解析那些没有找到的文件。

在第1步中使anaconda访问到include所包含的文件是比较困难的,但是通过运行pre脚本可以使anaconda在第3步中对缺失的文件进行解析。pre脚本可以写成如下的形式:

%pre
#!/bin/bash
###ks服务器的IP192.168.0.1common文件存在于ks服务器上的/kickstart/ks/ 目录下
mount 192.168.0.1:/kickstart /mnt
mkdir –p /tmp/ks
cp /mnt/ks/common /tmp/ks/common

通过以上三个命令anaconda可以直接访问到/tmp/ks/common文件。在第1步对ks配置文件解析时被忽略的%include /tmp/ks/common 顺利的在第3步中被解析了。

可以通过以上方法对系统的分区行为根据需要进行动态设置,方法如下:
1 ks文件中的分区信息独立出来,写进partation文件,然后在ks中添加%include /tmp/ks/partation
2 pre脚本中用fdisk等命令分析硬盘信息
3 pre脚本中运行命令,修改/tmp/ks/partation文件
经过以上三步,anaconda就可以根据硬盘类型,容量的不同对分区信息进行动态调整了