poetry

往事越千年,魏武挥鞭,东临碣石有遗篇。萧瑟秋风今又是,换了人间。

kvm

大纲

kvm创建虚拟机的根本在于这样一条命令,virsh define vm-template.xml,这条命令的核心就是创建一个虚拟机,之后或者之前的内容都是围绕着这条命令和这个虚拟机的。

  • 更新vm-templatem模板是为了进行子机资源配置
  • 在更新模板之前检查时主机是为了防止给子机过量的资源导致母机不稳定
  • 桥接网卡是为了让子机连接局域网

所以,virsh define vm-template.xml 其本质是在安全可靠的前提下,将母机的资源通过kvm虚拟化的形式分配给子机。

所以主要考虑方向有两个

1、保障母机和子机的安全可靠,包括系统安全和网络安全

2、进行资源分配,包括网络资源、存储资源、计算资源等

该脚本考虑了母机分配资源不会超过母机承受范围的资源安全,其他系统层面和网络层面的安全问题还需考虑

命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 1、sed   
- 替换注释 sed -i "s/^IPADDR/#&/" file
- 字段追加 sed -i "/DEVICE/a\BRIDGE='br0'" file
- 指定行插入 sed -i "4iContent" file
- 注意""''的区别,在使用变量时可以加\转义字符


- 2、cat
- cat << EOF > file ,这里的变量需要转义字符\,且EOF不能使用双引号"EOF",否则变量会消失


- 3、expect
- expect执行顺序容易错乱
- expect "~" { send "umount /share \r" } :常用expect方法
- 如果执行expect需要等待很长时间,可以把timeout设置为-1
- expect脚本执行时,不能使用sh script.sh 这样相当于用shell的解释器执行,可以采用./script $args


- 4、while
- while read a b c d e;do ....; done < file,用于读取类似格式为 192.168.1.1 255.255.255.0 C 之类的文本,读取之后 a b c d e 均为file中对应的变量


- 5、echo
- 注意echo颜色的使用,红色闪烁和绿色健康:-e "\033[31m\033[01m\033[05m[ err ]\033[0m" "\033[32m [ OK ] \033[0m"


- 6、bc
- shell中浮点数和整数、浮点数和浮点数不能直接比较大小,可以使用bc工具
- echo "1.1 > 1" | bc 正确为1 错误为0

过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
完成过程
- 1|主机检查-(磁盘、CPU、内存) 写了自动检查&手动检查[0]
- 2|网卡桥接,创建一个br0作为网桥,连接eth1和kvm虚拟机
- 3|安装软件,执行tlinux*.run
- 4|重启母机
- 5|主机通信[1]
- 6|创建子机磁盘,包括系统盘、数据盘、共享盘
- 6|配置模板,包括调整CPU个数、内存大小、vlanid、网卡、uuid、mac地址、子机名称
- 7|使用6中的模板创建子机[2]
- 8|登录子机[3]
- 9|执行脚本,只要expect程序不错,这里基本不会错[4]


[0]
刚开始考虑当母机资源超过一定比例则程序退出,比如磁盘使用超过2/3,后来觉得这样不够灵活,改用百分比,默认50%
在设置百分比的时候有几点小问题
1、浮点数运算保留小数
使用scale可以准确保留小数,echo "scale=2;62/3" | bc 结果 20.66
使用printf可以保留小数位,补零填充 printf %.2f 结果20.00
2、浮点数运算不保留小数
echo "123.123"|sed "s/\..*//g"
*代表0到多个,所以第一个命令中\.*只能替换掉小数点变成空
\..*代表了小数点之后的1到多个
3、除法
echo "2 / 3" | bc 这个结果会显示为0
echo "scale=2 ;2 / 3" | bc 这个结果会显示为.66
printf "%.2f" `echo "scale=2;2/3" | bc` 这个结果会显示为0.66


[1]
刚开始的时候选择将subvm_configuration.sh这个脚本cat进内存,然后用expect登录到子机的时候echo到文件,然后执行。后来发现expect输出的时候会把subvm_configuration.sh脚本里的内容先执行一遍,而且还存在其他一些问题,比如说echo到文件的时候残缺不全、不换行、文件为空等。
后来采用磁盘共享的方式,在宿主机上创建一块磁盘,然后挂载到/tmp/share/这个目录,再将subvm_configuration.sh脚本和ipinfo配置文件复制到该目录,之后在子机的XML文件中添加一块disk(vdc),登录进子机后,挂载vdc,此时就可以看到母机上/tmp/share/下的内容了。直接执行脚本即可。
磁盘共享也有一个缺点,就是文件内容不能实时刷新,比如在母机上改了ipinfo,只有子机重启后,子机上的ipinfo才可以刷新,鉴于/tmp/share/这个目录每个子机一生只有一次用到,所以这个问题暂时不需要解决。


[2]
创建子机
1、if ( vlanid != 0 && xenbrx not in `brctl show` ) 会报错网卡未找到导致虚拟机启动失败
2、vm-template模板不正确,包括<emulator>/usr/local/bin/qemu-system-x86_64</emulator>路径不正确,会导致虚拟机无法启动
3、disk的slot卡槽相同会导致虚拟机无法启动
4、需要注意的是,virsh define vm-template 这条命令的执行路径是/usr/local/etc/libvirt/qemu/vm-template,最后会在/usr/local/etc/libvirt/qemu/下生成vm$ipfmt.xml的配置文件。



[3]
expect会有很多问题
1、命令不按顺序执行
2、传入的变量为空,且传入的变量下标是从0开始的;shell传入变量下标从1开始,0代表自身文件
3、set timeout $time 设置的时间不一定准确,设置了300秒延时,但未到300s,程序还是退出了,可以考虑直接设置 timeout 为-1
4、expect有多种写法,有expect << EOF ; expect eof ; 最正常的是上面用的
5、expect文件用的解释器是/usr/bin/expect,这里将login.sh使用cat写在了单独的文件中

[4]
1、subvm_configuration.sh配置了两张网卡,格式化vdb数据盘,配置ssh
2、eth0为连接外网的网卡,使用tunnel,eth1为内网网卡,使用vlan

xenbrX为隧道入口,母机收到从xenbr361口收到的报文,就发给另一端隧道,从而实现连接外网
tunnel network ---- host(default router: subhost -> netowrk , throught interface & sh vlan.sh ) ---- subhost

母机收到vlan的报文,就在指定vlan的广播域内进行路由(不一定是母机进行路由)
vlan network ---- host(broadcast router: subhost ---> broadcast/vlanid throught 802.1Q ) ---- subhost

[*]

expect合理用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat  << EOF >  ${workdir}/login.sh
#!/usr/bin/expect
if { \$argc < 1} {
puts "Usage:cmd <host>"
exit 1
}
set timeout -1
set host [lindex \$argv 0]
spawn virsh console \$host
expect "*Escape*" { send "\r" }
expect "*login*" { send "root\r" }
expect "*Password*" { send "xxxx\r" }
interact
EOF

高效的while

1
2
3
4
5
6
while read equipmentName ip netmask;
do
echo "=====================${equipmentName}=================="
echo "inner_ip:${ip}"
echo "inner_netmask:${netmask}"
done < file