天天看點

Docker從入門到實戰(一)

Docker從入門到實戰(一)

容器技術并不是一個全新的概念,它又稱為容器虛拟化。虛拟化技術目前主要有硬體虛拟化、半虛拟化、作業系統虛拟化等。

1.1關于虛拟化

虛拟化技術的分類與定義在不同領域有不同的了解。對于計算機領域,虛拟化技術主要分為兩大類:一類基于硬體虛拟化,另一類基于軟體虛拟化。硬體虛拟化并不多見,大都是半虛拟化與軟體結合,應用較為廣泛的則是基于軟體的虛拟化技術。

基于軟體虛拟化又可分為應用虛拟化(如Wine)和平台虛拟化(如虛拟機),容器技術屬于作業系統虛拟化,屬于平台虛拟化的一種。

Docker從入門到實戰(一)

1.2容器的定義

所謂容器,顧名思義就是來放東西的道具。在剛進入國内時,還有一段時間在讨論Container這個單詞翻譯為“容器合适”,還是翻譯為“集裝箱”合适。大可把容器了解為一個沙盒,每個容器是獨立的,容器間可以互相通信。

如果說工業上的集裝箱是從一個箱子開始的,那麼軟體行業的容器則是從檔案系統隔離開始的。

2015年微軟公司也在Windows Server上為其基于Windows的應用添加了容器支援,稱之為Windows Containers,與Windows Server 2016一同釋出,通過該實作,Docker可以原生的在Windows上運作Docker容器,而不需要再啟動一個虛拟機來運作Docker(Windows上早期運作Docker需要使用Linux虛拟機)。同年,MacOS也原生支援運作Docker容器。

容器本質上是主控端上的程序。容器技術通過namespace實作資源隔離,通過Cgroups(Google公司的Control Groups技術,2007年被合并到Linux2.6.24核心中)實作資源控制,通過rootfs實作檔案系統隔離,再加上容器搜尋引擎自身的特性來管理容器的生命周期。

3.1認識namespace

在分布式的環境下,容器必須要有獨立的IP、端口和路由等,自然就有了網絡隔離。同時,程序通信隔離、權限隔離等也要考慮到,是以基本上一個容器需要做到6項基本隔離。

Docker從入門到實戰(一)

對namespace的操作主要通過clone(),setns(),unshare()這三個系統調用來完成的。

3.1.1檢視目前的namespance

root使用者:ls -l /proc/$$/ns

Docker從入門到實戰(一)

這裡$$指的是目前程序ID号,可以看到4026531839這樣的數字,表示目前程序指向的namespace.當兩個程序指向同一串數字時,表示他們處于同一個namespace下。

3.1.2使用clone()建立新的namespace

建立一個namespace的方法是使用clone()系統調用,它會建立一個新的程序。為了說明建立的過程,給出clone()的原型如下:

int clone (int(child_func) (void ) , void child_stack, int flags , voidarg) ;

如果調用clone()時設定了一個CLONE_NEW的标志,一個與之對應的新的命名空間将被建立,新的程序屬于該命名空間,可以使用多個CLONE_NEW标志的組合。

3.1.3使用一個sents()關聯一個已經存在namespace

當一個namespace沒有程序時還保持打開,這麼做是為了後續添加程序到該namesapce.而添加這個功能就是使用sents()系統調用來完成,這使得調用的程序能夠和namespace關聯,docker exec 就需要用到這個方法:

int setns (int fd, int nstyps);

fd參數指明了關聯的namespace,其指向了\proc\PID\ns目錄系一個符号連接配接的檔案描述符。可以通過發開這些符号連結指向的檔案或者打開一個綁定到符号連結的檔案來獲得檔案描述符。

nstype參數運作調用者檢查fd指向的命名空間的類型,如果這個參數等于數,将不會檢查,當調用者已經知道namespace的類型時這會很有用。當nstype被指派為CLONE_NEW*的常量時,核心會檢查fd指向的namespace的類型。

要把namespace利用起來,還要使用execve()函數(或者其他的exec()函數),使得我們能夠建構一個簡單但是有用的工具,該函數可以執行使用者指令。

3.1.4使用unshare()在已有程序上進行namespace隔離

unshare()和clone()有些像,不同的地方是前者運作在原有程序上,相當于跳出原來namespace操作,Linux自帶的unshare()就是通過調用unshare()這個API來實作。

[root@VM_110_98_centos ~]# unshare --help

Usage:

unshare [options] <program> [<argument>...]

Run a program with some namespaces unshared from the parent.

Options:

-m, --mount unshare mounts namespace

-u, --uts unshare UTS namespace (hostname etc)

-i, --ipc unshare System V IPC namespace

-n, --net unshare network namespace

-p, --pid unshare pid namespace

-U, --user unshare user namespace

-f, --fork fork before launching <program>

--mount-proc[=<dir>] mount proc filesystem first (implies --mount)

-r, --map-root-user map current user to root (implies --user)

--propagation <slave|shared|private|unchanged>

modify mount propagation in mount namespace

-s, --setgroups allow|deny control the setgroups syscall in user namespaces

-h, --help display this help and exit

-V, --version output version information and exit

For more details see unshare(1).

由于docker沒有使用這個系統調用,是以不展開。

3.2 認識Cgroups

Cgroups是linux核心提供的一種可以限制、記錄、隔離程序組(process groups)所使用的實體資源(如CPU,記憶體,I/O等)的機制。最初由Google公司的工程師提出看,後來被整合經linux核心。

這麼說了解起來有點吃力,我們通過指令來挂載cgroupfs

提示已經挂載,這個動作一般情況下已經在linux啟動的時候做了。

Docker從入門到實戰(一)

在主流linux發行版下,都可以通過/etc/cgconfig.conf或者cgroup-bin的相關指令來配置Cgroups。

mount {

cpuset = /sys/fs/cgroup/cpuset;

momory = /sys/fs/cgroup/momory;

}

group cnsworder/test {

perm {

task {

uid = root;

gid = root;

admin {

cpu {

cpu.shares = 1000;

然後通過指令行把一個程序移動到這個Cgroups之中。

#mount -t group -o cpu cpu /sys/fs/cgroup/cpuset

#cgcreate -g cpu,momory:/cnsworder

#chown root:root /sys/fs/cgroup/cpuset/cnsworder/test/*

#chown root:root /sys/fs/cgroup/cpuset/cnsworder/test/task

#cgrun -g cpu,momory:/cnsworder/test bash

3.3容器的建立

3.3.1系統調用clone()建立新程序,擁有自己的namespace

該程序擁有自己的pid,mount,user,net,ipc和uts namespace。

#pid =clone(fun,stack,flags,clone_arg);

3.3.2将pid寫入Cgroup子系統這樣就受到Cgroups子系統控制

#echo$pid >/sys/fs/cgroup/cpu/tasks

#echo$pid >/sys/fs/cgroup/cpuset/tasks

#echo$pid >/sys/fs/cgroup/bikio/tasks

#echo$pid >/sys/fs/cgroup/memory/tasks

#echo$pid >/sys/fs/cgroup/devices/tasks

#echo$pid >/sys/fs/cgroup/feezer/tasks

3.3.3通過pivot_root系統調用,使程序進入一個新的rootfs,之後通過exec()系統調用,在新的namespace,Cgroups,rootfs中執行/bin/bash.

fun () {

pivot_root ("path_of_rootfs/", path);

exec ("/bin/bash");

通過上面的操作,成功的在一個容器中運作了/bin/bash。

3.4 容器雲

雖然Docker提供了較為便捷的操作方式,但是在開發、生産環境中網路、存儲、叢集和高可用等問題層出不窮。僅憑Docker是無法做到面面俱到,于是就從容器到容器雲就成了容器技術的 必然發展途徑。

完整來說,容器雲是以容器為資源分割和排程的基本機關,通過容器封裝軟體運作環境,為使用者提供一個集建構,釋出和運作于一體的分布式應用平台。它與IaaS(Platform as a Service,也就是平台即服務)、PaaS等不同,容器雲可以共享與隔離資源、編排與部署容器。在這點上容器雲與IaaS相似。但是容器雲也可以***到應用支撐與運作時環境,在這一點上與PaaS 類似。

文中所有内容皆為手動敲出來的,難免有疏忽之處,歡迎評論指正!

後續文檔Docker從入門到實戰(二)連結 http://blog.51cto.com/12943999/2072592