Linux 容器在 v2.6.29版本之后就加入到內(nèi)核之中了, 之前雖然也聽說過, 但一直沒有太留心, 一直使用 KVM 來創(chuàng)建虛擬機(jī).直至最近 Docker 大出風(fēng)頭, 才開始關(guān)注. 想了解一下 Linux 容器究竟是什么? 與現(xiàn)有虛擬機(jī)技術(shù)(Xen, KVM等)有什么區(qū)別?
Linux 容器技術(shù)出現(xiàn)的很早, 其實(shí)也是一直虛擬化技術(shù), 但似乎一直沒有 Xen, KVM 這些來的出名.同時(shí), 在實(shí)現(xiàn)原理上, 和Xen, KVM之類的也是有很大區(qū)別的.下面簡(jiǎn)單說明下目前4類虛擬技術(shù)的區(qū)別: (下面說明中, VM:虛擬機(jī), HOST:主機(jī), 即安裝虛擬機(jī)的機(jī)器)
傳統(tǒng)的虛擬化技術(shù) (VirtualBox, VMware) 通過在Linux上安裝虛擬化軟件, 然后通過虛擬化軟件來安裝虛擬機(jī)系統(tǒng), 大致結(jié)構(gòu)如下:
| VM1VM2VM3...... |
| VirtualBoxorVMWareor... |
| LinuxKernel |
| 硬件 |
VM是由虛擬化軟件(VirtualBox, VMWare…)來管理的, Linux Kernel不能直接管理到各個(gè)VM.
Xen (半虛擬化) Xen是Linux上歷史比較長(zhǎng)的虛擬化技術(shù), 它的虛擬化結(jié)構(gòu)大致如下:
| LinuxKernelVM1VM2VM3...... |
| Xen |
| 硬件 |
Xen的虛擬化原理是在 Linux Kernel和硬件之間加入一層 Xen代碼, 有Xen來管理Linux Kernel和其它的VM.
KVM (最新的虛擬化技術(shù)) 相比其它的虛擬化技術(shù), KVM是比較新的, 它需要CPU的支持. 它的虛擬化結(jié)構(gòu)大致如下:
| VM1VM2VM3...... |
| KVM(由內(nèi)核管理) |
| LinuxKernel |
| 硬件 |
這個(gè)結(jié)構(gòu)和傳統(tǒng)的虛擬化技術(shù)很類似, 有一點(diǎn)不同的是, KVM和Linux Kernel是緊密結(jié)合的,所以Linux Kernel能夠更好的管理 VMs, VM的性能會(huì)比傳統(tǒng)的虛擬化技術(shù)更好.
Linux 容器 (LXC - linux container) LXC 是非常輕量級(jí)的, 它將 VM 的進(jìn)程也偽裝成 HOST 的進(jìn)程. 大致的結(jié)構(gòu)如下:
| p1(HOST),p2(VM),p3(VM),p4(HOST)...... |
| LinuxKernel |
| 硬件 |
那么, 對(duì)于某些系統(tǒng)進(jìn)程, PID是固定的, 比如 init進(jìn)程的PID=1, VM中的 init進(jìn)程的PID是如何處理的呢?原來, VM的 init進(jìn)程的PID在 HOST的進(jìn)程表中會(huì)顯示成其它PID(>1).
從上面可以看出, LXC這種虛擬化, VM的進(jìn)程就像HOST的進(jìn)程一樣運(yùn)行, 管理, 所以創(chuàng)建和銷毀都是非常快速的.
注: 參考 http://veck.logdown.com/posts/200566-compare-of-kvm-and-lxc
Linux 容器相關(guān)的2個(gè)重要概念Linux容器功能是基于 cgroups 和 Namespace 來實(shí)現(xiàn)的. 所以要了解 Linux 容器必須先了解 cgroup 和 Namespace.
cgroupscgroups 是將任意進(jìn)程進(jìn)行分組化管理的 Linux 內(nèi)核功能.通過cgroups可以有效的隔離各類進(jìn)程, 同時(shí)還可以控制進(jìn)程的資源占用(CPU, 內(nèi)存等等)情況.使用示例: (debian v7.6 x86_64)
mount -t tmpfs cgroup_root /sys/fs/cgroupmkdir /sys/fs/cgroup/testmount -t cgroup -ocpuset test /sys/fs/cgroup/test此時(shí), test目錄就是一個(gè) cgroup, 這里 -o 指定了 cpuset, cpuset是Linux中既定的一種cgroup, 后面有時(shí)間重新寫博客詳細(xì)介紹.test 目錄有cgroup必須的各個(gè)文件
cd /sys/fs/cgroup/testls -ltotal 0-rw-r--r-- 1 root root 0 Aug 14 14:34 cgroup.clone_children--w--w--w- 1 root root 0 Aug 14 14:34 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 14 14:34 cgroup.PRocs-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mems-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 14 14:34 notify_on_release-rw-r--r-- 1 root root 0 Aug 14 14:34 release_agent-rw-r--r-- 1 root root 0 Aug 14 14:34 tasks其中部分文件介紹.
| 文件名 | R/W | 用途 |
|---|---|---|
| release_agent | RW | 刪除分組時(shí)執(zhí)行的命令. 這個(gè)文件只存在于根分組 |
| notify_on_release | RW | 設(shè)置是否執(zhí)行 release/_agent. 為1時(shí)執(zhí)行 |
| tasks | RW | 屬于分組的線程 TID 列表 |
| cgroup.procs | R | 屬于分組的進(jìn)程 PID 列表. 僅包括多線程進(jìn)程的線程leader的TID, 這點(diǎn)與 tasks 不同 |
| cgroup.event_control | RW | 監(jiān)視狀態(tài)變化的分組刪除事件的配置文件 |
在cgroup中還可以建立子cgroup, 建立的方法很簡(jiǎn)單, 只要?jiǎng)?chuàng)建文件夾即可.
cd /sys/fs/cgroup/testmkdir test-childls -l test-child # 創(chuàng)建了文件夾之后, 自動(dòng)生成cgroup需要的文件total 0-rw-r--r-- 1 root root 0 Aug 14 15:10 cgroup.clone_children--w--w--w- 1 root root 0 Aug 14 15:10 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 14 15:10 cgroup.procs-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mems-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 14 15:10 notify_on_release-rw-r--r-- 1 root root 0 Aug 14 15:10 tasks注意, 刪除子cgroup的時(shí)候, 要用 rmdir 來刪除文件夾, 用 rm -rf 的方法無法刪除
cd /sys/fs/cgroup/testrmdir test-child注: 參考內(nèi)核文檔 Documentation/cgroups/cgroups.txt
Namespace (命名空間)使用Namespace, 可以讓每個(gè)進(jìn)程組有獨(dú)立的PID, ipC和網(wǎng)絡(luò)空間.Namespace的生效主要是通過 clone系統(tǒng)調(diào)用來實(shí)現(xiàn)的.clone系統(tǒng)調(diào)用的第3個(gè)參數(shù)flags就是通過設(shè)置Namespace來劃分資源的.參數(shù)種類如下:
| 名稱 | 說明 |
|---|---|
| CLONE_NEWIPC | 劃分IPC(進(jìn)程間通信)命名空間, 信號(hào)量(semaphore), 共享內(nèi)存, 消息隊(duì)列等進(jìn)程間通信用的資源 |
| CLONE_NEWNET | 劃分網(wǎng)絡(luò)命名空間. 分配網(wǎng)絡(luò)接口 |
| CLONE_NEWNS | 劃分掛載的命名空間. 與chroot同樣分配新的根文件系統(tǒng) |
| CLONE_NEWPID | 劃分 PID 命名空間. 分配新的進(jìn)程ID空間 |
| CLONE_NEWUTS | 劃分 UTS(Universal Time sharing System)命名空間. 分配新的 UTS 空間 |
安裝 LXC
apt-get install lxclxc-checkconfig # 安裝完成后, 用這個(gè)命令檢查系統(tǒng)是否可以使用 lxc# 我的debian系統(tǒng)上有個(gè) missingCgroup namespace: CONFIG_CGROUP_NSmissing# 對(duì)于這個(gè)missing, 可能是由于系統(tǒng)中沒有掛載cgroup導(dǎo)致的, 掛載一個(gè)cgroup即可mount -t cgroup cgroup /mnt/cgroup創(chuàng)建容器 從現(xiàn)有模板創(chuàng)建容器, 比較慢, 需要下載
# 創(chuàng)建一個(gè) debian 系統(tǒng)lxc-create -n test -t debian這樣創(chuàng)建的容器默認(rèn)在 /var/lib/lxc/test 中, 為了將容器創(chuàng)建在我們指定的位置, 可以寫個(gè)簡(jiǎn)單的配置文件lxc.conf, 里面只需要一句
lxc.rootfs = /home/lxc/test然后,
lxc-create -n test -t debian -f /path/to/lxc.conf這樣, 就把容器創(chuàng)建在了 /home/lxc/test 中了, /var/lib/lxc/test 中只有一個(gè) config文件(這個(gè)config文件可以作為 lxc-create 命令 -f 參數(shù)對(duì)應(yīng)配置文件的參考)
啟動(dòng)容器 啟動(dòng)后就進(jìn)行入了虛擬機(jī)的控制臺(tái)了. (果然像傳說一樣, 幾秒就啟動(dòng)完成了 ^_^)
lxc-start -n test停止容器 在主機(jī)中輸入停止的命令.
lxc-stop -n test銷毀容器 銷毀之前, 可以通過 lxc-ls 來查看有幾個(gè)容器
lxc-ls testlxc-destroy -n testlxc-ls注: 參考URL - http://obdnmagazine.blogspot.com/2013/07/tested-lxc-080-rc1-debian-wheezyax3a6.html
容器示例 - 配置python uliweb 開發(fā)環(huán)境嘗試在容器配置一次開發(fā)環(huán)境, 然后通過復(fù)制容器, 形成多個(gè)虛擬機(jī).
# 主機(jī)中root@debian-113:~# uliweb # 主機(jī)中沒有安裝uliweb 軟件包-bash: uliweb: command not foundroot@debian-113:~# lxc-start -n test# 虛擬機(jī)登錄界面, 輸入用戶名和密碼# 虛擬機(jī)中root@test:~# apt-get install pythonroot@test:~# apt-get install python-piproot@test:~# pip install Uliwebroot@test:~# uliweb --versionUliweb version is 0.3.1主機(jī)中設(shè)置網(wǎng)橋, 虛擬機(jī)用橋接方式上網(wǎng), 確保每個(gè)虛擬機(jī)有獨(dú)立的IP
# 主機(jī)中root@debian-113:~# lxc-stop -n testroot@debian-113:~# apt-cache search bridge-utilsroot@debian-113:~# brctl addbr br0# 配置主機(jī)的網(wǎng)橋root@debian-113:/var/lib/lxc/test# cat /etc/network/interfaces # This file describes the network interfaces available on your system# and how to activate them. For more information, see interfaces(5).# The loopback network interfaceauto lo#auto eth0iface lo inet loopback# 追加的網(wǎng)橋配置 auto br0iface br0 inet staticaddress 192.168.1.113netmask 255.255.255.0gateway 192.168.1.1 bridge_ports eth0 bridge_stp on bridge_fd 0root@debian-113:/var/lib/lxc/test# /etc/init.d/networking restart配置容器的網(wǎng)絡(luò)(也是在主機(jī)中修改容器的配置文件)
root@debian-113:/var/lib/lxc/test# cat /var/lib/lxc/test/config... ... (很多默認(rèn)生成的配置)# network <-- 這個(gè) network 相關(guān)的是要追加的lxc.network.type = vethlxc.network.flags = uplxc.network.link = br0lxc.network.name = eth0啟動(dòng)Linux容器, 進(jìn)入虛擬機(jī)
root@debian-113:/var/lib/lxc/test# lxc-start -n test# 登錄進(jìn)入虛擬機(jī), 確認(rèn)虛擬機(jī)的IProot@test:~# cat /etc/network/interfaces <-- 默認(rèn)是自動(dòng)獲取IPauto loiface lo inet loopbackauto eth0iface eth0 inet dhcproot@test:~# ifconfig <-- 我的機(jī)器自動(dòng)分配的 192.168.1.167# 創(chuàng)建一個(gè)簡(jiǎn)單的uliweb工程root@test:~# cd /home/root@test:/home# mkdir CM-webroot@test:/home# cd CM-web/root@test:/home/CM-web# uliweb makeproject testroot@test:/home/CM-web# cd test/root@test:/home/CM-web/test# uliweb makeapp first_approot@test:/home/CM-web/test# uliweb runserver -h 0.0.0.0啟動(dòng)Web服務(wù)后, 就可以在主機(jī)的瀏覽器中 通過 http://192.168.1.167:8000/ 來訪問虛擬機(jī)中的web服務(wù)了.
最后, 復(fù)制一個(gè)新的容器, 也就是再重新生成一個(gè)上面的 python uliweb 開發(fā)環(huán)境
# 在主機(jī)中root@debian-113:~# cd /var/lib/lxcroot@debian-113:/var/lib/lxc# cp -r test test2# 修改 test2/config 如下lxc.utsname = test2 <-- 修改名稱xc.rootfs = /home/lxc/test2 <-- 修改 rootfs位置... ... <-- 其它部分不用修改, 和 test 一樣就行root@debian-113:/var/lib/lxc# cd /home/lxc/root@debian-113:/home/lxc# cp -r test test2 <-- 重新復(fù)制一份 rootfsroot@debian-113:/home/lxc# lxc-start -n test2 <-- 啟動(dòng) test2 虛擬機(jī), 其中環(huán)境和 test一樣, IP會(huì)不一樣, 自動(dòng)獲取的# 進(jìn)入 test2 虛擬機(jī)中, 可以直接啟動(dòng)之前的 uliweb 測(cè)試工程, 也可以從主機(jī)中訪問其web服務(wù).新聞熱點(diǎn)
疑難解答
圖片精選