Container:容器,基于容器的虚拟化技术起源于所谓的资源容器和安全容器。
(linux:OpenVZ,linux-VServer,FreeVPS.非linux:Solaris Zones,BSD jails,CoreOS,Dejs,Dynos,Docker)
LXC:linux Container.
LXC开源项目(sourceforge):项目本身只是一个为用户提供一个用户空间的工具集,用来使用和管理LXC容器。
LXC真正的实现则是靠Linux内核的相关特性,LXC项目只是对此做了整合。
LXC由下列两个技术组成:
1,资源管理方面依赖于Linux内核的cgroups子系统,cgroups子系统是Linux内核提供的一个基于进程组的资源管理的框架,
可以为特定的进程组限定可以使用的资源。
2,LXC在隔离控制方面依赖于Linux内核的namespace特性,具体而言就是在clone时加入相应的flag(NEWNS NEWPID等等)。
用户空间两类管理工具集: liblxc,libvirt
libvirt是Linux上的虚拟化库,是长期稳定的C语言API,支持KVM/QEMU、Xen、LXC等主流虚拟化方案。
2.1,liblxc工具集:
1,liblxc 工具包: yum install lxc (lxc-devel,lxc-libs,lxc-doc,lxc-templates,lxc-extra,python3-lxc,lua-lxc)2,iproute2 工具包:管理网络接口。yum install iproute (iproute-devel,iproute-doc)3,如何配置网络: 如:桥接a.创建一个桥b.将已有的网络接口添加到桥4,如何填充一个容器文件系统:除了网络外,容器通常还需要自己的文件系统。(生成chroot环境)多种填充容器文件系统的方法:a,构建定制的 Debian 容器;debootstrap sid rootfs http://debian.osuosl.org/debian/b,运行 ssh 容器5,如何连接到容器文件系统a,SSH ;(可以创建一个SSH容器)b,VNC(GUI);Virtual Network Computing,可以为容器增加一个gui启动时创建:echo '/usr/bin/vnc4server :0 -geometry 1024x768 -depth 24' >> rootfs/etc/rc.local连接:vncviewer <ip>:<display>c,VT: tty(文本);linux virtual terminals;与宿主共享tty.echo '8:2345:respawn:/sbin/getty 38400 tty8' >> rootfs/etc/inittabd,VT:X (GUI)通过 VT: X 连接 让您可以运行一个 GUI。在 VT 9 上运行 GNOME Display Manager(gdm),然后编辑 rootfs/usr/share/gdm/defaults.conf,将 FirstVT=7 替换为 FirstVT=9,以及将 VTAllocation=true 替换为 VTAllocation=false。lxc对象(虚拟机)存放目录:/var/lib/lxc/lxc缓存目录:/var/cache/lxc/配置文件样例:/usr/share/lxc/template/
2.2,LXC 工具命令:
1,创建容器:创建容器就是将一个名称与一个配置文件关联起来。该名称将用于管理容器:lxc-create -n name -f configfile(配置文件样例:/usr/share/lxc/templates/lxc-fedora)如:运行 lxc-sshd 脚本(该脚本创建一个配置)之后,ssh 容器配置如下所示:lxc.utsname = my_ssh_containerlxc.network.type = vethlxc.network.flags = uplxc.network.link = br0lxc.network.ipv4 = 10.0.2.16/24lxc.network.name = eth0lxc.mount = ./fstablxc.rootfs = ./rootfs2,获得(或列出)关于已有容器的信息显示一个容器的状态:lxc-info -n name显示属于一个容器的进程:lxc-ps3,启动系统和应用程序容器LXC容器分两种类型:1,系统容器,系统容器类似于虚拟机。与真正的虚拟化相比,虽然它们的隔离性要低一些,但是开销也降低了。直接原因是每个容器使用相同的 Linux 内核。为了类似于虚拟机,系统容器和 Linux发行版一样在同一个地方启动,即通过运行 init 程序:lxc-start -n name init2,应用程序容器。应用程序容器只是创建用于隔离一个应用程序的单独的名称空间。启动一个应用程序容器:lxc-execute -n name cmd4,向容器中运行的进程发信号:将一个信号发送到在一个容器中运行的所有进程:lxc-kill -n name -s SIGNAL5,暂停、恢复、停止和销毁容器暂停(冻结):lxc-freeze -n name恢复:lxc-unfreeze -n name停止:lxc-stop -n name销毁(删除与名称关联的配置文件和元数据):lxc-destroy -n name6,杂项:查看和调整容器的优先级:lxc-priority -n namelxc-priority -n name -p priority持续观察容器的状态和优先级变化:lxc-monitor -n name持续观察容器的状态和优先级变化:lxc-monitor -n name还可以等待容器进入以一组状态之一:lxc-wait -n name -s 'STOPPED|STARTING|STOPPING|ABORTING|FREEZING|FROZEN'
用于显示系统LXC的版本号:lxc-version判断linux内核是否支持LXC:lxc-checkconfig创建一个容器: lxc-create -n name [-f config_file]在一个容器执行应用程序: lxc-execute -n name [-f config_file] [ -s KEY=VAL ]command容器中执行给定命令: lxc-start -n name [-f config_file] [-c console_file] [-d] [-s KEY=VAL] [command]获取一个容器的状态: lxc-info -n name列出当前系统所有的容器: lxc-ls列出特定容器中运行的进程: lxc-ps监控一个容器状态的变换: lxc-monitor -n name获取一个容器的状态: lxc-info -n name获取或调整与cgroup相关的参数:lxc-cgroup -n name subsystem value如: lxc-cgroup -n foo devices.listlxc-cgroup -n foo cpuset.cpus "0,3"发送信号给容器中用户进程: lxc-kill -n name SIGNUM停止容器中所有的进程: lxc-stop -n name
销毁容器: lxc-destroy -n name
2.3,libvirt: 默认为KVM+qemu;(配置文件目录:/etc/libvirt/ )
官网:http://libvirt.org/drvlxc.html安装包:yum install libvirt-client virt-viewer virt-managera,图形界面接口的管理工具:virt-managerb,字符界面接口的管理工具:virsh(命令行工具)virsh list #显示本地活动虚拟机virsh list –all #显示本地所有的虚拟机(活动的+不活动的)virsh define fedora-configuration.xml #通过配置文件定义一个虚拟机(这个虚拟机还不是活动的)virsh start fedora #启动名字为fedora的非活动虚拟机virsh create fedora.xml # 创建虚拟机(创建后,虚拟机立即执行,成为活动主机)virsh suspend fedora # 暂停虚拟机virsh resume fedora # 启动暂停的虚拟机virsh shutdown fedora # 正常关闭虚拟机virsh reboot fedora # 重启虚拟机virsh destroy fedora # 强制关闭虚拟机virsh dominfo fedora #显示虚拟机的基本信息virsh domname 2 # 显示id号为2的虚拟机名virsh domid fedora # 显示虚拟机id号virsh domuuid fedora # 显示虚拟机的uuidvirsh domstate fedora # 显示虚拟机的当前状态virsh dumpxml fedora # 显示虚拟机的当前配置文件(可以保存,以便用来创建虚拟机)(可能和定义虚拟机时的配置不同,因为当虚拟机启动时,需要给虚拟机分配id号、uuid、vnc端口号等等)virsh setmem fedora 512000 #给不活动虚拟机设置内存大小virsh setvcpus fedora 4 # 给不活动虚拟机设置cpu个数virsh attach-device name config.xml#给虚拟机添加设备如:guest_device.xml:<disk type='block' device='cdrom'><driver name='qemu' type='raw'/><target dev='hdc' bus='ide'/><readonly/><alias name='ide0-1-0'/><address type='drive' controller='0' bus='1' unit='0'/></disk>#virsh update-device guestname guest_device.xmlDevice updated successfullyvirsh attach-disk #给虚拟机添加磁盘如:# virsh attach-disk guestname sample.iso hdc --type cdrom --mode readonlyDisk attached successfullyvirsh attach-interface#给虚拟机添加网络接口virsh edit fedora # 编辑配置文件(一般是在刚定义完虚拟机之后)virsh connect xen+ssh://[email protected] #连接远程libvirt(默认为本地qumu虚拟机qemu:///system)virsh –c xen+ssh://[email protected] list --all #连接并执行远程命令
virsh connect name or url
3.1,使用工具完成(yum install bridge-utils)
brctl addbr br0 ; #创建一个名为br0 的桥
brctl setfd br0 0 ; #设置桥的转发廷迟时间
ifconfig br0 10.0.2.15 promisc up;#用一个已有网络接口中的IP(在本例中是 10.0.2.15)连接到桥接口
brctl addif br0 eth0;#将已有的网络接口(在本例中是 eth0)添加到桥,并取消它与它的 IP 地址的直接关联
ifconfig eth0 0.0.0.0 up; (任何添加到桥 br0 的接口都将对那个 IP 地址作出响应)
route add -net default gw 10.0.2.2 br0;确保默认的路由
创建完成后可以给容器用(修改容器的配置文件)
lxc.network.type=veth
lxc.network.flags=up
lxc.network.link=br0
lxc.network.ipv4=10.20.153.234/24 #可以不写
lxc.network.hwaddr=4a:49:43:49:79:bd
3.2,直接修改网络配置文件
cat /etc/sysconfig/network-scripts/ifcfg-br0:
DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
BROADCAST=10.1.255.255
IPADDR=10.1.29.4
NETMASK=255.255.0.0
NETWORK=10.1.0.0
GATEWAY=10.1.0.254
ONBOOT=yes
cat /etc/sysconfig/network-scripts/ifcfg-eth1:
# Realtek Semiconductor Co., Ltd. RTL8101E/RTL8102E PCI Express Fast Ethernet controller
DEVICE=eth1
#BOOTPROTO=static
HWADDR=E0:CB:4E:B9:EB:77
#TYPE=Ethernet
#IPADDR=10.1.29.4
#NETMASK=255.255.0.0
#NETWORK=10.1.0.0
#GATEWAY=10.1.0.254
#USERCTL=no
#IPV6INIT=no
#PEERDNS=yes
ONBOOT=yes
BRIDGE=br0
4.1,创建LXC应用程序容器
1,安装用户态工具(从2.6.29开始,内核层已支持),yum install lxc
2,检查内核是否支持;lxc-checkconfig
3, 在主机上创建并挂载cgroup;(fedora已自动挂载)
mkdir /cgroup
mount none -t cgroup /cgroup
echo "none /cgroup cgroup defaults 0 0" >>/etc/fstab
4,配置桥接网络 ;
(使用brctl工具,也可直接修改接口配置文件,)
5,为容器创建配置文件;
如:此例保存为 /var/lib/lxc/lxc_test.conf
lxc.utsname = test
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 4a:49:43:49:79:bd
lxc.network.ipv4 = 192.168.250.150
lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596
6,开启封闭的运行进程(此例为开启一个封闭shell)
lxc-execute -n test -f /var/lib/lxc/lxc_test.conf /bin/bash #宿主机test已经存在就不用指定配置文件
(此时即进入一个封闭的shell环境,可以与远程机相互ping通,并与主机共享文件系统,
但是有一个隔离的进程空间,可以ps ax查看与主机的输出不同。在主机上可以查看此容器的状态:lxc-info -n test;lxc-ps)
4.2,创建LXC系统容器;(主机内核启动参数要添加: audit=0)
1,可以使用已存在的操作系统模板去创建LXC系统容器:(templates privides by the OpenVZ project) (注:为了防止创建的系统容器无法登录,需关闭主机系统的audit,禁止掉容器中xx/pam.d/login中的pam_loginuid.so)
下载相应的模板:http://wiki.openvz.org/Download/template/precreated
使用OpenVZ容器:
1.1,解压模板(根文件系统);#mkdir -p /srv/lxc/lxctest #创建容器所在的目录(根目录)#cd /srv/lxc/lxctest#tar xvzf fedora-19-x86_64.tar.gz (根文件系统)1.2,创建配置文件;#cat /etc/lxc/lxc-fedora.conflxc.rootfs = /srv/lxc/lxctest #指定根文件系统目录lxc.mount = /etc/lxc/lxc-fedora.fstab #挂载表lxc.utsname = fedora #设置容器名lxc.network.type=veth #在此设置网络lxc.network.flags=uplxc.network.link=br0lxc.network.name=eth0lxc.network.hwaddr=4a:49:43:49:79:bdlxc.network.ipv4=192.168.1.156 #使用DHCP时为:0.0.0.0//以下为可选lxc.tty = 4
lxc.pts = 1024lxc.cap.drop = sys_module mac_admin mac_override sys_timelxc.autodev = 1# When using LXC with apparmor, uncomment the next line to run unconfined:#lxc.aa_profile = unconfined#cgroupslxc.cgroup.devices.deny = a# /dev/null and zerolxc.cgroup.devices.allow = c 1:3 rwmlxc.cgroup.devices.allow = c 1:5 rwm# consoleslxc.cgroup.devices.allow = c 5:1 rwmlxc.cgroup.devices.allow = c 5:0 rwmlxc.cgroup.devices.allow = c 4:0 rwmlxc.cgroup.devices.allow = c 4:1 rwm# /dev/{,u}randomlxc.cgroup.devices.allow = c 1:9 rwmlxc.cgroup.devices.allow = c 1:8 rwmlxc.cgroup.devices.allow = c 136:* rwmlxc.cgroup.devices.allow = c 5:2 rwm# rtclxc.cgroup.devices.allow = c 254:0 rm1.3,创建挂载表:#cat/etc/lxc/lxc-fedora.fstabnone /srv/lxc/lxctest/dev/pts devpts defaults 0 0none /srv/lxc/lxctest/proc proc defaults 0 0none /srv/lxc/lxctest/sys sysfs defaults 0 01.4,创建初始化容器;lxc-create -n fedora -f /etc/lxc/lxc-fedora.conf删除容器对象:lxc-destory -n fedora (不会删除实际的文件系与配置文件)1.5,修改容器内网络(因为根文件系统是OpenVZ的)cat /srv/lxc/lxctest/etc/sysconfig/network-scripts/ifcfg-eth0DEVICE=eth0 //跟1.2配置文件中一致BOOTPROTO=staticONBOOT=yesIPADDR=192.168.1.156NETMASK=255.255.255.0BROADCAST=192.168.1.2551.6,调整设置根文件系统#chroot /srv/lxc/lxctest #进入容器#useradd user #给容器添加用户#passwd user#chkconfig --list|grep '3:on'#确定开启哪些服务,关闭哪些服务#chkconfig httpd off#chkconfig saslauthd off#rm /etc/mtab #修复mtab表#touch /etc/mtab1.7,设置完成,可以启动lxc-start -n fedoralxc-stop -n fedora
2,LXC也提供了几个脚本工具去创建相应的系统空器:
lxc-fedora lxc-debian lxc-busybox lxc-ubuntu lxc-oracle lxc-sshd lxc-alpine
所有这些脚本工具都会下载一个最小的安装和交互设置容器;
2.1:指定install 参数运行,如:#/usr/share/lxc/templates/lxc-fedora install #会在/var/lib/lxc/目录下生成config,fstab配置文件,rootfs根目录2.2,在此配置文件config,fstab,和根文件系统rootfs基础上创建,修改,运行LXC容器(如上)
4.3,使用systemd包中systemd-nspawn工具
1,安装一个系统容器(容器根目录文件系统)
#yum -y --releasever=19 --nogpg --installroot=/home/lxc --disablerepo='*' --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
2,设置容器root密码
#systemd-nspawn -D /home/lxc #切换根目录到容器根目录 (把容器中/etc/pam.d/login文件中pam_loginuid注释掉)
#passwd
3,启动容器(主机内核启动参数要添加audit=0)
#systemd-nspawn -bD /home/lxc 3
4,为此容器制作一个服务单元(systemd的unit)
cat /etc/systemd/system/mycontainer.service
[Unit]
Description=My test container
[Service]
ExecStart=/usr/bin/systemd-nspawn -jbD /home/lxc 3
KillMode=process
5,重启systemd
#systemctl daemon-reload #重启systemd
#systemctl start mycontainer #启动容器 (在后台运行容器)
#systemctl stop mycontainer #停止容器
4.4,使用libvirt 管理LXC:
(默认uri为qumu:///system,KVM虚拟机,export LIBVIRT_DEFAULT_URI=lxc:///)
例:# cat helloworld.xml (配置文件)
<domain type='lxc'>
<name>helloworld</name>
<memory>102400</memory>
<os>
<type>exe</type>
<init>/bin/sh</init>
</os>
<devices> #指定容器中的设备
<console type='pty'/>
<filesystem type='mount'> #可以指定需要挂载的文件系统和目录(此处是挂了一个根目录)
<source dir='/export/helloword/root'/>
<target dir='/'/>
</filesystem>
<interface type='network'>
<mac address='52:54:00:4d:2b:cd'/>
<source network='default'/>
</interface/>
</devices>
</domain>
1,定义或创建domain:
# virsh --connect lxc:/// define helloword.xml
Domain helloword defined from helloword.xml
创建虚拟机:virsh create helloword.xml
2,启动:# virsh --connect lxc:/// start helloword
Domain helloword started
3,连到虚拟机中:
# virsh --connect lxc:/// console helloword
Connected to domain helloword
4,取消定义:virsh -c lxc:/// undefine helloword
5,销毁:virsh -c lxc:/// destroy helloword
kvm:
内核 kvm.ko +用户态管理工具: yum install libvirt-client virt-viewer virt-manager
pci 设备passthrough3.1,列出当前机上所有设备:
# virsh nodedev-list --tree
3.2,查看设备的域,总线,插槽,功能号等信息:
# virsh nodedev-dumpxml pci_0000_00_0f_0
<device>
<name>pci_0000_00_0f_0</name>
<parent>computer</parent>
<driver>
<name>vmwgfx</name>
</driver>
<capability type='pci'>
<domain>0</domain>
<bus>0</bus>
<slot>15</slot>
<function>0</function>
<product id='0x0405'>SVGA II Adapter</product>
<vendor id='0x15ad'>VMware</vendor>
</capability>
</device>
3.3,与主机断开连接(detach from the system)
# virsh nodedev-dettach pci_0000_00_0f_0
3.4,给客户机添加一个设备(3.2中查询的设备域,总线,插槽,功能号信息);不支持热插拨
# virsh edit win2k3 (domain,客户机名;在<devices>段添加一个设备项)
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x00' slot='0x1a' function='0x7'/>
</source>
</hostdev>
3.5,当客户机启来后,要通知主机不能使用它;
$ readlink /sys/bus/pci/devices/0000\:00\:1d.7/driver
../../../bus/pci/drivers/drivername
3.6,与设备断开连接
$ virsh nodedev-dettach pci_8086_3a6c
3.7,验证现在在pci_stub的控制下:
$ readlink /sys/bus/pci/devices/0000\:00\:1d.7/driver
../../../bus/pci/drivers/pci-stub
3.8,设置sebool来让客户机管理pci设备
$ setsebool -P virt_manage_sysfs 1
3.9,启动客户机
# virsh start win2k3
连接虚拟机:
connect qemu+ssh://virtuser@host2/ #用SSH连接,
connect qemu://host2/ #用TLS连接