本博客主要介绍通过cloud-init工具实现在Ubuntu16.04操作系统和KVM虚拟化技术下实现创建虚拟机同时离线安装编程环境
在可以联网的机器上准备好编程语言包,在这里我们以python3.6.8和java8为例
在python下载链接和java下载链接处下载好Python-3.6.8.tgz和jdk-8u321-linux-x64.tar.gz
sudo qemu-img create -f qcow2 package.qcow2 1G
将该磁盘挂载到一台虚拟机上,并对该磁盘进行分区,这里我们假设该磁盘挂载到虚拟机上后为/dev/vda,我们将该磁盘划分为一个区
sudo fdisk /dev/vda
输入n创建一个新分区,剩余选项全都默认回车,创建好之后输入w保存分区并退出,这样我们就在该磁盘上划分出一个1G的分区/dev/vda1,接着对该分区进行格式化
sudo mkfs.ext4 /dev/vda1
我们将磁盘挂载到虚拟机的一个目录下,这里我们在/home/ubuntu下创建package目录,并挂载磁盘,之后创建不同的文件夹用于区别不同的软件包
cd ~
sudo mkdir package
sudo mount /dev/vda1 package
cd package
sudo mkdir java-8
sudo mkdir python-3.6.8
分别将python包和java包放到对应的目录下,因为我们这里采用离线安装python,所以需要预先准备好编译python的软件,同样在该目录下创建目录用于存放python编译软件,这里我们采用递归下载所有deb依赖的方式获取所有的软件包
mkdir python-pkgs
cd python-pkgs
sudo apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances --no-pre-depends libbz2-dev libssl-dev libreadline6 libreadline6-dev libsqlite3-dev | grep -v i386 | grep "^\w")
最终该磁盘的目录如下显示:
.
├── java-8
│ └── jdk-8u321-linux-x64.tar.gz #java源码包
├── lost+found
├── python-3.6.8
│ └── Python-3.6.8.tgz #python源码包
└── python-pkgs #python编译需要的软件包
├── cdebconf_0.198ubuntu1_amd64.deb
├── debconf_1.5.58ubuntu2_all.deb
├── dpkg_1.18.4ubuntu1.7_amd64.deb
├── gcc-6-base_6.0.1-0ubuntu1_amd64.deb
├── install-info_6.1.0.dfsg.1-5_amd64.deb
├── libbz2-1.0_1.0.6-8ubuntu0.2_amd64.deb
├── libbz2-dev_1.0.6-8ubuntu0.2_amd64.deb
├── libc6_2.23-0ubuntu11.3_amd64.deb
├── libc6-dev_2.23-0ubuntu11.3_amd64.deb
├── libc-dev-bin_2.23-0ubuntu11.3_amd64.deb
├── libdebian-installer4_0.102ubuntu1.1_amd64.deb
├── libgcc1_1%3a6.0.1-0ubuntu1_amd64.deb
├── libnewt0.52_0.52.18-1ubuntu2_amd64.deb
├── libpcre3_2%3a8.38-3.1_amd64.deb
├── libreadline6_6.3-8ubuntu2_amd64.deb
├── libreadline6-dev_6.3-8ubuntu2_amd64.deb
├── libselinux1_2.4-3build2_amd64.deb
├── libslang2_2.3.0-2ubuntu1.1_amd64.deb
├── libsqlite3-0_3.11.0-1ubuntu1.5_amd64.deb
├── libsqlite3-dev_3.11.0-1ubuntu1.5_amd64.deb
├── libssl1.0.0_1.0.2g-1ubuntu4.20_amd64.deb
├── libssl-dev_1.0.2g-1ubuntu4.20_amd64.deb
├── libtextwrap1_0.1-14_amd64.deb
├── libtinfo5_6.0+20160213-1ubuntu1_amd64.deb
├── libtinfo-dev_6.0+20160213-1ubuntu1_amd64.deb
├── linux-libc-dev_4.4.0-210.242_amd64.deb
├── ncurses-bin_6.0+20160213-1ubuntu1_amd64.deb
├── readline-common_6.3-8ubuntu2_all.deb
├── zlib1g_1%3a1.2.8.dfsg-2ubuntu4.3_amd64.deb
└── zlib1g-dev_1%3a1.2.8.dfsg-2ubuntu4.3_amd64.deb
完成上述操作后,就可以把磁盘从虚拟机上卸载下来
这里我们需要一台模板虚拟机,可以参考之前的文章进行安装
参考cloud-init中NoCloud配置中使用方法的第一、二点对一台初始化的虚拟机进行安装并初始化文件和修改cloud-init配置文件操作。
在/etc/cloud目录下,我们准备好安装软件包的shell文件,通过NoCloud启动该脚本文件执行安装
cd /etc/cloud
sudo vim package.sh
文件中的内容如下显示:
#!/bin/bash
package=$1
install_python()
{
dpkg -i /mnt/python-pkgs/*.deb
package_full_name=$(ls /mnt/$package/)
package_name=${package_full_name%.*}
tar -zxf /mnt/$package/$package_full_name -C /tmp/
cd /tmp/$package_name
./configure && make && make install && make clean | cat > /dev/null
}
install_java()
{
username=$(ls /home/)
java_path="/usr/lib/jvm"
mkdir $java_path
tar -zxf /mnt/$package/*.gz -C $java_path
package_name=$(ls $java_path)
echo '
#set oracle jdk environment
export JAVA_HOME='$java_path/$package_name >> /home/$username/.bashrc
echo 'export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:\${JAVA_HOME}/lib:\${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH' >> /home/$username/.bashrc
}
package_type=${package%%-*}
case $package_type in
python)
install_python
;;
java)
install_java
;;
*)
return
;;
esac
该文件主要定义两个函数,用于安装java和python,通过在启动脚本文件时加入参数来判断安装什么环境,$1代表脚本文件后面带的参数,可以为python-3.6.8或者java-8,其中/mnt目录为我们将上面准备好的磁盘文件到时候直接挂载在虚拟机的/mnt目录下。完成以上操作后关闭虚拟机。
我们在物理机上准备好user-data文件,用于传输到虚拟机上配合cloud-init执行操作
sudo vim user-data
user-data文件内容如下:
#cloud-config
chpasswd:
list:
- ubuntu:root
- root:root
expire: false
mounts:
- [ /dev/vda1, /mnt, auto, "defaults", "0", "0" ]
runcmd:
- sh /etc/cloud/package.sh java-8
文件中chpasswd为配置用户名和密码,如果不需要可以删除,mounts为将磁盘挂载到/mnt目录下,即我们上面准备好的软件包磁盘,runcmd为执行脚本文件,后面的java-8是脚本参数,编写好文件后,创建一个空的meta-data文件,如果不创建,cloud-init会执行失败
touch meta-data
通过iso生成工具将user-data和meta-data封装到iso镜像中
genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
将生成的seed.iso和包含安装包的磁盘挂载到虚拟机上,编辑虚拟机对应的xml文件,添加cdrom和disk内容,如果虚拟机已经有cdrom设备,则只需要添加源文件即可
virsh edit ubuntu16.04
添加内容如下:
<disk type='file' device='cdrom'> #如果已有cdrom设备,则只需要添加source file即可
<driver name='qemu' type='raw'/>
<source file='/home/xidian/static_file/cloud-init-file/package/seed.iso'/>
<target dev='hdb' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<disk type='file' device='disk'> #将生成的package.qcow2文件挂载到虚拟机上
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/package.qcow2'/> #packge.qcow2文件位置
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</disk>
启动虚拟机,cloud-init读取cdrom设备的内容并执行user-data文件内容,触发脚本文件,安装编程环境
virsh start ubuntu16.04