您好,登錄后才能下訂單哦!
鏈接:https://blog.51cto.com/14320361/2457143
1.1什么是docker
Docker 是一個開源的應用容器引擎,基于 Go 語言 并遵從Apache2.0協議開源。
Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然后發布到任何流行的 Linux 機器上。
1.2.1高效有序利用資源
機器資源有限;
單臺機器得部署多個應用;
應用之間互相隔離;
應用之間不能發生資源搶占,每個應用只能使用事先注冊申請的資源。
1.2.2一次編譯,到處運行
類似于java代碼,應用及依賴的環境構建一次,可以到處運行。
1.2.1Linux的namespace和cgroup簡單理解
namespace:類似于JAVA的命名空間
controll groups : controll (system resource) (for) (process)groups
1.2.2Linux中的namespace
在Linux系統中,可以同時存在多用戶多進程,那么對他們的運行協調管理,通過進程調度和進度管理可以解決,但是,整體資源是有限的,怎么把有限的資源(進程號、網絡資源等等)合理分配給各個用戶所在的進程?
Linux Namespaces機制提供一種資源隔離方案。PID,IPC,Network等系統資源不再是全局性的,而是屬于某個特定的Namespace。每個namespace下的資源對于其他namespace下的資源都是透明,不可見的。因此在操作系統層面上看,就會出現多個相同pid的進程。系統中可以同時存在兩個進程號為0,1,2的進程,由于屬于不同的namespace,所以它們之間并不沖突。而在用戶層面上只能看到屬于用戶自己namespace下的資源,例如使用ps命令只能列出自己namespace下的進程。這樣每個namespace看上去就像一個單獨的Linux系統。
命名空間建立系統的不同視圖, 對于每一個命名空間,從用戶看起來,應該像一臺單獨的Linux計算機一樣,有自己的init進程(PID為0),其他進程的PID依次遞增,A和B空間都有PID為0的init進程,子容器的進程映射到父容器的進程上,父容器可以知道每一個子容器的運行狀態,而子容器與子容器之間是隔離的。
<colgroup style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"></colgroup>
|
namespace
|
引入的相關內核版本
|
被隔離的全局系統資源
|
在容器語境下的隔離效果
Mount namespaces | Linux 2.4.19 | 文件系統掛接點 |
將一個文件系統的頂層目錄掛到另一個文件系統的子目錄上,使它們成為一個整體,稱為掛載。把該子目錄稱為掛載點。
Mount namespace用來隔離文件系統的掛載點, 使得不同的mount namespace擁有自己獨立的掛載點信息,不同的namespace之間不會相互影響,這對于構建用戶或者容器自己的文件系統目錄非常有用。
|
| UTS namespaces | Linux 2.6.19 | nodename 和 domainname |
UTS,UNIX Time-sharing System namespace提供了主機名和域名的隔離。能夠使得子進程有獨立的主機名和域名(hostname),這一特性在Docker容器技術中被用到,使得docker容器在網絡上被視作一個獨立的節點,而不僅僅是宿主機上的一個進程。
|
| IPC namespaces | Linux 2.6.19 | 特定的進程間通信資源,包括System V IPC 和 POSIX message queues |
IPC全稱 Inter-Process Communication,是Unix/Linux下進程間通信的一種方式,IPC有共享內存、信號量、消息隊列等方法。所以,為了隔離,我們也需要把IPC給隔離開來,這樣,只有在同一個Namespace下的進程才能相互通信。如果你熟悉IPC的原理的話,你會知道,IPC需要有一個全局的ID,即然是全局的,那么就意味著我們的Namespace需要對這個ID隔離,不能讓別的Namespace的進程看到。
|
| PID namespaces | Linux 2.6.24 | 進程 ID 數字空間 (process ID number space) |
PID namespaces用來隔離進程的ID空間,使得不同pid namespace里的進程ID可以重復且相互之間不影響。
PID namespace可以嵌套,也就是說有父子關系,在當前namespace里面創建的所有新的namespace都是當前namespace的子namespace。父namespace里面可以看到所有子孫后代namespace里的進程信息,而子namespace里看不到祖先或者兄弟namespace里的進程信息。
|
| Network namespaces | 始于Linux 2.6.24 完成于 Linux 2.6.29 | 網絡相關的系統資源 | 每個容器用有其獨立的網絡設備,IP 地址,IP 路由表,/proc/net 目錄,端口號等等。這也使得一個 host 上多個容器內的同一個應用都綁定到各自容器的 80 端口上。 |
| User namespaces | 始于 Linux 2.6.23 完成于 Linux 3.8) | 用戶和組 ID 空間 |
User namespace用來隔離user權限相關的Linux資源,包括user IDs and group IDs。
這是目前實現的namespace中最復雜的一個,因為user和權限息息相關,而權限又事關容器的安全,所以稍有不慎,就會出安全問題。
在不同的user namespace中,同樣一個用戶的user ID 和group ID可以不一樣,換句話說,一個用戶可以在父user namespace中是普通用戶,在子user namespace中是超級用戶
[root@localhost ~]# docker run -it --name test centos /bin/bash
//進入到容器里面
[root@41052cceb473 /]# ls
//查看一下和宿主機差不多,都是從宿主機鏈接過來的
[root@41052cceb473 /]# uname -r
//查看一下內核,和宿主機也是一樣的
如果虛擬機內服務對內核版有要求,這個服務就不太適合用docker來實現了,因為docker就是共用宿主機的內核,可以使用kvm之類的虛擬機。
[root@localhost ~]# docker pull ubuntu
//使用docker下載一個Ubuntu
[root@localhost ~]# docker images
//查看一下
[root@localhost ~]# docker run -it ubuntu:latest /bin/bash
//進入ubuntu環境
root@afbee6750865:/# ls /
//查看一下
root@48c8dd7b098e:/# uname -r
//查看一下內核
Docker本身不占用任何端口,他一般是在后臺運行,無論在docker里進行什么操作(系統、服務)對于docker來說他們僅僅就是一個進程
Run-?centos系統(nginx,web)
Busybox:欺騙層。欺騙docker中的虛擬機是在自己獨立的環境中
解耦:解除耦合、沖突。
耦合:沖突現象。
1.4 Namespace操作
/proc /sys:虛擬文件系統,偽目錄文件
[root@localhost ~]# cd /proc/
[root@localhost proc]# ls
[root@localhost proc]# echo $$
//當前的進程編號
3864
[root@localhost proc]# cd 3864
[root@localhost 3864]# cd ns
[root@localhost ns]# ll
//可以看到一閃一閃的
[root@localhost ns]# ls
IPC:共享內存、消息列隊
MNT:掛載點、文件系統
NET:網絡棧
PID: 進程編號
USER:用戶、組
UTS:主機名、域名
namespec這六項隔離,實現了容器與宿主機,容器與容器之間的隔離
//創建一個用戶并設置密碼
[root@localhost ns]# useradd bdqn
[root@localhost ns]# echo 123.com | passwd --stdin bdqn
[root@localhost ns]# id bdqn
查看docker進程[root@localhost ns]# docker ps -a
[root@localhost ns]# docker start test
//啟動centos
[root@localhost ns]# docker exec -it test /bin/bash
//進入docker容器
[root@41052cceb473 /]# id dbqn
[root@41052cceb473 /]# echo $$
2.1.1有了namespace為什么還要cgroup:
Docker 容器使用 linux namespace 來隔離其運行環境,使得容器中的進程看起來就像一個獨立環境中運行一樣。但是,光有運行環境隔離還不夠,因為這些進程還是可以不受限制地使用系統資源,比如網絡、磁盤、CPU以及內存 等。關于其目的,一方面,是為了防止它占用了太多的資源而影響到其它進程;另一方面,在系統資源耗盡的時候,linux 內核會觸發 OOM,這會讓一些被殺掉的進程成了無辜的替死鬼。因此,為了讓容器中的進程更加可控,Docker 使用 Linux cgroups 來限制容器中的進程允許使用的系統資源。
2.1.2原理
Linux Cgroup 可為系統中所運行任務(進程)的用戶定義組群分配資源 — 比如 CPU 時間、系統內存、網絡帶寬或者這些資源的組合。可以監控管理員配置的 cgroup,拒絕 cgroup 訪問某些資源,甚至在運行的系統中動態配置 cgroup。所以,可以將 controll groups 理解為 controller (system resource) (for) (process)groups,也就是是說它以一組進程為目標進行系統資源分配和控制。它主要提供了如下功能:
Resource limitation: 限制資源使用,比如內存使用上限以及文件系統的緩存限制。
Prioritization: 優先級控制,比如:CPU利用和磁盤IO吞吐。
Accounting: 一些審計或一些統計,主要目的是為了計費。
Controll: 掛起進程,恢復執行進程。
使用 cgroup,系統管理員可更具體地控制對系統資源的分配、優先順序、拒絕、管理和監控。可更好地根據任務和用戶分配硬件資源,提高總體效率。
在實踐中,系統管理員一般會利用CGroup做下面這些事:
隔離一個進程集合(比如:nginx的所有進程),并限制他們所消費的資源,比如綁定CPU的核。
為這組進程分配其足夠使用的內存
為這組進程分配相應的網絡帶寬和磁盤存儲限制
限制訪問某些設備(通過設置設備的白名單)
[root@localhost ~]# cd /sys/fs/cgroup/
//對cpu,內存限制的目錄
[root@localhost cgroup]# ls
[root@localhost cgroup]# cd cpu
[root@localhost cpu]# ls
cpu.shares:權重
tasks:這個文件內的數字,記錄的是進程編號。PID
[root@localhost cpu]# cd docker/
[root@localhost docker]# ls
[root@localhost docker]# cat tasks
//里面是空的
[root@localhost docker]# cd 41052cceb4739fa8e0ddd2ffa733a78cd1043b3fdff874cd266c009391a34d70/
[root@localhost41052cceb4739fa8e0ddd2ffa733a78cd1043b3fdff874cd266c009391a34d70]# ls
[root@localhost41052cceb4739fa8e0ddd2ffa733a78cd1043b3fdff874cd266c009391a34d70]# cat tasks
[root@localhost ]# docker ps
四大功能:
1) 資源的限制:cgroup可以對進程組使用的資源總額進行限制
2) 優先級分配:通過分配的cpu時間片數量以及硬盤IO帶寬的大小,實際上相當于控制了進程運行的優先級別
3) 資源統計: group可以統計系統資源使用量,比如gpu使用時間,內存使用量等,用于按量計費。同時還支持掛起動能,也就是說通過cgroup把所有 資源限制起來,對資源都不能使用,注意著并不是說我們的程序不能使用了,知識不能使用資源,處于等待狀態。
4) 進程控制:可以對進程組執行掛起、恢復等操作。
2.1.4 內存限額
容器內存包括兩個部分:物理內存和swap
可以通過參數控制容器內存的使用量:
-m或者--memory:設置內存的使用限額
--memory-swap:設置內存+ swap的使用限額
舉個例子:
運行一個容器,并且限制該容器最多使用200M內存和100M的swap
[root@localhost ~]# docker run -it -m 200M --memory-swap 300M centos:7
[root@fba67fec2718 ~]# cd /sys/fs/cgroup/
[root@fba67fec2718 cgroup]# ls
[root@fba67fec2718 cgroup]# cd memory/
[root@fba67fec2718 memory]# ls
[root@fba67fec2718 memory]# cat memory.limit_in_bytes
//查看內存使用限制,(單位字節)
[root@fba67fec2718 memory]# cat memory.memsw.limit_in_bytes
//查看交換分區,內存+swap限制
運行一個新容器,并且不限制該容器
[root@localhost ~]# docker run -it centos:7
[root@5be901bfb093 /]# cd /sys/fs/cgroup/memory/
[root@5be901bfb093 memory]# cat memory.limit_in_bytes
//查看內存限制
[root@5be901bfb093 memory]# cat memory.memsw.limit_in_bytes
//查看交換分區,內存+swap限制
對比一個沒有限制的容器,我們會發現,如果運行容器之后不限制內存的話,意味著沒有限制。
2.1.5 CPU使用
通過-c或者--cpu -shares設置容器使用cpu的權重。如果不設置默認為1024.
舉個例子:
沒有限制
[root@localhost ~]# docker run -it --name containerA centos:7
//沒有限制,1024
[root@8683d8ff8234 /]# cd /sys/fs/cgroup/cpu
[root@8683d8ff8234 cpu]# cat cpu.shares
限制CPU使用權重為512
[root@localhost ~]# docker run -it --name containerB -c 512 centos:7
//限制CPU使用權重為512
[root@d919d906295d /]# cd /sys/fs/cgroup/cpu
//可以看到cpu已經限制了
2.1.6 容器的Block IO
磁盤的讀寫。
Docker中可以通過設置權重,限制bps和iops的方式控制容器讀寫磁盤的IO
bps:每秒讀寫的數據量byte per second
iopS:每秒IO的次數 io per second。
默認情況下,所有容器都能夠平等的讀寫磁盤,也可以通過--blkig-weight參數改變容器的blocklO的優先級。
--device-read-bps:顯示讀取某個設備的bps。
--device-write-bps:顯示寫入某個設備的bps.
--device-read-iops:顯示讀取某個設備的iops.
--device-write-iops:顯示寫入某個設備的iops.
限制testA這個容器,寫入/dev/sda這塊磁盤的bps為30MB
[root@localhost ~]# docker run -it --name testA --device-write-bps /dev/sda:30MB centos:7
[root@60e59e96fc16 /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
//從/dev/zero輸入,然后輸出到test.out文件中,每次大小為1M,總共800次,oflag=direct 用來指定directlQ方式寫文件,這樣才會使--device-write-bps生效。
[root@60e59e96fc16 /]# du -h test.out
docker沒有限制
[root@localhost ~]# docker run -it --name testc centos:7
[root@5bf5f3d60d0e /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
[root@5bf5f3d60d0e /]# du -h test.out
虛擬機:
我們傳統的虛擬機需要模擬整臺機器包括硬件,每臺虛擬機都需要有自己的操作系統,虛擬機一旦被開啟,預分配給他的資源將全部被占用。,每一個虛擬機包括應用,必要的二進制和庫,以及一個完整的用戶操作系統。
Docker:
容器技術是和我們的宿主機共享硬件資源及操作系統可以實現資源的動態分配。
容器包含應用和其所有的依賴包,但是與其他容器共享內核。容器在宿主機操作系統中,在用戶空間以分離的進程運行。
|
虛擬機和容器都是在硬件和操作系統以上的,虛擬機有Hypervisor層,Hypervisor是整個虛擬機的核心所在。他為虛擬機提供了虛擬的運行平臺,管理虛擬機的操作系統運行。每個虛擬機都有自己的系統和系統庫以及應用。
容器沒有Hypervisor這一層,并且每個容器是和宿主機共享硬件資源及操作系統,那么由Hypervisor帶來性能的損耗,在linux容器這邊是不存在的。
但是虛擬機技術也有其優勢,能為應用提供一個更加隔離的環境,不會因為應用程序的漏洞給宿主機造成任何問題。同時還支持跨操作系統的虛擬化,例如你可以在linux操作系統下運行windows虛擬機。
從虛擬化層面來看,傳統虛擬化技術是對硬件資源的虛擬,容器技術則是對進程的虛擬,從而可提供更輕量 級的虛擬化,實現進程和資源的隔離。
從架構來看,Docker比虛擬化少了兩層,取消了hypervisor層和GuestOS層,使用 Docker Engine 進行調度和隔離,所有應用共用主機操作系統,因此在體量上,Docker較虛擬機更輕量級,在性能上優于虛擬化,接近裸機性能。從應用場景來 看,Docker和虛擬化則有各自擅長的領域,在軟件開發、測試場景和生產運維場景中各有優劣
具體對比:
3.1.1 docker結構介紹
基礎設施(Infrastructure)。
主操作系統(Host Operating System)。所有主流的Linux發行版都可以運行Docker。對于MacOS和Windows,也有一些辦法”運行”Docker。
Docker守護進程(Docker Daemon)。Docker守護進程取代了Hypervisor,它是運行在操作系統之上的后臺進程,負責管理Docker容器。
各種依賴。對于Docker,應用的所有依賴都打包在Docker鏡像中,Docker容器是基于Docker鏡像創建的。
應用。應用的源代碼與它的依賴都打包在Docker鏡像中,不同的應用需要不同的Docker鏡像。不同的應用運行在不同的Docker容器中,它們是相互隔離的。
Docker守護進程可以直接與主操作系統進行通信,為各個Docker容器分配資源;它還可以將容器與主操作系統隔離,并將各個容器互相隔離。虛擬機啟動需要數分鐘,而Docker容器可以在數毫秒內啟動。由于沒有臃腫的從操作系統,Docker可以節省大量的磁盤空間以及其他系統資源;虛擬機更擅長于資源的完全隔離。
鏈接:https://blog.51cto.com/14320361/2457143
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。