docker實現原理以及簡單體驗(一)

簡介

 因爲科技技術的高度發展,在物理機服務器性能愈來愈高的今天,不少生產環境中使用的服務器,因爲沒有不少的用戶訪問,而致使性能過剩。而生產中又須要在多臺服務器上部署業務。若是老是購買物理服務器,顯然會形成經濟成本大大增長,這時候就須要虛擬化技術來完成物理機性能的合理分配。
 虛擬化技術在上世紀已經誕生,可是上世紀的物理機性能顯然沒法提供大規模的虛擬化環境,因此沒有流行開來。最現現在虛擬化技術已經以勢不可擋之勢步入各個公司的生產環境中,不經可以大幅節約成本,還能夠提升 IT 敏捷性、靈活性和可擴展性。
 虛擬機技術中最早誕生的是主機級虛擬化,主機級虛擬化典型的表明即是KVM/XEN,它能夠在物理機之上部署多臺虛擬機同時運行,而各個虛擬機之間互不影響,即便某一臺服務器因爲各類緣由「壽終正寢」以後,也不會影響到其它虛擬機和宿主機的正常運行。可是這種技術的缺點也很明顯,每一個虛擬機都有單獨的內核空間,對系統的資源消耗至關大。
 而容器虛擬化技術則解決了這一難題,它不須要在運行是安裝一個龐大的內核,而只是將運行某個服務的環境集成在一個容器中,大大減小了對系統資源的消耗,而且有「秒級」的自愈功能,一個容器宕機以後可當即棄之,隨後頭也不回的重啓一個容器接替它的位置,固然此功能須要運維人員對容器進行很好的優化才能實現。
docker實現原理以及簡單體驗(一)node

linux namespace的組成

 雖然容器虛擬化技術有種種好處,可是在宿主機之上運行N個容器,如何讓這些容器之間的運行穩定,且各個容器之間環境互不影響,就成爲了迫在眉睫的問題。每一個容器佔用系統資源較少,可麻雀雖少,也得五臟俱全。它也得具有主機名,網卡,用戶等資源。爲了解決此各個容器之間不衝突,就得使用到Linux Namespace
 namespace 是 Linux 系統的底層概念,在內核層實現,即有一些不一樣類型的命名空間被部署在內核之中,各個docker容器運行時共享一個宿主機的內核。與此同時,每一個宿主機之間要相互隔離的運行,並意識不到別的容器的存在,覺得本身就是這個「世界」的主宰,那麼一個容器必須有以下幾類namespacelinux

IPC Namespace:保證容器內的進程間可以相互通訊,可是不能跨容器訪問其餘容器的數據

MNT Namespace:獨立的根文件系統,以實如今容器裏面啓動服務而且構建出容器的運行環境

[root@node1 ~]#docker exec -it k1 bash
[root@3864270aea99 /]# ls /
#獨立根文件系統
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr

UTS Namespace:用於系統標識,包含主機名和域名,用來惟一標識獨立於宿主機系統和運行在其上的其餘容器

[root@node1 ~]#docker exec -it k1 bash
[root@3864270aea99 /]# hostname
#主機名
3864270aea99
[root@3864270aea99 /]# uname -a
#內核版本,注意此處也是宿主機的內核版本
Linux 3864270aea99 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

PID Namespace:每一個容器出有一個PID爲1的進程,用來管理進程的建立和回收

[root@node1 ~]#docker exec -it k1 bash
[root@3864270aea99 /]# top
top - 03:13:35 up  2:17,  0 users,  load average: 0.00, 0.03, 0.06
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   995896 total,   146980 free,   216372 used,   632544 buff/cache
KiB Swap:  2097148 total,  2096884 free,      264 used.   558252 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
     #容器的PID
     1 root      20   0   11820   1680   1408 S  0.0  0.2   0:00.02 bash                                        
    44 root      20   0   11820   1888   1508 S  0.0  0.2   0:00.02 bash                                        
    57 root      20   0   56192   2008   1468 R  0.0  0.2   0:00.02 top

Net Namespace:網絡是容器中很是重要的一環每一個容器都相似於虛擬機同樣有本身的網卡、監聽端口、TCP/IP 協議棧等,在運行容器時會自動生成一些防火牆規則用於和外界通信。

容器內網卡邏輯架構圖
docker實現原理以及簡單體驗(一)
查看容器內網卡git

[root@3864270aea99 /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 4190  bytes 39525574 (37.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3233  bytes 179563 (175.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

查看宿主機的上容器網卡的映射docker

[root@node1 ~]#ifconfig 
veth4ce4103: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::c061:9aff:fe02:ce89  prefixlen 64  scopeid 0x20<link>
        ether c2:61:9a:02:ce:89  txqueuelen 0  (Ethernet)
        RX packets 3234  bytes 179605 (175.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4191  bytes 39525616 (37.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

查看自動生成的防火牆規則安全

[root@node1 ~]#iptables -vnL
Chain INPUT (policy ACCEPT 7764 packets, 77M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 7409   40M DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 7409   40M DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 4179   39M ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
 3230  134K ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0

User Namespace: 每一個容器中都要單獨的用戶和組,和宿主機並不衝突,只是會把用戶的做用範圍限制在每一個容器內

root@node1 ~]#docker exec -it k1 bash
[root@3864270aea99 /]# cat /etc/passwd
#每一個容器中都有相應的用戶
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

容器資源限制

 在使用VMware建立虛擬機時,每一個虛擬在安裝和啓動以前都會有這麼一個界面來設置這個虛擬機以前,能夠設置此虛擬機佔用宿主機的內存,CPU,網卡等硬件設備的大小。
docker實現原理以及簡單體驗(一)
 容器亦是如此,雖然一個容器內的程序能夠在其「領地」內行使對全部資源使用權利,但仍是要對其作資源限制,容器亦是如此,若是不對容器使用的資源作任何限制,當容器內的資源不夠時,容器便會侵蝕宿主機的資源,直至把宿主機的資源佔完,成爲這臺物理機新的「主人」。
 對容器的資源限制還能夠提升對於宿主機的安全性,假設一個容器出現漏洞被別人拿到控制權後,資源限制可以使其只可以使用這個容器中的資源,而沒法對宿主機的資源造成危害。
 那麼爲了不物理機的「主人」被其它容器取而代之,就須要一些手段來限制,主要使用的技術即是Linux control groups,簡稱Linux Cgroups。它的主要做用是限制一個進程組可以使用的資源上限,包括 CPU、內存、磁盤、網絡帶寬等等。此外,還可以對進程進行優先級設置,以及將進程掛起和恢復等操做。
 在容器使用的過程當中,一旦內存超過時初給它分配了空間,那麼內核將主動殺死這個容器所使用的進程。
此功能在內核層默認已經開啓。bash

[root@node1 ~]#cat /boot/config-3.10.0-957.el7.x86_64 | grep CGROUP
#驗證系統的Cgroups是否開啓
CONFIG_CGROUPS=y
#CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_BLK_CGROUP=y
#CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=y

Cgroup的具體實現服務器

[root@node1 ~]#ll /sys/fs/cgroup/
總用量 0
drwxr-xr-x 2 root root  0 7月   3 21:02 blkio
lrwxrwxrwx 1 root root 11 7月   3 21:02 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 7月   3 21:02 cpuacct -> cpu,cpuacct
drwxr-xr-x 2 root root  0 7月   3 21:02 cpu,cpuacct
drwxr-xr-x 2 root root  0 7月   3 21:02 cpuset
drwxr-xr-x 4 root root  0 7月   3 21:02 devices
drwxr-xr-x 2 root root  0 7月   3 21:02 freezer
drwxr-xr-x 2 root root  0 7月   3 21:02 hugetlb
drwxr-xr-x 2 root root  0 7月   3 21:02 memory
lrwxrwxrwx 1 root root 16 7月   3 21:02 net_cls -> net_cls,net_prio
drwxr-xr-x 2 root root  0 7月   3 21:02 net_cls,net_prio
lrwxrwxrwx 1 root root 16 7月   3 21:02 net_prio -> net_cls,net_prio
drwxr-xr-x 2 root root  0 7月   3 21:02 perf_event
drwxr-xr-x 2 root root  0 7月   3 21:02 pids
drwxr-xr-x 4 root root  0 7月   3 21:02 systemd

blkio:塊設備 IO 限制
cpu:使用調度程序爲 cgroup 任務提供 cpu 的訪問
cpuacct:產生 cgroup 任務的 cpu 資源報告
cpuset:若是是多核心的 cpu,這個子系統會爲 cgroup 任務分配單獨的 cpu 和內存
devices:容許或拒絕 cgroup 任務對設備的訪問
freezer:暫停和恢復 cgroup 任務。
memory:設置每一個 cgroup 的內存限制以及產生內存資源報告
ns:命名空間子系統
perf_event:增長了對每 group 的監測跟蹤的能力,能夠監測屬於某個特定的 group 的所 有線程以及運行在特定 CPU 上的線程
 有了這些就具有了容器的基礎運行環境,可是還須要有相應的容器建立與刪除的管理工具、以及怎麼樣把容器運行起來、容器數據怎麼處理、怎麼進行啓動與關閉等問題須要解決,因而容器管理技術便應運而生。網絡

容器管理工具

 容器的管理技術早期誕生的有 Linux Container(LXC),它能夠提供輕量級的虛擬化來隔離各個容器之間的通信。可是LXC啓動容器依賴於模板,而模板須要一步步創構建文件系統、準備基礎目錄及可執行程序等一堆步驟纔可以使容器運行,另外後期代碼升級也須要從新從頭構建模板。
 這就與容器的理念背道而馳,容器自己是爲了簡化操做而誕生的,如此大費周折的啓動一個容器,顯然不是生產環境中所指望的。後來docker的橫空出世,便以勢不可擋之勢侵佔了大部分LXC的市場。
 然而並非說docker啓動容器時不須要模板,docker也是須要的。只是它把這些模板包裝成爲一個個的鏡像。而docker的鏡像便可以保存在一個公共的地方供全部人共享使用,也能夠保存在本地的私有倉庫中使用。
 當咱們在使用鏡像時,只要把別人製做的鏡像下載下來就可使用。若是咱們以爲別人的配置不符合生產環境中的需求,咱們還能夠在別人製做的鏡像基礎之上作自定義配置,配置完成後保存爲本身的一個鏡像。如此造成了前人栽樹後人乘涼的良性循環,這也是容器技術愈來愈火爆的緣由之一
docker官方鏡像倉庫地址:https://hub.docker.com/架構

docker 的組成

docker 主機(Host):一個物理機或虛擬機,用於運行 docker 服務進程和容器。
docker 服務端(Server):docker 守護進程,運行 docker 容器。
docker 客戶端(Client):客戶端使用 docker 命令或其餘工具調用 docker API。
docker 倉庫(Registry): 保存鏡像的倉庫,相似於 git 或 svn 這樣的版本控制系
docker 鏡像(Images):鏡像能夠理解爲建立實例使用的模板。
docker 容器(Container): 容器是從鏡像生成對外提供服務的一個或一組服務。運維

瞭解了上述這些原理後,基本上對docker有了一個初步的認識,下面說一下若是安裝docker,以及如何在docker中運行並管理一個容器。

相關文章
相關標籤/搜索