mirror of
https://github.com/yeasy/docker_practice.git
synced 2025-08-04 23:02:39 +00:00
修正多個用詞
"s/程序/程式/g" "s/性能/效能/g" "s/如下/以下/g" "s/加載/載入/g" "s/獲取/取得/g" "s/服務器/伺服器/g" "s/信息/訊息/g" "s/註釋/註解/g" "s/裏/裡/g" "s/構建/建立/g" "s/配置/設定/g"
This commit is contained in:
@@ -6,8 +6,8 @@ Docker 底層的核心技術包括 Linux 上的名字空間(Namespaces)、
|
||||
這種直接的做法實做了對資源最完整的封裝,但很多時候往往意味著系統資源的浪費。
|
||||
例如,以宿主機和虛擬機系統都為 Linux 系統為例,虛擬機中執行的應用其實可以利用宿主機系統中的執行環境。
|
||||
|
||||
我們知道,在作業系統中,包括內核、文件系統、網路、PID、UID、IPC、內存、硬盤、CPU 等等,所有的資源都是應用程序直接共享的。
|
||||
我們知道,在作業系統中,包括內核、文件系統、網路、PID、UID、IPC、內存、硬盤、CPU 等等,所有的資源都是應用程式直接共享的。
|
||||
要想實做虛擬化,除了要實做對內存、CPU、網路IO、硬盤IO、存儲空間等的限制外,還要實做文件系統、網路、PID、UID、IPC等等的相互隔離。
|
||||
前者相對容易實做一些,後者則需要宿主機系統的深入支持。
|
||||
|
||||
隨著 Linux 系統對於名字空間功能的完善實做,程序員已經可以實做上面的所有需求,讓某些程序在彼此隔離的名字空間中執行。大家雖然都共用一個內核和某些執行時環境(例如一些系統命令和系統庫),但是彼此卻看不到,都以為系統中只有自己的存在。這種機制就是容器(Container),利用名字空間來做權限的隔離控制,利用 cgroups 來做資源分配。
|
||||
隨著 Linux 系統對於名字空間功能的完善實做,程式員已經可以實做上面的所有需求,讓某些程式在彼此隔離的名字空間中執行。大家雖然都共用一個內核和某些執行時環境(例如一些系統命令和系統庫),但是彼此卻看不到,都以為系統中只有自己的存在。這種機制就是容器(Container),利用名字空間來做權限的隔離控制,利用 cgroups 來做資源分配。
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
控制組([cgroups](http://en.wikipedia.org/wiki/Cgroups))是 Linux 內核的一個特性,主要用來對共享資源進行隔離、限制、審計等。只有能控制分配到容器的資源,才能避免當多個容器同時執行時的對系統資源的競爭。
|
||||
|
||||
控制組技術最早是由 Google 的程序員 2006 年起提出,Linux 內核自 2.6.24 開始支持。
|
||||
控制組技術最早是由 Google 的程式員 2006 年起提出,Linux 內核自 2.6.24 開始支持。
|
||||
|
||||
控制組可以提供對容器的內存、CPU、磁盤 IO 等資源的限制和審計管理。
|
||||
|
||||
|
@@ -2,21 +2,21 @@
|
||||
名字空間是 Linux 內核一個強大的特性。每個容器都有自己單獨的名字空間,執行在其中的應用都像是在獨立的作業系統中執行一樣。名字空間保證了容器之間彼此互不影響。
|
||||
|
||||
### pid 名字空間
|
||||
不同使用者的程序就是透過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 程序在 Docker 中的父程序為Docker程序,每個 LXC 程序具有不同的名字空間。同時由於允許嵌套,因此可以很方便的實做嵌套的 Docker 容器。
|
||||
不同使用者的程式就是透過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 程式在 Docker 中的父程式為Docker程式,每個 LXC 程式具有不同的名字空間。同時由於允許嵌套,因此可以很方便的實做嵌套的 Docker 容器。
|
||||
|
||||
### net 名字空間
|
||||
有了 pid 名字空間, 每個名字空間中的 pid 能夠相互隔離,但是網路端口還是共享 host 的端口。網路隔離是透過 net 名字空間實做的, 每個 net 名字空間有獨立的 網路設備, IP 地址, 路由表, /proc/net 目錄。這樣每個容器的網路就能隔離開來。Docker 默認采用 veth 的方式,將容器中的虛擬網卡同 host 上的一 個Docker 網橋 docker0 連接在一起。
|
||||
|
||||
### ipc 名字空間
|
||||
容器中程序交互還是采用了 Linux 常見的程序間交互方法(interprocess communication - IPC), 包括信號量、消息隊列和共享內存等。然而同 VM 不同的是,容器的程序間交互實際上還是 host 上具有相同 pid 名字空間中的程序間交互,因此需要在 IPC 資源申請時加入名字空間信息,每個 IPC 資源有一個唯一的 32 位 id。
|
||||
容器中程式交互還是采用了 Linux 常見的程式間交互方法(interprocess communication - IPC), 包括信號量、消息隊列和共享內存等。然而同 VM 不同的是,容器的程式間交互實際上還是 host 上具有相同 pid 名字空間中的程式間交互,因此需要在 IPC 資源申請時加入名字空間訊息,每個 IPC 資源有一個唯一的 32 位 id。
|
||||
|
||||
### mnt 名字空間
|
||||
類似 chroot,將一個程序放到一個特定的目錄執行。mnt 名字空間允許不同名字空間的程序看到的文件結構不同,這樣每個名字空間 中的程序所看到的文件目錄就被隔離開了。同 chroot 不同,每個名字空間中的容器在 /proc/mounts 的信息只包含所在名字空間的 mount point。
|
||||
類似 chroot,將一個程式放到一個特定的目錄執行。mnt 名字空間允許不同名字空間的程式看到的文件結構不同,這樣每個名字空間 中的程式所看到的文件目錄就被隔離開了。同 chroot 不同,每個名字空間中的容器在 /proc/mounts 的訊息只包含所在名字空間的 mount point。
|
||||
|
||||
### uts 名字空間
|
||||
UTS("UNIX Time-sharing System") 名字空間允許每個容器擁有獨立的 hostname 和 domain name, 使其在網路上可以被視作一個獨立的節點而非 主機上的一個程序。
|
||||
UTS("UNIX Time-sharing System") 名字空間允許每個容器擁有獨立的 hostname 和 domain name, 使其在網路上可以被視作一個獨立的節點而非 主機上的一個程式。
|
||||
|
||||
### user 名字空間
|
||||
每個容器可以有不同的使用者和組 id, 也就是說可以在容器內用容器內部的使用者執行程序而非主機上的使用者。
|
||||
每個容器可以有不同的使用者和組 id, 也就是說可以在容器內用容器內部的使用者執行程式而非主機上的使用者。
|
||||
|
||||
*註:關於 Linux 上的名字空間,[這篇文章](http://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/) 介紹的很好。
|
||||
|
@@ -11,29 +11,29 @@ Linux 透過在內核中進行數據復制來實做虛擬接口之間的數據
|
||||
Docker 容器網路就利用了這項技術。它在本地主機和容器內分別建立一個虛擬接口,並讓它們彼此連通(這樣的一對接口叫做 `veth pair`)。
|
||||
|
||||
### 建立網路參數
|
||||
Docker 建立一個容器的時候,會執行如下操作:
|
||||
Docker 建立一個容器的時候,會執行以下操作:
|
||||
* 建立一對虛擬接口,分別放到本地主機和新容器中;
|
||||
* 本地主機一端橋接到默認的 docker0 或指定網橋上,並具有一個唯一的名字,如 veth65f9;
|
||||
* 容器一端放到新容器中,並修改名字作為 eth0,這個接口只在容器的名字空間可見;
|
||||
* 從網橋可用地址段中獲取一個空閑地址分配給容器的 eth0,並配置默認路由到橋接網卡 veth65f9。
|
||||
* 從網橋可用地址段中取得一個空閑地址分配給容器的 eth0,並設定默認路由到橋接網卡 veth65f9。
|
||||
|
||||
完成這些之後,容器就可以使用 eth0 虛擬網卡來連接其他容器和其他網路。
|
||||
|
||||
可以在 `docker run` 的時候透過 `--net` 參數來指定容器的網路配置,有4個可選值:
|
||||
可以在 `docker run` 的時候透過 `--net` 參數來指定容器的網路設定,有4個可選值:
|
||||
* `--net=bridge` 這個是默認值,連接到默認的網橋。
|
||||
* `--net=host` 告訴 Docker 不要將容器網路放到隔離的名字空間中,即不要容器化容器內的網路。此時容器使用本地主機的網路,它擁有完全的本地主機接口訪問權限。容器程序可以跟主機其它 root 程序一樣可以打開低範圍的端口,可以訪問本地網路服務比如 D-bus,還可以讓容器做一些影響整個主機系統的事情,比如重啟主機。因此使用這個選項的時候要非常小心。如果進一步的使用 `--privileged=true`,容器會被允許直接配置主機的網路堆棧。
|
||||
* `--net=container:NAME_or_ID` 讓 Docker 將新建容器的程序放到一個已存在容器的網路棧中,新容器程序有自己的文件系統、程序列表和資源限制,但會和已存在的容器共享 IP 地址和端口等網路資源,兩者程序可以直接透過 `lo` 環回接口通信。
|
||||
* `--net=none` 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路配置。之後,使用者可以自己進行配置。
|
||||
* `--net=host` 告訴 Docker 不要將容器網路放到隔離的名字空間中,即不要容器化容器內的網路。此時容器使用本地主機的網路,它擁有完全的本地主機接口訪問權限。容器程式可以跟主機其它 root 程式一樣可以打開低範圍的端口,可以訪問本地網路服務比如 D-bus,還可以讓容器做一些影響整個主機系統的事情,比如重啟主機。因此使用這個選項的時候要非常小心。如果進一步的使用 `--privileged=true`,容器會被允許直接設定主機的網路堆棧。
|
||||
* `--net=container:NAME_or_ID` 讓 Docker 將新建容器的程式放到一個已存在容器的網路棧中,新容器程式有自己的文件系統、程式列表和資源限制,但會和已存在的容器共享 IP 地址和端口等網路資源,兩者程式可以直接透過 `lo` 環回接口通信。
|
||||
* `--net=none` 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路設定。之後,使用者可以自己進行設定。
|
||||
|
||||
### 網路配置細節
|
||||
使用者使用 `--net=none` 後,可以自行配置網路,讓容器達到跟平常一樣具有訪問網路的權限。透過這個過程,可以了解 Docker 配置網路的細節。
|
||||
### 網路設定細節
|
||||
使用者使用 `--net=none` 後,可以自行設定網路,讓容器達到跟平常一樣具有訪問網路的權限。透過這個過程,可以了解 Docker 設定網路的細節。
|
||||
|
||||
首先,啟動一個 `/bin/bash` 容器,指定 `--net=none` 參數。
|
||||
```
|
||||
$ sudo docker run -i -t --rm --net=none base /bin/bash
|
||||
root@63f36fc01b5f:/#
|
||||
```
|
||||
在本地主機查找容器的程序 id,並為它建立網路命名空間。
|
||||
在本地主機查找容器的程式 id,並為它建立網路命名空間。
|
||||
```
|
||||
$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
|
||||
2778
|
||||
@@ -41,7 +41,7 @@ $ pid=2778
|
||||
$ sudo mkdir -p /var/run/netns
|
||||
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
|
||||
```
|
||||
檢查橋接網卡的 IP 和子網掩碼信息。
|
||||
檢查橋接網卡的 IP 和子網掩碼訊息。
|
||||
```
|
||||
$ ip addr show docker0
|
||||
21: docker0: ...
|
||||
@@ -54,7 +54,7 @@ $ sudo ip link add A type veth peer name B
|
||||
$ sudo brctl addif docker0 A
|
||||
$ sudo ip link set A up
|
||||
```
|
||||
將B放到容器的網路命名空間,命名為 eth0,啟動它並配置一個可用 IP(橋接網段)和默認網關。
|
||||
將B放到容器的網路命名空間,命名為 eth0,啟動它並設定一個可用 IP(橋接網段)和默認網關。
|
||||
```
|
||||
$ sudo ip link set B netns $pid
|
||||
$ sudo ip netns exec $pid ip link set dev B name eth0
|
||||
@@ -62,8 +62,8 @@ $ sudo ip netns exec $pid ip link set eth0 up
|
||||
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
|
||||
$ sudo ip netns exec $pid ip route add default via 172.17.42.1
|
||||
```
|
||||
以上,就是 Docker 配置網路的具體過程。
|
||||
以上,就是 Docker 設定網路的具體過程。
|
||||
|
||||
當容器結束後,Docker 會清空容器,容器內的 eth0 會隨網路命名空間一起被清除,A 接口也被自動從 `docker0` 卸載。
|
||||
|
||||
此外,使用者可以使用 `ip netns exec` 命令來在指定網路名字空間中進行配置,從而配置容器內的網路。
|
||||
此外,使用者可以使用 `ip netns exec` 命令來在指定網路名字空間中進行設定,從而設定容器內的網路。
|
||||
|
@@ -1,10 +1,10 @@
|
||||
## Union 文件系統
|
||||
Union文件系統([UnionFS](http://en.wikipedia.org/wiki/UnionFS))是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。
|
||||
Union文件系統([UnionFS](http://en.wikipedia.org/wiki/UnionFS))是一種分層、輕量級並且高效能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。
|
||||
|
||||
Union 文件系統是 Docker 鏡像的基礎。鏡像可以透過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
|
||||
|
||||
另外,不同 Docker 容器就可以共享一些基礎的文件系統層,同時再加上自己獨有的改動層,大大提高了存儲的效率。
|
||||
|
||||
Docker 中使用的 AUFS(AnotherUnionFS)就是一種 Union FS。 AUFS 支持為每一個成員目錄(類似 Git 的分支)設定唯讀(readonly)、讀寫(readwrite)和寫出(whiteout-able)權限, 同時 AUFS 裏有一個類似分層的概念, 對唯讀權限的分支可以邏輯上進行增量地修改(不影響唯讀部分的)。
|
||||
Docker 中使用的 AUFS(AnotherUnionFS)就是一種 Union FS。 AUFS 支持為每一個成員目錄(類似 Git 的分支)設定唯讀(readonly)、讀寫(readwrite)和寫出(whiteout-able)權限, 同時 AUFS 裡有一個類似分層的概念, 對唯讀權限的分支可以邏輯上進行增量地修改(不影響唯讀部分的)。
|
||||
|
||||
Docker 目前支持的 Union 文件系統種類包括 AUFS, btrfs, vfs 和 DeviceMapper。
|
||||
|
Reference in New Issue
Block a user