docker概念

雖然Kubernetes 在 v1.20 版本之后將不支持 Docker作為容器運(yùn)行時(shí)Container Runtime(Docker的多層封裝和調(diào)用,導(dǎo)致其在可維護(hù)性上略遜一籌),但是現(xiàn)在Docker還是Kubernetes默認(rèn)的容器運(yùn)行時(shí)(Container Runtime),在使用為 Kubernetes 創(chuàng)建的Container Runtime Interface(CRI)的運(yùn)行時(shí),Docker 生成的鏡像可以繼續(xù)在你的集群中與所有CRI實(shí)現(xiàn)一起工作。后續(xù)可以切換至與之兼容的容器運(yùn)行時(shí)containerd、CRI-O等。

為什么要使用Docker而不是其它虛擬化技術(shù)?

  • 容器不需要進(jìn)行硬件虛擬以及運(yùn)行完整操作系統(tǒng)等額外開(kāi)銷(xiāo),Docker 對(duì)系統(tǒng)資源的利用率更高。無(wú)論是應(yīng)用執(zhí)行速度、內(nèi)存損耗或者文件存儲(chǔ)速度,都要比傳統(tǒng)虛擬機(jī)技術(shù)更高效。
  • Docker 容器應(yīng)用直接運(yùn)行于宿主內(nèi)核,無(wú)需啟動(dòng)完整的操作系統(tǒng),可以做到秒級(jí)啟動(dòng)。
  • Docker 的鏡像提供了除內(nèi)核外完整的運(yùn)行時(shí)環(huán)境,確保了應(yīng)用運(yùn)行環(huán)境一致性。
  • Docker 可以通過(guò)定制應(yīng)用鏡像來(lái)實(shí)現(xiàn)持續(xù)集成、持續(xù)交付、部署。
  • Docker 確保了執(zhí)行環(huán)境的一致性,使得應(yīng)用的遷移更加容易。
  • Docker 使用的分層存儲(chǔ)以及鏡像的技術(shù),使得應(yīng)用重復(fù)部分的復(fù)用更為容易,也使得應(yīng)用的維護(hù)更新更加簡(jiǎn)單,基于基礎(chǔ)鏡像進(jìn)一步擴(kuò)展鏡像也非常簡(jiǎn)單。

Docker Engine簡(jiǎn)介

Docker Engine 可以通過(guò)Docker Desktop在macOS和Windows10上使用,也可以使用靜態(tài)二進(jìn)制在各種Linux上使用。

Docker Engine作為一個(gè)client-server應(yīng)用:

  • 一個(gè)長(zhǎng)期運(yùn)行的守護(hù)進(jìn)程服務(wù)端 dockerd。Docker守護(hù)進(jìn)程 (dockerd) 監(jiān)聽(tīng)Docker API的請(qǐng)求和管理Docker對(duì)象,比如鏡像,容器,網(wǎng)絡(luò),數(shù)據(jù)卷。守護(hù)進(jìn)程并且可以與其他守護(hù)進(jìn)程通信去管理Docker服務(wù)。
  • Docker API,通過(guò)指定接口Docker客戶(hù)端能與 Docker守護(hù)進(jìn)程進(jìn)行通信,使守護(hù)程序完成了構(gòu)建、運(yùn)行和分發(fā)Docker容器等工作。.
  • 命令行界面(CLI, command line interface) 客戶(hù)端 dockerdocker是docker用戶(hù)與docker交互的一個(gè)主要途徑,當(dāng)你使用命令(比如docker run), 客戶(hù)端發(fā)送這些命令至守護(hù)進(jìn)程dockerd。docker命令使用 Docker API。Docker客戶(hù)端可以和多個(gè)守護(hù)進(jìn)程通信。
    docker組件流圖.png

Docker Engine版本

Docker Engine分為 CE 和 EE 兩大版本。CE 即社區(qū)版(免費(fèi),支持周期 7 個(gè)月),EE 即企業(yè)版,強(qiáng)調(diào)安全,付費(fèi)使用,支持周期 24 個(gè)月。
Docker CE 分為 stable, test, 和 nightly 三個(gè)更新通道。每六個(gè)月發(fā)布一個(gè) stable 版本:
Stable為您提供一般可用性(GA, general availability)的最新版本。年-月發(fā)布是從與主分支的發(fā)布分支生成的
test 提供在GA之前準(zhǔn)備好進(jìn)行測(cè)試的預(yù)發(fā)布。
Nightly提供下一個(gè)主要版本的最新內(nèi)容。


Docker組件

docker client

docker client是一個(gè)客戶(hù)端工具,將用戶(hù)的請(qǐng)求發(fā)送給 docker daemon(dockerd)

dockerd

dockerd是docker守護(hù)進(jìn)程(Docker daemon)。是對(duì)容器相關(guān)操作的api的最上層封裝,將請(qǐng)求發(fā)送給 containerd 。

 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

containerd

containerd 是一個(gè)守護(hù)進(jìn)程,它管理容器生命周期,提供了在一個(gè)節(jié)點(diǎn)上執(zhí)行容器和管理鏡像的最小功能集。dockerd操作實(shí)際調(diào)用的還是containerd的api接口(gRPC方式實(shí)現(xiàn)),containerd是dockerd和runc之間交流的一個(gè)中間組件。

containerd-shim

containerd-shim 是一個(gè)是容器的運(yùn)行時(shí)載體,允許runc在創(chuàng)建&運(yùn)行容器之后退出,每啟動(dòng)一個(gè)容器都會(huì)啟動(dòng)一個(gè)新的containerd-shim進(jìn)程,他直接通過(guò)指定的三個(gè)參數(shù):容器id,boundle目錄(容器的文件系統(tǒng)和一個(gè) config.json文件)來(lái)調(diào)用runc的api創(chuàng)建一個(gè)容器(比如創(chuàng)建容器:最后拼裝的命令如下:runc create )。用containerd-shim作為容器的父進(jìn)程,而不是直接用containerd作為容器的父進(jìn)程,是為了防止當(dāng)containerd掛掉的時(shí)候?qū)е氯萜魇?。runC 啟動(dòng)完容器后本身會(huì)直接退出,containerd-shim 則會(huì)成為容器進(jìn)程的父進(jìn)程,負(fù)責(zé)收集容器進(jìn)程的狀態(tài),上報(bào)給 containerd,并在容器中 pid 為 1 的進(jìn)程退出后接管容器中的子進(jìn)程進(jìn)行清理,確保不會(huì)出現(xiàn)僵尸進(jìn)程,這樣就不需要containerd來(lái)wait子進(jìn)程。

containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/274f1a80e3946d74354a449954874ae47e4b5dbcb1313966e82d33826ddee3a7 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup

runc

runc是一個(gè)命令行工具端,他根據(jù)oci(開(kāi)放容器組織, Open Container Initiative)的標(biāo)準(zhǔn)來(lái)創(chuàng)建和運(yùn)行容器。具體參考:http://www.itdecent.cn/p/2f6296190049


創(chuàng)建一個(gè)docker容器的步驟

docker啟動(dòng)容器.gif
  1. docker cli發(fā)送創(chuàng)建容器命令至Docker daemon;
  2. Docker daemon 仍然不能幫我們創(chuàng)建容器,轉(zhuǎn)而請(qǐng)求 containerd 創(chuàng)建一個(gè)容器;
  3. containerd 收到請(qǐng)求后,并不會(huì)自己直接去操作容器,而是創(chuàng)建一個(gè)叫做 containerd-shim 的進(jìn)程,讓 containerd-shim 去操作容器。這是因?yàn)槿萜鬟M(jìn)程需要一個(gè)父進(jìn)程來(lái)做諸如收集狀態(tài),維持 stdin 等 fd 打開(kāi)等工作。而假如這個(gè)父進(jìn)程就是 containerd,那每次 containerd 掛掉或升級(jí),整個(gè)宿主機(jī)上所有的容器都得退出了。而引入了 containerd-shim 就規(guī)避了這個(gè)問(wèn)題(containerd 和 shim 并不是父子進(jìn)程關(guān)系);
  4. 我們知道創(chuàng)建容器需要做一些設(shè)置 namespaces 和 cgroups,掛載 root filesystem 等等操作,而這些事該怎么做已經(jīng)有了公開(kāi)的規(guī)范了,那就是 OCI(Open Container Initiative,開(kāi)放容器標(biāo)準(zhǔn))。它的一個(gè)參考實(shí)現(xiàn)叫做 runC。于是,containerd-shim 在這一步需要調(diào)用 runC 這個(gè)命令行工具,來(lái)啟動(dòng)容器;
  5. runC 啟動(dòng)完容器后本身會(huì)直接退出,containerd-shim 則會(huì)成為容器進(jìn)程的父進(jìn)程,負(fù)責(zé)收集容器進(jìn)程的狀態(tài),上報(bào)給 containerd,并在容器中 pid 為 1 的進(jìn)程退出后接管容器中的子進(jìn)程進(jìn)行清理,確保不會(huì)出現(xiàn)僵尸進(jìn)程。

查看相關(guān)組件版本

[ ~]# docker version
Client: Docker Engine - Community
 Version:           19.03.12
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:46:54 2020
 OS/Arch:           linux/amd64
 Experimental:      false
?
Server: Docker Engine - Community
 Engine:
 Version:          19.03.12
 API version:      1.40 (minimum version 1.12)
 Go version:       go1.13.10
 Git commit:       48a66213fe
 Built:            Mon Jun 22 15:45:28 2020
 OS/Arch:          linux/amd64
 Experimental:     false
 containerd:
 Version:          1.2.13
 GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
 Version:          1.0.0-rc10
 GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
 Version:          0.18.0
 GitCommit:        fec3683</pre>

Docker底層技術(shù)

Namespaces

Docker使用namespaces為容器的工作空間做隔離. 當(dāng)你運(yùn)行一個(gè)容器, Docker 會(huì)發(fā)該容器創(chuàng)建一系列的namespace。這些namespace提供了一層隔離。一個(gè)容器運(yùn)行在一個(gè)單獨(dú)的命名空間中,并且其訪問(wèn)被限制在當(dāng)前命名空間內(nèi) 。

Docker Engine在Linux上使用下列namespace:

  • pid namespace: 進(jìn)程隔離 (PID: Process ID),"chroot"進(jìn)程樹(shù),提供進(jìn)程隔離能力。PID namespace是劃分那些一個(gè)進(jìn)程可以查看并與之交互的PID的方式。當(dāng)我們創(chuàng)建一個(gè)新的PID namespace時(shí),第一個(gè)進(jìn)程的PID會(huì)被賦值為1。當(dāng)該進(jìn)程退出時(shí),內(nèi)核會(huì)殺死當(dāng)前namespace內(nèi)的其他進(jìn)程。
  • net namespace: 管理網(wǎng)絡(luò)接口 (NET: Networking),提供網(wǎng)絡(luò)隔離能力。Network Namespace 可以讓每個(gè)容器擁有自己獨(dú)立的(虛擬的)網(wǎng)絡(luò)設(shè)備,而且容器內(nèi)的應(yīng)用可以綁定到自己的端口,每個(gè) Namespace 內(nèi)的端口都不會(huì)互相沖突。在宿主機(jī)上搭建網(wǎng)橋后,就能很方便地實(shí)現(xiàn)容器之間的通信,而且不同容器上的應(yīng)用可以使用相同的端口 。
  • The ipc namespace: 管理IPC資源的訪問(wèn) (IPC: InterProcess Communication),提供進(jìn)程間通信的隔離能力。
  • The mnt namespace: 管理文件系統(tǒng)掛載點(diǎn) (MNT: Mount),提供磁盤(pán)掛載點(diǎn)和文件系統(tǒng)的隔離能力
  • The uts namespace: 隔離內(nèi)核和版本標(biāo)識(shí)符 (UTS: Unix Timesharing System),主要用來(lái)完成對(duì)容器HOSTNAME和domain的隔離,同時(shí)保存內(nèi)核名稱(chēng)、版本、以及底層體系結(jié)構(gòu)類(lèi)型等信息。使得用戶(hù)在容器中查看到的信息是當(dāng)前容器的系統(tǒng)、版本,不同于主機(jī)的,內(nèi)核通過(guò)uts_namespace對(duì)當(dāng)前系統(tǒng)中多個(gè)容器的這些信息進(jìn)行統(tǒng)一管理,每一個(gè)容器對(duì)應(yīng)有一個(gè)自己的uts_namespace,用來(lái)隔離容器的內(nèi)核名稱(chēng)、版本等信息,不同容器查看到的都是屬于自己的信息,相互間不能查看。

Control groups

Docker Engine運(yùn)行在Linux上也依賴(lài)control groups (cgroups). cgroup將應(yīng)用程序限制為一組特定的資源。 Control groups允許Docker Engine將可用的硬件資源(比如cpu,內(nèi)存,磁盤(pán)和網(wǎng)絡(luò)IO)共享給容器,并有選擇地實(shí)施限制和約束。 例如,您可以限制特定容器可用的內(nèi)存。


Union file systems

Union file systems(或UnionFS)是通過(guò)創(chuàng)建layer來(lái)操作文件系統(tǒng),使其非常輕便且快速。 Docker Engine使用UnionFS為容器提供基本組成塊(building blocks)。 Docker Engine可以使用多個(gè)UnionFS變體,包括aufs,fuse-overlayfs,btrfs,zfs,vfs,devicemapper和overlay2(當(dāng)前推薦)。

  • overlay2 is the preferred storage driver, for all currently supported Linux distributions, and requires no extra configuration.
  • aufs was the preferred storage driver for Docker 18.06 and older, when running on Ubuntu 14.04 on kernel 3.13 which had no support for overlay2.
  • fuse-overlayfs is preferred only for running Rootless Docker on a host that does not provide support for rootless overlay2. On Ubuntu and Debian 10, the fuse-overlayfs driver does not need to be used overlay2 works even in rootless mode. See Rootless mode documentation.
  • devicemapper is supported, but requires direct-lvm for production environments, because loopback-lvm, while zero-configuration, has very poor performance. devicemapper was the recommended storage driver for CentOS and RHEL, as their kernel version did not support overlay2. However, current versions of CentOS and RHEL now have support for overlay2, which is now the recommended driver.
  • The btrfs and zfs storage drivers are used if they are the backing filesystem (the filesystem of the host on which Docker is installed). These filesystems allow for advanced options, such as creating “snapshots”, but require more maintenance and setup. Each of these relies on the backing filesystem being configured correctly.
  • The vfs storage driver is intended for testing purposes, and for situations where no copy-on-write filesystem can be used. Performance of this storage driver is poor, and is not generally recommended for production use.

storage driver所支持的操作系統(tǒng)

對(duì)于Docker Engine - Community,僅測(cè)試了一些配置,并且你的操作系統(tǒng)的內(nèi)核可能不支持每一個(gè)storage driver。一般來(lái)說(shuō), 以下配置適用于最新版本的Linux發(fā)行版:

Linux distribution Recommended storage drivers Alternative drivers
Docker Engine - Community on Ubuntu overlay2 or aufs (for Ubuntu 14.04 running on kernel 3.13) overlay1, devicemapper2, zfs, vfs
Docker Engine - Community on Debian overlay2 (Debian Stretch), aufs or devicemapper (older versions) overlay1, vfs
Docker Engine - Community on CentOS overlay2 overlay1, devicemapper2, zfs, vfs
Docker Engine - Community on Fedora overlay2 overlay1, devicemapper2, zfs, vfs

1) The overlay storage driver is deprecated, 將在未來(lái)的版本中移除。 推薦用戶(hù)將其遷移至overlay2。
2) The devicemapper storage driver is deprecated, 將在未來(lái)的版本中移除。推薦用戶(hù)將其遷移至overlay2。

storage drivers所支持的文件系統(tǒng)

Storage driver Supported backing filesystems
overlay2, overlay xfs with ftype=1, ext4
fuse-overlayfs any filesystem
aufs xfs, ext4
devicemapper direct-lvm
btrfs btrfs
zfs zfs
vfs any filesystem

根據(jù)工作負(fù)載選型

除其他事項(xiàng)外,每個(gè)存儲(chǔ)驅(qū)動(dòng)都有其自己的性能特征,這使其或多或少地適合于不同的工作負(fù)載??紤]以下概括:

  • overlay2, aufs以及overlay都是操作于文件層而不是塊(block)層。它使用內(nèi)存更效率, 但是在寫(xiě)密集型write-heavy工作負(fù)載下容器的可寫(xiě)層可能會(huì)增長(zhǎng)很大。
  • 塊層Block-level存儲(chǔ)驅(qū)動(dòng),比如devicemapper, btrfs和zfs在寫(xiě)密集型write-heavy workloads的情況下表現(xiàn)的更好 (雖然不如Docker volumes一樣好)。
  • 對(duì)于大量的小型寫(xiě)入,容器包含大量的層或者深層文件系統(tǒng) , overlay也許性能更優(yōu)于overlay2,但是會(huì)使用更多的inode,這將導(dǎo)致inode耗盡。
  • btrfs和zfs 需要大量的內(nèi)存。
  • zfs對(duì)于高密集high-density工作負(fù)載型(比如 PaaS)是一個(gè)好的選擇

當(dāng)前使用的storage driver以及backing filesystem,可以使用docker info查看

[ ~]# docker info
 Server Version: 19.03.12
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Cgroup Driver: systemd
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init

devicemapper與overlayFS

devicemapper

devicemapper 驅(qū)動(dòng)使用專(zhuān)用于Docker的塊設(shè)備,并操作于塊級(jí)別而非文件級(jí)別??梢酝ㄟ^(guò)向Docker主機(jī)添加物理存儲(chǔ)來(lái)擴(kuò)展這些設(shè)備,并且它們的性能要好于在操作系統(tǒng)(OS)級(jí)別上使用文件系統(tǒng)devicemapper要求lvm2device-mapper-persistent-data已經(jīng)安裝。且其loop-lvm模式僅使用于配置direct-lvm模式之前的測(cè)試工作。生產(chǎn)環(huán)境使用devicemapper存儲(chǔ)驅(qū)動(dòng)一定要使用direct-lvm模式。 direct-lvm模式將使用塊設(shè)備創(chuàng)建thin pool。這比loop-lvm模式使用回環(huán)設(shè)備(loopback devices)更快、能更有效的使用系統(tǒng)資源以及其塊設(shè)備能按需增長(zhǎng)。
當(dāng)你使用devicemapper驅(qū)動(dòng)啟動(dòng)Docker時(shí),其與鏡像和容器層相關(guān)的所有對(duì)象都存儲(chǔ)在/var/lib/docker/devicemapper/目錄中,這些對(duì)象由一個(gè)或多個(gè)塊級(jí)設(shè)備支持,而不是回環(huán)設(shè)備(loopback devices)(僅測(cè)試)或物理磁盤(pán)。

  • 基本設(shè)備(base device)是最低級(jí)別的對(duì)象,這就是thin pool本身,你可以使用docker info查看它。 它包含一個(gè)文件系統(tǒng)。 此基本設(shè)備是每個(gè)鏡像和容器層的起點(diǎn)。 基本設(shè)備是Device Mapper實(shí)現(xiàn)細(xì)節(jié),而不是Docker層。

  • 關(guān)于基本設(shè)備和每個(gè)鏡像、容器層的元數(shù)據(jù)使用JSON格式存儲(chǔ)在/var/lib/docker/devicemapper/metadata/ 。這些層都是寫(xiě)時(shí)復(fù)制copy-on-write快照, 這意味著它們是空的,直到它們脫離其父層。

  • 每個(gè)容器的可寫(xiě)層都掛載在/var/lib/docker/devicemapper/mnt/。每個(gè)只讀鏡像層和每個(gè)停止的容器都存在一個(gè)空目錄。
    每個(gè)鏡像層都是其下一層的快照。 每個(gè)鏡像的最低層是基本設(shè)備的快照,基本設(shè)備存在于池中。 當(dāng)你運(yùn)行容器時(shí),它是容器所基于的鏡像的快照。 以下示例顯示了兩個(gè)正在運(yùn)行的容器的Docker主機(jī)。 第一個(gè)是ubuntu容器,第二個(gè)是busybox容器。


    two_dm_container.jpg
OverlayFS

如果你要使用OverlayFS, 那應(yīng)該使用overlay2而不是overlay驅(qū)動(dòng), 因?yàn)?code>overlay2的inode利用率更高。 為了使用overlay2, 你的內(nèi)核版本應(yīng)該是 4.0或以上, RHEL或CentOS使用內(nèi)核應(yīng)該是 3.10.0-514或以上。
下圖是OverlayFS是如何將Docker鏡像和Docker容器分層。容器層是lowerdir,容器層是upperdir,統(tǒng)一視圖通過(guò)merged目錄顯示,該目錄實(shí)際上是容器的掛載點(diǎn)。 該圖顯示了Docker構(gòu)造如何映射到OverlayFS構(gòu)造。

overlay_constructs.jpg


Container format

Docker Engine將namespaces, control groups和UnionFS組合到一個(gè)稱(chēng)為容器格式的包裝器中。 默認(rèn)容器格式為libcontainer。 將來(lái),Docker可以通過(guò)與BSD Jails或Solaris Zones等技術(shù)集成來(lái)支持其他容器格式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本章內(nèi)容 ◆ Docker簡(jiǎn)介◆ Docker 鏡像與制作◆ Docker 數(shù)據(jù)管理◆ Docker 網(wǎng)絡(luò)◆ Do...
    Liang_JC閱讀 917評(píng)論 0 0
  • Docker是基于容器的應(yīng)用開(kāi)發(fā),部署和運(yùn)行平臺(tái) 高性能:相比傳統(tǒng)虛擬機(jī),不需要hepervisor的額外負(fù)載,而...
    wangdy12閱讀 2,007評(píng)論 0 0
  • docker概念 鏡像與容器 docker鏡像是一個(gè)統(tǒng)一文件系統(tǒng),由一系列只讀層堆疊而成。容器則是在只讀層堆頂加上...
    羽色云煙閱讀 862評(píng)論 0 0
  • docker最早是LXC(Linux Container)的二次封裝發(fā)行,后來(lái)使用的是Libcontainer技術(shù)...
    OOM_Killer閱讀 718評(píng)論 0 0
  • 一. 容器與虛擬機(jī)的區(qū)別 和虛擬機(jī)相比,容器更加輕量級(jí)。因?yàn)檫\(yùn)行在相同宿主機(jī)上的容器共享一個(gè)操作系統(tǒng),可以節(jié)省大量...
    睡不醒的大橘閱讀 250評(píng)論 0 0

友情鏈接更多精彩內(nèi)容