Linux 容器的使用

Linux 容器的使用

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

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

  1. 傳統的虛擬化技術 (VirtualBox, VMware)
    經過在Linux上安裝虛擬化軟件, 而後經過虛擬化軟件來安裝虛擬機系統, 大體結構以下:linux

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

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

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

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

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

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

     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).app

    從上面能夠看出, 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服務.
相關文章
相關標籤/搜索