lxc介紹
LXC又名Linux container,是一種虛擬化的解決方案,這種是內核級的虛擬化。(主流的解決方案Xen ,KVM, LXC)
Linux Container容器是一種內核虛擬化技術,可以提供輕量級的虛擬化,以便隔離進程和資源。可以最大效率隔離進程和資源。它可以把傳統虛擬技術以及后來的Xen、KVM的VM進程像HOST進程一樣運行管理, 所以創建和銷毀都非常輕。
如果說LXC着眼點在於提供輕量級的虛擬技術,扎根在虛擬機,那Docker則定位於應用。
概述
LXC架構的介紹
通過namespace進行資源的隔離,Guest1下的進程與Guset2下的進程是獨立的,可以看作運行在兩台物理機上一樣。Contaniner管理工具就是對Guest進行管理的(創建、銷毀)。
圖是對LXC架構的介紹
下圖是LXC與KVM技術的比較,KVM的優點是一個物理機上可以跑多個操作系統(Guest-OS),然后在每個操作系統運行應用,通過這種方式實現應用的隔離。而使用LXC技術直接可以在Host-OS的基礎上實現隔離的。這就是LXC的優勢--運行快。但是,如果有兩個應用一個是在windows運行的,一個是在linux上運行的,這時只能使用KVM技術來實現了。
container管理工具
container與KVM的比較
container並未實現完全虛擬化,在Guest-OS中執行的一些操作會直接影響到HOST-OS。下面是兩者的對比。
LXC具體組成
LXC項目在Sourceforge上面的,它有一個Linux內核補丁和一些用戶空間的工具組成,其中內核補丁提供底層新特性,上層工具使用這些新特性,提供一套簡化的工具來維護容器。
LXC在資管管理方面,依賴與Linux內核密切相關的Cgroups子系統,這個子系統是Linux內核提供的一個基於進程組的資源管理框架,可以為特定的進程組限定可以使用的資源,借助cgroups子系統,在當前Linux環境下,實現一個輕量化的虛擬機。
LXC在隔離控制方面,依賴於Linux內核提供的namespace特性,具體來說,就是在clone的時候加入相應的flag。
LXC的優勢
LXC是操作系統層面的虛擬化技術,與傳統的HAL層次的虛擬化技術相比,有以下優勢:
1. 更小的虛擬化開銷。LXC的諸多特性基本有內核提供
2. 快速部署。只需要安裝LXC,就可以利用LXC的相關命令來創建並且啟動容器,為應用提供虛擬執行環節。而傳統的虛擬化技術,需要先創建虛擬機,然后安裝系統,再部署應用。
3. 虛擬機的rootfs就在/var/lib/lxc/container_name ,可以在宿主機上輕松修改container的文件系統。
4. LXC使用apparmor,應用程序訪問控制系統來確保主機不受容器內實例的惡意行為。
LXC的缺點
1. 缺少對磁盤限額(disk quota)的支持,目前使用LVM來限定支持。
2. 缺少對寫時復制(copy on write)的支持,對於每個容器來說,都是一份操作系統的用戶態實例,都有屬於自己的系統庫函數文件等必需文件。在一個系統有多個容器的情況下,這會造成磁盤空間的浪費。這里可以借鑒寫時復制的概念,對於容器共用的文件,在沒有對共享文件進行寫入之前,可以只保存一份拷貝,其他容器采用硬鏈接的方式來共享,當有容器對共享文件進行寫入時,為其單獨創建一份拷貝。
3. 進程和容器之間的動態關聯還不夠完善
理想情況下,進程和容器之間是動態關聯的,進程可以在容器之間遷移。在LXC中,資源管理是通過cgroups實現的,進程可以在cgroup之間有條件的遷移。命名空間的隔離是通過namespace實現的,目前內核只支持進程變更有限的幾類命名空間。
4. 不支持checkpoint
checkpoint技術可以將容器中所有的進程暫時frozen,將當時容器完整的狀態存儲在磁盤上,類似於Vmware的snapshot,目前LXC不支持checkpoint技術,只是借助cgroups的freezer子系統,將進程暫時frozen和resume,沒有完整的存儲容器的狀態。
5. 不支持容器的動態遷移
動態遷移是指將正在運行的容器從一個機器上遷移到另一個機器上,在此過程中,容器中的進程無需停止,此項技術可以用來優化服務器集群的資源配置。目前LXC不支持動態遷移。
namespace介紹
Linux Namespaces機制提供一種資源隔離方案。PID,IPC,Network等系統資源不再是全局性的(在Linux2.6內核以前是全局的),而是屬於特定的Namespace。每個Namespace里面的資源對其他Namespace都是透明的。namespace是container中使用到的重要技術之一,是對系統資源的操作上的隔離。使Guest-OS1的操作對Guest-OS2無法產生影響。
當然namespace的實現還在完善中,下面是3.8以上的內核實現的namespace
Mount
Mount namespace是對掛載的文件系統布局進行隔離。圖中顯示在Namespace1中的進程看到的文件系統的掛載方式是一致的,但是在Mount Namespace2中看到的是一另一種情況
IPC
處於同一namespace下的進程才可以進行進程間通信。
NET
NET NAMESPACE實現網絡協議棧上的隔離,在自己的namespace中對網絡的設置只能在本namespace中生效。
PID
我們通過fork來創建進程時可以為每個進程指定命名空間。linux下的進程關系是一棵樹,所以有了父命名空間和子名字空間之分。
在namespace2創建的P2進程有兩個pid。第一個是在父命名空間的下的它的PID號,一個是在自己空間下的PID號。之所以有父pid號是因為P2最終還是在父命名空間下運行的,而為進程指定命名空間是為了讓P2和P3實現隔離。
USER
User namespace中使用到了map轉換,由於container並不是真正的虛擬化,所以在Guest-OS中創建的root用戶會被映射到Host-OS中的普通用戶中去。
下圖中的例子中,root用戶在自己的namespace下創建了一個文件,那這個文件的所有者ID應該是0,當時在磁盤上存的時候文件UID會被轉換為kuid,並且所有者ID為1000。想說名一點是在Guest-OS下你是個root用戶,但是在Host-OS你只不過被轉為一個普通用戶而已。因為我們知道在Host-OS下已經有一個root用戶了。
system API/ABI
linux下的proc目錄是對整個系統狀態的描述,用戶可以通過查看proc目錄來了解當前的系統狀態。在proc目錄下有很多數字,這些數字對應的是系統創建的進程ID,以前我們說進程是看不見摸不着的,但是通過proc目錄我們的確可以看到一些關於進程的信息。
每個進程下有個ns目錄,在目下記錄了該進程使用的到namespace
相關函數
1.clone函數的使用
clone函數是系統的API,是用於創建進程的。我們常用到的fork函數其實底層調用的是clone函數。在使用clone函數的可以為其指定namespace。下面是一個指定IPC名字空間的例子。
p2會運行在新的IPC namespace中,其他namespace會從P1繼承下來
2.unshare函數
unshare函數用於修改當前的進程的namespace的信息。比如更換當前進程的namespace等等。
3.setns函數
將當前進程的namespace設置為另一進程的namespace
參考博文
http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/
http://www.open-open.com/lib/view/open1427350543512.html
http://www.cnblogs.com/wang_yb/p/3923040.html
https://linux.cn/article-5019-1.html
http://blog.csdn.net/preterhuman_peak/article/details/40857117