Linux 容器的使用


Linux 容器的使用

Linux 容器在 v2.6.29版本之后就加入到內核之中了, 之前雖然也聽說過, 但一直沒有太留心, 一直使用 KVM 來創建虛擬機.
直至最近 Docker 大出風頭, 才開始關注. 想了解一下 Linux 容器究竟是什么? 與現有虛擬機技術(Xen, KVM等)有什么區別?

Linux 容器技術出現的很早, 其實也是一直虛擬化技術, 但似乎一直沒有 Xen, KVM 這些來的出名.
同時, 在實現原理上, 和Xen, KVM之類的也是有很大區別的.
下面簡單說明下目前4類虛擬技術的區別: (下面說明中, VM:虛擬機, HOST:主機, 即安裝虛擬機的機器)

  1. 傳統的虛擬化技術 (VirtualBox, VMware)
    通過在Linux上安裝虛擬化軟件, 然后通過虛擬化軟件來安裝虛擬機系統, 大致結構如下:

     VM1  VM2 VM3 ... ...                                   
                 VirtualBox or VMWare or ...                
                    Linux Kernel                            
                     硬件                                   

    VM是由虛擬化軟件(VirtualBox, VMWare…)來管理的, Linux Kernel不能直接管理到各個VM.

  2. Xen (半虛擬化)
    Xen是Linux上歷史比較長的虛擬化技術, 它的虛擬化結構大致如下:

     Linux Kernel  VM1  VM2 VM3 ... ...                     
                     Xen                                    
                     硬件                                   

    Xen的虛擬化原理是在 Linux Kernel和硬件之間加入一層 Xen代碼, 有Xen來管理Linux Kernel和其它的VM.

  3. KVM (最新的虛擬化技術)
    相比其它的虛擬化技術, KVM是比較新的, 它需要CPU的支持. 它的虛擬化結構大致如下:

     VM1  VM2 VM3 ... ...                                   
                     KVM (由內核管理)                       
                    Linux Kernel                            
                     硬件                                   

    這個結構和傳統的虛擬化技術很類似, 有一點不同的是, KVM和Linux Kernel是緊密結合的,
    所以Linux Kernel能夠更好的管理 VMs, VM的性能會比傳統的虛擬化技術更好.

  4. Linux 容器 (LXC - linux container)
    LXC 是非常輕量級的, 它將 VM 的進程也偽裝成 HOST 的進程. 大致的結構如下:

     p1(HOST), p2(VM), p3(VM), p4(HOST)......               
                  Linux Kernel                              
                     硬件                                   

    那么, 對於某些系統進程, PID是固定的, 比如 init進程的PID=1, VM中的 init進程的PID是如何處理的呢?
    原來, VM的 init進程的PID在 HOST的進程表中會顯示成其它PID(>1).

    從上面可以看出, LXC這種虛擬化, VM的進程就像HOST的進程一樣運行, 管理, 所以創建和銷毀都是非常快速的.

: 參考 http://veck.logdown.com/posts/200566-compare-of-kvm-and-lxc

Linux 容器相關的2個重要概念

Linux容器功能是基於 cgroups 和 Namespace 來實現的. 所以要了解 Linux 容器必須先了解 cgroup 和 Namespace.

cgroups

cgroups 是將任意進程進行分組化管理的 Linux 內核功能.
通過cgroups可以有效的隔離各類進程, 同時還可以控制進程的資源占用(CPU, 內存等等)情況.
使用示例: (debian v7.6 x86_64)

mount -t tmpfs cgroup_root /sys/fs/cgroup
mkdir /sys/fs/cgroup/test
mount -t cgroup -ocpuset test /sys/fs/cgroup/test

此時, test目錄就是一個 cgroup, 這里 -o 指定了 cpuset, cpuset是Linux中既定的一種cgroup, 后面有時間重新寫博客詳細介紹.
test 目錄有cgroup必須的各個文件

cd /sys/fs/cgroup/test
ls -l
total 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 刪除分組時執行的命令. 這個文件只存在於根分組
notify_on_release RW 設置是否執行 release\_agent. 為1時執行
tasks RW 屬於分組的線程 TID 列表
cgroup.procs R 屬於分組的進程 PID 列表. 僅包括多線程進程的線程leader的TID, 這點與 tasks 不同
cgroup.event_control RW 監視狀態變化的分組刪除事件的配置文件

在cgroup中還可以建立子cgroup, 建立的方法很簡單, 只要創建文件夾即可.

cd /sys/fs/cgroup/test
mkdir test-child
ls -l test-child    # 創建了文件夾之后, 自動生成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的時候, 要用 rmdir 來刪除文件夾, 用 rm -rf 的方法無法刪除

cd /sys/fs/cgroup/test
rmdir test-child

: 參考內核文檔 Documentation/cgroups/cgroups.txt

Namespace (命名空間)

使用Namespace, 可以讓每個進程組有獨立的PID, IPC和網絡空間.
Namespace的生效主要是通過 clone系統調用來實現的.
clone系統調用的第3個參數flags就是通過設置Namespace來划分資源的.
參數種類如下:

名稱 說明
CLONE_NEWIPC 划分IPC(進程間通信)命名空間, 信號量(semaphore), 共享內存, 消息隊列等進程間通信用的資源
CLONE_NEWNET 划分網絡命名空間. 分配網絡接口
CLONE_NEWNS 划分掛載的命名空間. 與chroot同樣分配新的根文件系統
CLONE_NEWPID 划分 PID 命名空間. 分配新的進程ID空間
CLONE_NEWUTS 划分 UTS(Universal Time sharing System)命名空間. 分配新的 UTS 空間

Linux 容器的使用方法 (以下命令基於 debian v7.5)

  1. 安裝 LXC

    apt-get install lxc
    lxc-checkconfig   # 安裝完成后, 用這個命令檢查系統是否可以使用 lxc
    # 我的debian系統上有個 missing
    Cgroup namespace: CONFIG_CGROUP_NSmissing
    # 對於這個missing, 可能是由於系統中沒有掛載cgroup導致的, 掛載一個cgroup即可
    mount -t cgroup cgroup /mnt/cgroup
    
  2. 創建容器
    從現有模板創建容器, 比較慢, 需要下載

    # 創建一個 debian 系統
    lxc-create -n test -t debian
    

    這樣創建的容器默認在 /var/lib/lxc/test 中, 為了將容器創建在我們指定的位置, 可以寫個簡單的配置文件
    lxc.conf, 里面只需要一句

    lxc.rootfs = /home/lxc/test
    

    然后,

    lxc-create -n test -t debian -f /path/to/lxc.conf
    

    這樣, 就把容器創建在了 /home/lxc/test 中了, /var/lib/lxc/test 中只有一個 config文件(這個config文件可以作為 lxc-create 命令 -f 參數對應配置文件的參考)

  3. 啟動容器
    啟動后就進行入了虛擬機的控制台了. (果然像傳說一樣, 幾秒就啟動完成了 _)

    lxc-start -n test
    
  4. 停止容器
    在主機中輸入停止的命令.

    lxc-stop -n test
    
  5. 銷毀容器
    銷毀之前, 可以通過 lxc-ls 來查看有幾個容器

    lxc-ls
      test
    lxc-destroy -n test
    lxc-ls
    

: 參考URL - http://obdnmagazine.blogspot.com/2013/07/tested-lxc-080-rc1-debian-wheezyax3a6.html

容器示例 - 配置python uliweb 開發環境

嘗試在容器配置一次開發環境, 然后通過復制容器, 形成多個虛擬機.

# 主機中
root@debian-113:~# uliweb   # 主機中沒有安裝uliweb 軟件包
-bash: uliweb: command not found
root@debian-113:~# lxc-start -n test
# 虛擬機登錄界面, 輸入用戶名和密碼
# 虛擬機中
root@test:~# apt-get install python
root@test:~# apt-get install python-pip
root@test:~# pip install Uliweb
root@test:~# uliweb --version
Uliweb version is 0.3.1

主機中設置網橋, 虛擬機用橋接方式上網, 確保每個虛擬機有獨立的IP

# 主機中
root@debian-113:~# lxc-stop -n test
root@debian-113:~# apt-cache search bridge-utils
root@debian-113:~# brctl addbr br0
# 配置主機的網橋
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 interface
auto lo
#auto eth0
iface lo inet loopback

# 追加的網橋配置    
auto br0
iface br0 inet static
address 192.168.1.113
netmask 255.255.255.0
gateway 192.168.1.1
   bridge_ports eth0
   bridge_stp on
   bridge_fd 0

root@debian-113:/var/lib/lxc/test# /etc/init.d/networking restart

配置容器的網絡(也是在主機中修改容器的配置文件)

root@debian-113:/var/lib/lxc/test# cat /var/lib/lxc/test/config
... ... (很多默認生成的配置)

# network  <-- 這個 network 相關的是要追加的
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0

啟動Linux容器, 進入虛擬機

root@debian-113:/var/lib/lxc/test# lxc-start -n test
# 登錄進入虛擬機, 確認虛擬機的IP
root@test:~# cat /etc/network/interfaces  <-- 默認是自動獲取IP
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
root@test:~# ifconfig   <-- 我的機器自動分配的 192.168.1.167
# 創建一個簡單的uliweb工程
root@test:~# cd /home/
root@test:/home# mkdir CM-web
root@test:/home# cd CM-web/
root@test:/home/CM-web# uliweb makeproject test
root@test:/home/CM-web# cd test/
root@test:/home/CM-web/test# uliweb makeapp first_app
root@test:/home/CM-web/test# uliweb runserver -h 0.0.0.0

啟動Web服務后, 就可以在主機的瀏覽器中 通過 http://192.168.1.167:8000/ 來訪問虛擬機中的web服務了.

最后, 復制一個新的容器, 也就是再重新生成一個上面的 python uliweb 開發環境

# 在主機中
root@debian-113:~# cd /var/lib/lxc
root@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  <-- 重新復制一份 rootfs
root@debian-113:/home/lxc# lxc-start -n test2  <-- 啟動 test2 虛擬機, 其中環境和 test一樣, IP會不一樣, 自動獲取的
# 進入 test2 虛擬機中, 可以直接啟動之前的 uliweb 測試工程, 也可以從主機中訪問其web服務.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM