构建 docker 镜像

构建 docker 镜像主要基于 git project 和 branch (还有 timeout ),输出的是可运行镜像。


我们基于 git 事件自动打包,当 project 有新的 push 或者 merge 事件时自动触发,我司使用 Gerrit,监控 git 事件
很简单:

ssh -p 29418 -i key_path user@git.xxx.com "gerrit stream-events"

比如获取到了下面的事件:

{
"type": "ref-updated",
    "submitter": {
    "name": "Zhou xxx",
    "email": "zhouxxx@xxx.com",
    "username": "zhouxxx"
},
"refUpdate": {
    "oldRev": "f612a09551f848c22cc6b758ab6844c9afd73b00",
    "newRev": "c6f8b2214afcaa83d11a109703c31227e9ac4068",
    "refName": "master",
    "project": "projectName"
}
}

匹配需要的 type 然后拿到 project 和 refName。


构建的整体思路是创建一个 Container,在 Container 里构建镜像,构建镜像需要一些配置文件,我们定义了一个 dockerfiles 项目来专门存放配置文件,目录结构如下:

dockerfiles/{project1,project2…}/{service1,service2…}/{Dockerfile,build_app_image,build_app.sh,…}
  1. 对于一个 project,它有哪些 service 根据 dockerfiles/project/ 下面的目录名称来获取,当 project 有事件发生
    ,它下面所有的 service 都会构建(构建之前先 pull dockerfiles,保持 dockerfiles 最新);

  2. service 需要一个构建应用程序包的镜像,包含必要的基础环境,比如 centos6-java6-maven 包含 java 和 maven。

  3. 构建应用程序包镜像 在 build_app_image 中定义;

  4. build_app.sh 是具体构建应用程序包的命令,可以约定一个基础目录统一存放 project,以便 build_app.sh 知道进入哪个目录打包;

  5. Dockerfile 用于打真正运行的镜像,FROM 后面指定运行基础镜像,比如 centos6-java8-tomcat8,运行镜像的格式定
    义为 service:branch,比如 image-service:release_20151128。

  6. 我们用的 Docker 调度系统是 swarm,调用 swarm api 创建基于构建应用程序包镜像的服务,并且 Container command (entrypoint)中要写相关命令,包括:

1). 在约定的统一目录拉取项目代码,用:

git clone -b release/RB_2015_11_01 --depth=1 ssh://git.nosa.me:29418/projectName

2). 并且拉取 dockerfiles 配置:

git clone -b release/master --depth=1 ssh://git.nosa.me:29418/dockerfiles

3). 执行 build_app.sh 打包;

4). 构建运行镜像:

docker build --rm=true -t dockerRegistry/image-service:release_20151128 .

docker push dockerRegistry/image-service:release_20151128

这两个命令在 Dockefile 的目录运行,这里会使用 build_app.sh 打成的包,比如 COPY webapp.war /。

这些命令合起来就是完整的构建命令,举个例子:

cd / && git clone -b master –depth=1 ssh://autodeploy@git.nosa.me:29418/wdstack && \
cd / && git clone -b master –depth=1 ssh://autodeploy@git.nosa.me:29418/dockerfiles && \
cd //wdstack && sh //dockerfiles/services/wdstack/wdstack-service/build_app.sh && \
cd //dockerfiles/services/wdstack/wdstack-service && \
docker build –rm=true -t hub.internal.nosa.me/wdstack-service:master . && \
docker push hub.internal.nosa.me/wdstack-service:master

从镜像中 exclude 文件或目录, 缩减镜像大小

我的目标是从在基于镜像创建虚拟机的时候 exclude 部分文件或目录,使得创建虚机更快。本来我想如果 qemu-image convert 的时候支持 exclude,那就简单了,但是不支持,查了更多资料以后,我发现 guestfish 的 tar-out 支持 exclude,但是出来的是 tar 包,而不是 image 了(virt-tar-out 这个命令和 tar-out 类似,但是不支持 exclude)。


下面举个栗子,记录一下过程。

我的 domain 是 vm1, 系统盘名称叫 vm1,数据盘(/home)叫 vm1_data。

首先,对于系统盘的 vm1,我打算不使用 tar-out 打包出来,而是还是用 qemu-image convert 命令转换成 qcow2 格式,即使 vm1 已经是 qcow2,转换之后的 image 大小也可能减小,而且我使用 -c 选项启用压缩,转换之后的 image 大概 900M,大小我能接受。

下面是完整的转换命令:

qemu-img convert -c -O qcow2 vm1 /mfs/vm1

这种方法有个问题,如果系统盘不止 vm1,还有其他盘,会有问题,但是这种情况几乎没有,暂不考虑。


对于数据盘 vm1_data,不用 image ,使用 tar-out,而且我准备 exclude 出名字为 log 或者 logs 的目录,所以我先要获取 log 或者 logs 的目录路径。

在 vm1 关机情况下,对整个 domain 查找 /home 下 log 或 logs 的目录:

guestfish -d vm1 -i sh \
"find /home -type d -name log -o -name logs "

结果是:

/home/op/assets_agent_v2/logs
/home/ossec/ossec/logs

然后,用 tar-out 打包出来(启用压缩),格式如下:

guestfish -d vm1 \
run : mount /dev/datavg/home / : \
tar-out / home.tgz compress:gzip \
"excludes:op/assets_agent_v2/logs/* ossec/ossec/logs/*"

home.tgz 即是数据盘中去除日志的目录,当然在系统的实现中,我们支持自定义 exclude 目录。


在开机状态下,不能使用 -d vm1,只能用 add vm1_data 这种格式,此次 find 不支持 -type d 类似的参数,只能使用简单的 find 目录:

guestfish add vm1_data \
: run : mount /dev/datavg/home / : find /

这条命令会显示所有的文件和目录,如果想去重 log 或者 logs 目录,可以做聚合。

然后 tar-out 命令类似下面:

guestfish add vm1_data \
: run : mount /dev/datavg/home / : \
tar-out / home.tgz compress:gzip \
"excludes:op/assets_agent_v2/logs/* ossec/ossec/logs/*"

由于在开机状态下,我们指定了 /home 的 image,如果 /home 有多个 image,那么这种情况就需要关机了,系统中应该判断,如果有多个数据盘,需提示关机。


那么,对于 tar-out 出来的包,怎么「塞进」新的数据盘呢。

先创建 vm2_data:

virsh vol-create-as –pool vm_storage_pool \
–name vm2_data –capacity 10G –allocation 1G \
–format qcow2

然后创建 lvm 和文件系统,和 vm1_data 保持一致:

virt-format -a vm2_data –lvm=/dev/datavg/home \
–filesystem=ext4

查看 lvm group:

# virt-filesystems -a vm2_data –volume-groups
/dev/datavg

查看 physical volumes:

# virt-filesystems -a vm2_data –physical-volumes
/dev/sda1

查看文件系统:

# virt-filesystems -a vm2_data -l

Name Type VFS Label Size Parent
/dev/datavg/home filesystem ext4 – 10733223936 –

准备工作完成了,可以 tar-in 数据了:

guestfish add vm2_data \
: run : mount /dev/datavg/home / : \
tar-in home.tgz / compress:gzip

如果 home.tgz 通过 http 获取,可以这样:

curl http://nosa.me/vm2_home.tgz | \
guestfish add vm2_data : run : \
mount /dev/datavg/home / : \
tar-in – / compress:gzip

最后,借贵地记录一下 allocation 和 capacity 的说明。

allocation
Providing the total storage allocation for the volume. This may be smaller than the logical capacity if the volume is sparsely allocated. It may also be larger than the logical capacity if the volume has substantial metadata overhead. This value is in bytes. If omitted when creating a volume, the volume will be fully allocated at time of creation. If set to a value smaller than the capacity, the pool has the option of deciding to sparsely allocate a volume. It does not have to honour requests for sparse allocation though. Different types of pools may treat sparse volumes differently. For example, the logical pool will not automatically expand volume’s allocation when it gets full; the user is responsible for doing that or configuring dmeventd to do so automatically.By default this is specified in bytes, but an optional attribute unit can be specified to adjust the passed value. Values can be: ‘B’ or ‘bytes’ for bytes, ‘KB’ (kilobytes, 103 or 1000 bytes), ‘K’ or ‘KiB’ (kibibytes, 210 or 1024 bytes), ‘MB’ (megabytes, 106 or 1,000,000 bytes), ‘M’ or ‘MiB’ (mebibytes, 220 or 1,048,576 bytes), ‘GB’ (gigabytes, 109 or 1,000,000,000 bytes), ‘G’ or ‘GiB’ (gibibytes, 230 or 1,073,741,824 bytes), ‘TB’ (terabytes, 1012 or 1,000,000,000,000 bytes), ‘T’ or ‘TiB’ (tebibytes, 240 or 1,099,511,627,776 bytes), ‘PB’ (petabytes, 1015 or 1,000,000,000,000,000 bytes), ‘P’ or ‘PiB’ (pebibytes, 250 or 1,125,899,906,842,624 bytes), ‘EB’ (exabytes, 1018 or 1,000,000,000,000,000,000 bytes), or ‘E’ or ‘EiB’ (exbibytes, 260 or 1,152,921,504,606,846,976 bytes). Since 0.4.1, multi-character unit since 0.9.11
capacity
Providing the logical capacity for the volume. This value is in bytes by default, but a unit attribute can be specified with the same semantics as for allocationThis is compulsory when creating a volume. Since 0.4.1

用 guestfish 修改虚拟机镜像里的文件

接上文,在新宿主机上生成的新虚拟机为 vm2 ,镜像文件分别为 /vm_sp/vm2.img (/ 分区)和 /vm_sp/vm2_data.img (/home分区,做数据盘),格式都是 qcow2,/vm_sp/ 是基于 目录的存储池。

 

首先先把 vm2 关机,否则无法修改 虚拟机内容。

 

安装 guestfish 命令
# yum -y install guestfish

 

我们先来看看单条命令,比如你只想修改主机名,可以这样:

[shell]
guestfish -d vm2 -i sh \
"sed -i ‘s/HOSTNAME.*/HOSTNAME=test0.hlg01/g’ /etc/sysconfig/network"
[/shell]

-d 表示 指定 虚拟机 域,-i 会自动 挂载 域 的磁盘,当然也可以不用 -d 而用 -a ,表示直接指定一个 img 文件。

另外,修改文件也可以用 virt-edt 命令,但是没上条命令那么通用,上条命令所有的 shell 都能执行。
# virt-edit -d $name /etc/sysconfig/network -e “s/HOSTNAME=.*/HOSTNAME=test0.hlg01/g

 

再来看看交互情况下的用法。
# guestfish -d vm2

Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: ‘help’ for help on commands
‘man’ to read the manual
‘quit’ to quit the shell

><fs> run
><fs> list-filesystems
/dev/sda1: ext3
/dev/sda2: swap
/dev/datavg/home: ext4
/dev/domovg/root: ext4
><fs> mount /dev/domovg/root /
><fs> mount /dev/datavg/home /home/
><fs> cat /etc/fstab

/dev/mapper/domovg-root / ext4 defaults,data=ordered 1 1
UUID=7415a5d3-bd20-4a08-9288-66c49ab20b8d /boot ext3 defaults,data=ordered,nodev,nosuid,noexec 1 2
UUID=df3f6ed1-40e7-4da4-b481-465c7ac5fc17 swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
/dev/datavg/home /home ext4 defaults,data=ordered,nodev,nosuid 1 2

><fs> cat /etc/udev/rules.d/70-persistent-net.rules
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.
# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM==”net”, ACTION==”add”, DRIVERS==”?*”, ATTR{address}==”52:54:00:b0:4a:a1″, ATTR{type}==”1″, KERNEL==”eth*”, NAME=”em2″

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM==”net”, ACTION==”add”, DRIVERS==”?*”, ATTR{address}==”52:54:00:6a:e8:21″, ATTR{type}==”1″, KERNEL==”eth*”, NAME=”em1″

><fs> cat /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=test0.hlg01

><fs> cat /etc/sysconfig/network-scripts/ifcfg-em2
DEVICE=”em2″
BOOTPROTO=”static”
DNS1=”10.0.12.234″
GATEWAY=”10.19.26.1″
IPADDR=”10.19.26.101″
NETMASK=”255.255.255.0″
ONBOOT=”yes”
TYPE=”Ethernet”

><fs> ls /home/
lost+found

 

上面的交互不易于自动化,这里我们可以编写脚本,如下:

[shell]

#!/bin/bash

name=$1
ip=$2
hostname=$3
hwaddr_em2=$4
hwaddr_em1=$5

netmask=255.255.255.0

x=`echo $ip | awk -F. ‘{print $1"."$2"."$3}’`
gateway="$x.1"

# 定义虚拟机, 否则无法根据域修改镜像.
virsh define /etc/libvirt/qemu/$name.xml || exit 1

# 修改系统镜像, 包括:
# 1. 修改主机名;
# 2. 修改网卡设置(增加HWADDR的原因是系统可以把eth变成em);
# 3. 修改路由信息;
# 4. 删除/etc/udev/rules.d/70-persistent-net.rules;
# 5. 删除/var/lib/puppet;
# 6. 删除/etc/sn;
# 然后启动.
guestfish –rw -d $name <<_EOF_
run
mount /dev/domovg/root /
mount /dev/datavg/home /home/
command "sed -i ‘s/HOSTNAME=.*/HOSTNAME=${hostname}/g’ /etc/sysconfig/network"

write /etc/sysconfig/network-scripts/ifcfg-em2 "DEVICE=em2\nHWADDR=${hwaddr_em2}\nBOOTPROTO=static\nIPADDR=$ip\nNETMASK=$netmask\nONBOOT=yes\nTYPE=Ethernet"

write /etc/sysconfig/network-scripts/ifcfg-em1 "DEVICE=em1\nHWADDR=${hwaddr_em1}"

write /etc/sysconfig/network-scripts/route-em2 "192.168.0.0/16 via 10.19.28.1\n10.0.0.0/8 via 10.19.28.1\n100.64.0.0/16 via 10.19.28.1\n0.0.0.0/0 via 10.19.28.1"

command "/bin/rm -rf /etc/udev/rules.d/70-persistent-net.rules"
command "/bin/rm -rf /var/lib/puppet/"
command "/bin/rm -rf /etc/sn"
_EOF_

[/shell]

说明一下,command 命令里 echo xxx > file 是无效的。

 

挂载raw镜像文件中的 LVM 逻辑分区

这里的raw镜像是 存储池的一个卷 /dev/vm_storage_pool_vg/vm_test .

 

首先用 losetup 工具把 centos.img 文件和 loop 设备映射起来,-f 参数 用来找出下一个可用的 loop 设备:
# losetup -f
/dev/loop0

# losetup /dev/loop0 /dev/vm_storage_pool_vg/vm_test

然后通过 fdisk /dev/loop0 来查看 分区表,-u 参数指明使用 sector 为单位记录偏移量(offset)而不是 cylinder 为单位
# fdisk -ul /dev/loop0
Disk /dev/loop0: 19.3 GB, 19327352832 bytes
255 heads, 63 sectors/track, 2349 cylinders, total 37748736 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0007f3dc

Device Boot Start End Blocks Id System
/dev/loop0p1 * 2048 1050623 524288 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/loop0p2 1050624 9439231 4194304 82 Linux swap / Solaris
Partition 2 does not end on cylinder boundary.
/dev/loop0p3 9439232 37748735 14154752 8e Linux LVM

因为每个 sector 是 512 字节(bytes),所以 offset 等于 512 * 9439232 = 4832886784,这个 offset 很重要

先删除映射,用offset 重新做映射.
# losetup -d /dev/loop0

# losetup /dev/loop0 /dev/vm_storage_pool_vg/vm_test -o 4832886784
看到有两个 domovg ,要改名。

# lvm pvscan
PV /dev/vm_storage_pool_vg/vm_test_data VG datavg lvm2 [3.00 GiB / 0 free]
PV /dev/vm_storage_pool_vg/vm03_data VG datavg lvm2 [30.00 GiB / 0 free]
PV /dev/sda5 VG vm_storage_pool_vg lvm2 [825.09 GiB / 294.09 GiB free]
PV /dev/vm_storage_pool_vg/vm02_data VG datavg lvm2 [20.00 GiB / 0 free]
PV /dev/vm_storage_pool_vg/vm01_data VG datavg lvm2 [200.00 GiB / 0 free]
PV /dev/sda2 VG domovg lvm2 [9.97 GiB / 992.00 MiB free]
PV /dev/loop0 VG domovg lvm2 [13.47 GiB / 5.47 GiB free]
Total: 7 [1.08 TiB] / in use: 7 [1.08 TiB] / in no VG: 0 [0 ]

先找到UUID,根据大小判断 UUID 是 0lejct-TXWQ-Keib-siM2-3Nsx-YwvE-WYhKBP
# vgs -v
Finding all volume groups
Finding volume group “datavg”
Archiving volume group “datavg” metadata (seqno 2).
Archiving volume group “datavg” metadata (seqno 2).
Creating volume group backup “/etc/lvm/backup/datavg” (seqno 2).
Finding volume group “vm_storage_pool_vg”
Finding volume group “datavg”
Archiving volume group “datavg” metadata (seqno 2).
Archiving volume group “datavg” metadata (seqno 2).
Creating volume group backup “/etc/lvm/backup/datavg” (seqno 2).
Finding volume group “domovg”
Archiving volume group “domovg” metadata (seqno 6).
Archiving volume group “domovg” metadata (seqno 7).
Creating volume group backup “/etc/lvm/backup/domovg” (seqno 7).
Finding volume group “domovg”
Archiving volume group “domovg” metadata (seqno 7).
Archiving volume group “domovg” metadata (seqno 6).
Creating volume group backup “/etc/lvm/backup/domovg” (seqno 6).
VG Attr Ext #PV #LV #SN VSize VFree VG UUID
datavg wz–n- 4.00m 1 1 0 3.00g 0 neUdtJ-tGn6-0m2w-Tkv7-rJyF-dWEs-g0Oi0Y
datavg wz–n- 4.00m 1 1 0 200.00g 0 Rhflru-OVBX-Mzbh-Xto1-6mNZ-DAhl-21gnpe
domovg wz–n- 32.00m 1 6 0 9.97g 992.00m fPnkRe-0oTr-99xV-FqcR-tO9M-6uTi-fvUVii
domovg wz–n- 32.00m 1 5 0 13.47g 5.47g 0lejct-TXWQ-Keib-siM2-3Nsx-YwvE-WYhKBP
vm_storage_pool_vg wz–n- 32.00m 1 12 0 825.09g 294.09g RhYxZm-eF5N-CMMb-b8it-UcLI-9zeZ-POM6tH

# vgrename 0lejct-TXWQ-Keib-siM2-3Nsx-YwvE-WYhKBP testvg
Volume group “domovg” successfully renamed to “testvg”
# lvm vgchange -ay
1 logical volume(s) in volume group “datavg” now active
12 logical volume(s) in volume group “vm_storage_pool_vg” now active
device-mapper: create ioctl on datavg-home failed: Device or resource busy
0 logical volume(s) in volume group “datavg” now active
6 logical volume(s) in volume group “domovg” now active
5 logical volume(s) in volume group “testvg” now active

可以看到设备了。
# ls /dev/mapper/testvg-*
/dev/mapper/testvg-opt /dev/mapper/testvg-tmp /dev/mapper/testvg-var
/dev/mapper/testvg-root /dev/mapper/testvg-usr

可以挂载了。
# mount /dev/mapper/testvg-root /mnt/root

# df -h |grep /mnt/root
1008M 191M 767M 20% /mnt/root

# ls /mnt/root/
bin dev home lib64 media opt root selinux sys usr
boot etc lib lost+found mnt proc sbin srv tmp var

可以修改里面的配置了。

 

回收过程:
# umount /mnt/root/

# lvm vgchange testvg -aln
0 logical volume(s) in volume group “testvg” now active

可以看到已经无法改回domovg
# vgrename 0lejct-TXWQ-Keib-siM2-3Nsx-YwvE-WYhKBP domovg
/dev/domovg: already exists in filesystem
New volume group name “domovg” is invalid

# losetup -d /dev/loop0

原虚拟机不能用了,我试图:
1. 修改 /mnt/root/etc/fstab 里面的domovg 为 testvg.
2. cd /mnt/root ; mv etc/lvm/backup/domovg etc/lvm/backup/testvg;修改etc/lvm/backup/testvg里面的domovg 为 testvg
3. cd /mnt/root ; 修改 etc/mtab 里面的domovg 为 testvg

结果还是报找不到 domovg !!!

 

参考:
http://www.vpsee.com/2010/10/mount-lvm-volumes-from-loopback-disk-images/

挂载qcow2 镜像文件中的的 lvm 分区

先用qemu-img 生成一个qcow2的镜像

# qemu-img convert /dev/vm_storage_pool_vg/vm07 /dev/vm_storage_pool_vg/vm07_data -O qcow2 vm07.qcow2

/dev/vm_storage_pool_vg/vm07 /dev/vm_storage_pool_vg/vm07_data 分别是系统盘和数据盘,都是raw 格式的,里面有LVM分区,所以转换之后 vm07.qcow2 是含有LVM的qcow2镜像。
先挂载qcow2镜像。

# modprobe nbd max_part=16

# qemu-nbd -c /dev/nbd0 vm07.qcow2

# partprobe /dev/nbd0

# ls /dev/nbd0*
/dev/nbd0 /dev/nbd0p1 /dev/nbd0p2 /dev/nbd0p3

# fdisk -ul /dev/nbd0

Disk /dev/nbd0: 180.4 GB, 180388626432 bytes
255 heads, 63 sectors/track, 21931 cylinders, total 352321536 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0007e2d5

Device Boot Start End Blocks Id System
/dev/nbd0p1 * 2048 1050623 524288 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/nbd0p2 1050624 9439231 4194304 82 Linux swap / Solaris
Partition 2 does not end on cylinder boundary.
/dev/nbd0p3 9439232 37748735 14154752 8e Linux LVM

可以看到LVM分区是/dev/nbd0p3,下面我们想办法挂载它。

可以算出偏移量 9439232 * 512 = 4832886784

删除映射
# qemu-nbd -d /dev/nbd0

重启以偏移量做映射
# qemu-nbd -c /dev/nbd0 vm07.qcow2 -o 4832886784

这样我们就可以看到LVM设备了- 第二个domovg 。
# vgs -v
Finding all volume groups
Finding volume group “domovg”
Archiving volume group “domovg” metadata (seqno 6).
Archiving volume group “domovg” metadata (seqno 7).
Creating volume group backup “/etc/lvm/backup/domovg” (seqno 7).
Finding volume group “domovg”
Archiving volume group “domovg” metadata (seqno 7).
Archiving volume group “domovg” metadata (seqno 6).
Creating volume group backup “/etc/lvm/backup/domovg” (seqno 6).
VG Attr Ext #PV #LV #SN VSize VFree VG UUID
domovg wz–n- 32.00m 1 6 0 835.09g 27.09g j6085A-ldRg-8gOV-F9pH-rnl9-EfvF-DwdA05
domovg wz–n- 32.00m 1 5 0 13.47g 4.47g xIRE6j-eOhA-lwkI-yhci-WCY1-Noaa-XvaB9D

看到有两个domovg,我把本机的domovg 改掉(本机是测试环境),保持我们要挂载的LVM设备不变
# vgrename j6085A-ldRg-8gOV-F9pH-rnl9-EfvF-DwdA05 domovg2
Volume group “domovg” successfully renamed to “domovg2”

# vgs -v
Finding all volume groups
Finding volume group “domovg2”
Finding volume group “domovg”
VG Attr Ext #PV #LV #SN VSize VFree VG UUID
domovg wz–n- 32.00m 1 5 0 13.47g 4.47g xIRE6j-eOhA-lwkI-yhci-WCY1-Noaa-XvaB9D
domovg2 wz–n- 32.00m 1 6 0 835.09g 27.09g j6085A-ldRg-8gOV-F9pH-rnl9-EfvF-DwdA05

激活所有LVM设备
# lvm vgchange -ay
6 logical volume(s) in volume group “domovg2” now active
5 logical volume(s) in volume group “domovg” now active

# ls /dev/mapper/
control domovg2-opt domovg2-tmp domovg2-var domovg-root domovg-usr
domovg2-home domovg2-root domovg2-usr domovg-opt domovg-tmp domovg-var

# mount /dev/mapper/domovg-root /mnt/

# ls /mnt/
bin dev home lib64 media opt root selinux sys usr
boot etc lib lost+found mnt proc sbin srv tmp var

如果要修改的話,注意下面几个文件:
在 /mnt/etc/sysconfig/network 里面修改主机名
在 /mnt/etc/sysconfig/network-scripts/ifcfg-em2 修改IP地址。
这个文件也要修改下 /mnt/etc/udev/rules.d/70-persistent-net.rules ,否则MAC地址会有问题。

 

如果系统里没有nbd模块或者qemu-nbd工具,请看:

http://nosa.me/2014/11/09/%E5%AE%89%E8%A3%85-nbd-%E6%A8%A1%E5%9D%97-%E5%92%8C-qemu-nbd-%E5%B7%A5%E5%85%B7/