自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

容器技術(shù)的發(fā)展與基本原理

云計算
從容器的發(fā)展歷程可以看到,容器在出現(xiàn)的早期并沒有得到人們的廣泛關(guān)注,主要原因是當時開放的云計算環(huán)境還沒出現(xiàn)或者未成為主流。2010年之后,隨著IaaS、PaaS和SaaS等云平臺逐漸成熟,用戶對云端應(yīng)用開發(fā)、部署和運維的效率不斷重視,重新發(fā)掘了容器的價值,最終促成了容器技術(shù)的盛行。

容器技術(shù)的發(fā)展背景

近些年來,容器技術(shù)迅速席卷全球,顛覆了應(yīng)用的開發(fā)、交付和運行模式,在云計算、互聯(lián)網(wǎng)等領(lǐng)域得到了廣泛應(yīng)用。其實,容器技術(shù)在約二十年前就出現(xiàn)了,但直到2013年Docker推出之后才遍地開花,其中有偶然因素,也有大環(huán)境造就的必然因素。這里回顧一下容器的產(chǎn)生的背景和發(fā)展過程。

在電子計算機剛出現(xiàn)時,由于硬件成本高昂,人們試圖尋找能夠多用戶共享計算資源的方式,以提高資源利用率和降低成本。在20世紀60年代,基于硬件技術(shù)的主機虛擬化技術(shù)出現(xiàn)了。一臺物理主機可以被劃分為若干個小的機器,每個機器的硬件互不共享,并可以安裝各自的操作系統(tǒng)來使用。20世紀90年代后期,X86架構(gòu)的硬件虛擬化技術(shù)逐漸興起,可在同一臺物理機上隔離多個操作系統(tǒng)實例,帶來了很多的優(yōu)點,目前絕大多數(shù)的數(shù)據(jù)中心都采用了硬件虛擬化技術(shù)。

雖然硬件虛擬化提供了分隔資源的能力,但是采用虛擬機方式隔離應(yīng)用程序時,效率往往較低,畢竟還要在每個虛擬機中安裝或復制一個操作系統(tǒng)實例,然后把應(yīng)用部署到其中。因此人們探索出一種更輕量的方案——操作系統(tǒng)虛擬化,使面向應(yīng)用的管理更便捷。所謂操作系統(tǒng)虛擬化,就是由操作系統(tǒng)創(chuàng)建虛擬的系統(tǒng)環(huán)境,使應(yīng)用感知不到其他應(yīng)用的存在,仿佛在獨自占有全部的系統(tǒng)資源,從而實現(xiàn)應(yīng)用隔離的目的。在這種方式中不需要虛擬機,也能夠?qū)崿F(xiàn)應(yīng)用彼此隔離,由于應(yīng)用是共享同一個操作系統(tǒng)實例的,因此比虛擬機更節(jié)省資源,性能更好。操作系統(tǒng)虛擬化在不少系統(tǒng)里面也被稱為容器(Container),下面也會以容器來指代操作系統(tǒng)虛擬化。

操作系統(tǒng)虛擬化最早出現(xiàn)在2000年,F(xiàn)reeBSD 4.0推出了Jail。Jail加強和改進了用于文件系統(tǒng)隔離的chroot環(huán)境。到了2004年,Sun公司發(fā)布了Solaris 10的Containers,包括Zones和Resource management兩部分。Zones實現(xiàn)了命名空間隔離和安全訪問控制,Resource management實現(xiàn)了資源分配控制。2007年,Control Groups(簡稱cgroups)進入Linux內(nèi)核,可以限定和隔離一組進程所使用的資源(包括CPU、內(nèi)存、I/O和網(wǎng)絡(luò)等)。

2013年,Docker公司發(fā)布Docker開源項目,提供了一系列簡便的工具鏈來使用容器。毫不夸張地說,Docker公司率先點燃了容器技術(shù)的火焰,拉開了云原生應(yīng)用變革的帷幕,促進容器生態(tài)圈一日千里地發(fā)展。截至2020年,Docker Hub中的鏡像累計下載了1300億次,用戶創(chuàng)建了約600萬個容器鏡像庫。從這些數(shù)據(jù)可以看到,用戶正在以驚人的速度從傳統(tǒng)模式切換到基于容器的應(yīng)用發(fā)布和運維模式。

2015年,OCI(Open Container Initiative)作為Linux基金會項目成立,旨在推動開源技術(shù)社區(qū)制定容器鏡像和運行時規(guī)范,使不同廠家的容器解決方案具備互操作能力。同年還成立了CNCF,目的是促進容器技術(shù)在云原生領(lǐng)域的應(yīng)用,降低用戶開發(fā)云原生應(yīng)用的門檻。創(chuàng)始會員包括谷歌、紅帽、Docker、VMware等多家公司和組織。

CNCF成立之初只有一個開源項目,就是后來大名鼎鼎的Kubernetes。Kubernetes是一個容器應(yīng)用的編排工具,最早由谷歌的團隊研發(fā),后來開源并捐贈給了CNCF成為種子項目。由于Kubernetes是廠家中立的開源項目,開源后得到了社區(qū)用戶和開發(fā)者的廣泛參與和支持。到了2018年,Kubernetes已成為容器編排領(lǐng)域事實上的標準,并成為首個CNCF的畢業(yè)(graduated)項目。2020年8月,CNCF旗下的開源項目增加到了63個,包括原創(chuàng)于中國的Harbor等項目。

從容器的發(fā)展歷程可以看到,容器在出現(xiàn)的早期并沒有得到人們的廣泛關(guān)注,主要原因是當時開放的云計算環(huán)境還沒出現(xiàn)或者未成為主流。2010年之后,隨著IaaS、PaaS和SaaS等云平臺逐漸成熟,用戶對云端應(yīng)用開發(fā)、部署和運維的效率不斷重視,重新發(fā)掘了容器的價值,最終促成了容器技術(shù)的盛行。

容器的基本原理

本節(jié)以Linux容器為例,講解容器的實現(xiàn)原理,主要包括命名空間(Namespace)和控制組(cgroups)。

命名空間

命名空間是Linux操作系統(tǒng)內(nèi)核的一種資源隔離方式,使不同的進程具有不同的系統(tǒng)視圖。系統(tǒng)視圖就是進程能夠感知到的系統(tǒng)環(huán)境,如主機名、文件系統(tǒng)、網(wǎng)絡(luò)協(xié)議棧、其他用戶和進程等。使用命名空間后,每個進程都具備獨立的系統(tǒng)環(huán)境,進程間彼此感覺不到對方的存在,進程之間相互隔離。目前,Linux中的命名空間共有6種,可以嵌套使用。

  • Mount:隔離了文件系統(tǒng)的掛載點(mount points),處于不同“mount”命名空間中的進程可以看到不同的文件系統(tǒng)。
  • Network:隔離進程網(wǎng)絡(luò)方面的系統(tǒng)資源,包括網(wǎng)絡(luò)設(shè)備、IPv4和IPv6的協(xié)議棧、路由表、防火墻等。
  • IPC:進程間相互通信的命名空間,不同命名空間中的進程不能通信。
  • PID:進程號在不同的命名空間中是獨立編號的,不同的命名空間中的進程可以有相同的編號。當然,這些進程在操作系統(tǒng)中的全局(命名空間外)編號是唯一的。
  • UTS:系統(tǒng)標識符命名空間,在每個命名空間中都可以有不同的主機名和NIS域名。
  • User:命名空間中的用戶可以有不同于全局的用戶ID和組ID,從而具有不同的特權(quán)。

命名空間實現(xiàn)了在同一操作系統(tǒng)中隔離進程的方法,幾乎沒有額外的系統(tǒng)開銷,所以是非常輕量的隔離方式,進程啟動和運行的過程在命名空間中和外面幾乎沒有差別。

控制組

命名空間實現(xiàn)了進程隔離功能,但由于各個命名空間中的進程仍然共享同樣的系統(tǒng)資源,如CPU、磁盤I/O、內(nèi)存等,所以如果某個進程長時間占用某些資源,其他命名空間里的進程就會受到影響,這就是“吵鬧的鄰居(noisy neighbors)”現(xiàn)象。因此,命名空間并沒有完全達到進程隔離的目的。為此,Linux內(nèi)核提供了控制組(Control Groups,cgroups)功能來處理這個問題。

Linux把進程分成控制組,給每組里的進程都設(shè)定資源使用規(guī)則和限制。在發(fā)生資源競爭時,系統(tǒng)會根據(jù)每個組的定義,按照比例在控制組之間分配資源??刂平M可設(shè)定規(guī)則的資源包括CPU、內(nèi)存、磁盤I/O和網(wǎng)絡(luò)等。通過這種方式,就不會出現(xiàn)某些進程無限度搶占其他進程資源的情況。

Linux系統(tǒng)通過命名空間設(shè)置進程的可見且可用資源,通過控制組規(guī)定進程對資源的使用量,這樣隔離進程的虛擬環(huán)境(即容器)就建立起來了。

容器運行時

Linux 提供了命名空間和控制組兩大系統(tǒng)功能,它們是容器的基礎(chǔ)。但是,要把進程運行在容器中,還需要有便捷的SDK或命令來調(diào)用Linux的系統(tǒng)功能,從而創(chuàng)建出容器。容器的運行時(runtime)就是容器進程運行和管理的工具。

容器運行時分為低層運行時和高層運行時,功能各有側(cè)重。低層運行時主要負責運行容器,可在給定的容器文件系統(tǒng)上運行容器的進程;高層運行時則主要為容器準備必要的運行環(huán)境,如容器鏡像下載和解壓并轉(zhuǎn)化為容器所需的文件系統(tǒng)、創(chuàng)建容器的網(wǎng)絡(luò)等,然后調(diào)用低層運行時啟動容器。主要的容器運行時的關(guān)系如下圖所示。

OCI運行時規(guī)范

成立于2015年的OCI是Linux基金會旗下的合作項目,以開放治理的方式制定操作系統(tǒng)虛擬化(特別是Linux容器)的開放工業(yè)標準,主要包括容器鏡像格式和容器運行時(runtime)。初始成員包括Docker、亞馬遜、CoreOS、谷歌、微軟和VMware等公司。OCI成立之初,Docker公司為其捐贈了容器鏡像格式和運行時的草案及相應(yīng)的實現(xiàn)代碼。原來屬于Docker的libcontainer項目被捐贈給OCI,成為獨立的容器運行時項目runC。

OCI運行時規(guī)范定義了容器配置、運行時和生命周期的標準,主流的容器運行時都遵循OCI運行時的規(guī)范,從而提高系統(tǒng)的可移植性和互操作性,用戶可根據(jù)需要進行選擇。

首先,容器啟動前需要在文件系統(tǒng)中按一定格式存放所需的文件。OCI運行時規(guī)范定義了容器文件系統(tǒng)包(filesystem bundle)的標準,在OCI運行時的實現(xiàn)中通常由高層運行時下載OCI鏡像,并將OCI鏡像解壓成OCI運行時文件系統(tǒng)包,然后OCI運行時讀取配置信息和啟動容器里的進程。OCI運行時文件系統(tǒng)包主要包括以下兩部分。

  • config.json:這是必需的配置文件,存放于文件系統(tǒng)包的根目錄下。OCI運行時規(guī)范對Linux、Windows、Solaris和虛擬機4種平臺的運行時做了相應(yīng)的配置規(guī)范。
  • 容器的根文件系統(tǒng):容器啟動后進程所使用的根文件系統(tǒng),由 config.json 中的root.path屬性確定該文件系統(tǒng)的路徑,通常是“rootfs/”。

然后,在定義文件系統(tǒng)包的基礎(chǔ)上,OCI運行時規(guī)范制定了運行時和生命周期管理規(guī)范。生命周期定義了容器從創(chuàng)建到刪除的全過程,可用以下三條命令說明。

  • “create”命令:在調(diào)用該命令時需要用到文件系統(tǒng)包的目錄位置和容器的唯一標識。在創(chuàng)建運行環(huán)境時需要使用config.json里面的配置。在創(chuàng)建的過程中,用戶可加入某些事件鉤子(hook)來觸發(fā)一些定制化處理,這些事件鉤子包括prestart、createRuntime和createContainer。
  • “start”命令:在調(diào)用該命令時需要運行容器的唯一標識。用戶可在 config.json 的process 屬性中指明運行程序的詳細信息。“start”命令包括兩個事件鉤子:startContainer和poststart。
  • “delete”命令:在調(diào)用該命令時需要運行容器的唯一標識。在用戶的程序終止后(包括正常和異常退出),容器運行時執(zhí)行“delete”命令以清除容器的運行環(huán)境。“delete”命令有一個事件鉤子:poststop。

除了上述生命周期命令,OCI運行時還必須支持另外兩條命令。

“state”命令:在調(diào)用該命令時需要運行容器的唯一標識。該命令查詢某個容器的狀態(tài),必須包括的狀態(tài)屬性有ociVersion、id、status、pid和bundle,可選屬性有annotation。不同的運行時實現(xiàn)可能會有一些差異。下面是一個容器狀態(tài)的例子:

 

  1.     "ociVersion""1.0.1"
  2.     "id""oci-container001"
  3.     "status""running"
  4.     "pid": 8080, 
  5.     "bundle""/containers/nginx"
  6.     "annotations": { 
  7.         "key1""value1" 
  8.     } 
  9. }  

“kill”命令:在調(diào)用該命令時需要運行容器的唯一標識和信號(signal)編號。該命令給容器進程發(fā)送信號,如Linux操作系統(tǒng)的信號9表示立即終止進程。

runC

runC是OCI運行時規(guī)范的參考實現(xiàn),也是最常用的容器運行時,被其他多個項目使用,如containerd和CRI-O等。runC也是低層容器運行時,開發(fā)人員可通過runC實現(xiàn)容器的生命周期管理,避免煩瑣的操作系統(tǒng)調(diào)用。根據(jù)OCI運行時規(guī)范,runC不包括容器鏡像的管理功能,它假定容器的文件包已經(jīng)從鏡像里解壓出來并存放于文件系統(tǒng)中。runC創(chuàng)建的容器需要手動配置網(wǎng)絡(luò)才能與其他容器或者網(wǎng)絡(luò)節(jié)點連通,為此可在容器啟動之前通過OCI定義的事件鉤子來設(shè)置網(wǎng)絡(luò)。

由于runC提供的功能比較單一,復雜的環(huán)境需要更高層的容器運行時來生成,所以runC常常成為其他高層容器運行時的底層實現(xiàn)基礎(chǔ)。

containerd

在OCI成立時,Docker公司把其Docker項目拆分為runC的低層運行時及高層運行時功能。2017年,Docker公司把這部分高層容器運行時的功能集中到containerd項目里,捐贈給云原生計算基金會。

containerd 已經(jīng)成為多個項目共同使用的高層容器運行時,提供了容器鏡像的下載和解壓等鏡像管理功能,在運行容器時,containerd先把鏡像解壓成OCI的文件系統(tǒng)包,然后調(diào)用runC運行容器。containerd提供了API,其他應(yīng)用程序可以通過API與containerd交互。“ctr”是containerd的命令行工具,和“docker”命令很相像。但作為容器運行時,containerd只注重在容器運行等方面,因而不包含開發(fā)者使用的鏡像構(gòu)建和鏡像上傳鏡像倉庫等功能。

Docker

Docker引擎是最早流行也是最廣泛使用的容器運行時之一,是一個容器管理工具,架構(gòu)如下圖所示。Docker的客戶端(命令行CLI工具)通過API調(diào)用容器引擎Docker Daemon(dockerd)的功能,完成各種容器管理任務(wù)。

Docker引擎在發(fā)布時是一個單體應(yīng)用,所有功能都集中在一個可執(zhí)行文件里,后來按功能分拆成runC和containerd兩個不同層次的運行時,分別捐獻給了OCI和CNCF。上面兩節(jié)已經(jīng)分別介紹了runC和containerd的主要特點,剩下的dockerd就是Docker公司維護的容器運行時。

dockerd同時提供了面向開發(fā)者和面向運維人員的功能。其中,面向開發(fā)者的命令主要提供鏡像管理功能。容器鏡像一般可由Dockerfile構(gòu)建(build)而來。Dockerfile是一個文本文件,通過一組命令關(guān)鍵字定義了容器鏡像所包含的基礎(chǔ)鏡像(base image)、所需的軟件包及有關(guān)應(yīng)用程序。在Dockerfile編寫完成以后,就可以用“docker build”命令構(gòu)建鏡像了。下面是一個Dockerfile的簡單例子:

 

  1. FROM ubuntu:18.04 
  2. EXPOSE 8080 
  3. CMD ["nginx""-g""daemon off;"

容器的鏡像在構(gòu)建之后被存放在本地鏡像庫里,當需要與其他節(jié)點共享鏡像時,可上傳鏡像到鏡像倉庫(Registry)以供其他節(jié)點下載。

Docker還提供了容器存儲和網(wǎng)絡(luò)映射到宿主機的功能,大部分由containerd實現(xiàn)。應(yīng)用的數(shù)據(jù)可以被保存在容器的私有文件系統(tǒng)里面,這部分數(shù)據(jù)會隨著容器一起被刪除。對需要數(shù)據(jù)持久化的有狀態(tài)應(yīng)用來說,可用數(shù)據(jù)卷Volume的方式導入宿主機上的文件目錄到容器中,對該目錄的所有寫操作都將被保存到宿主機的文件系統(tǒng)中。Docker可以把容器內(nèi)的網(wǎng)絡(luò)映射到宿主機的網(wǎng)絡(luò)上,并且可以連接外部網(wǎng)絡(luò)。

CRI和CRI-O

Kubernetes是當今主流的容器編排平臺,為了適應(yīng)不同場景的需求,Kubernetes需要有使用不同容器運行時的能力。為此,Kubernetes從1.5版本開始,在kubelet中增加了一個容器運行時接口CRI(Container Runtime Interface),需要接入Kubernetes的容器運行時必須實現(xiàn)CRI接口。由于kubelet的任務(wù)是管理本節(jié)點的工作負載,需要有鏡像管理和運行容器的能力,因此只有高層容器運行時才適合接入CRI。CRI和容器運行時的關(guān)系如下圖所示。

CRI和容器運行時之間需要有個接口層,通常稱之為shim(墊片),用以匹配相應(yīng)的容器運行時。CRI接口由shim實現(xiàn),定義如下,分為RuntimeService和ImageServiceManager(代碼參見GitHub上kubernetes/cri-api的項目文件“pkg/apis/services.go”):

 

  1. // RuntimeService接口必須由容器運行時實現(xiàn) 
  2. // 以下方法必須是線程安全的 
  3. type RuntimeService interface { 
  4. RuntimeVersioner 
  5. ContainerManager 
  6. PodSandboxManager 
  7. ContainerStatsManager 
  8.  
  9. // UpdateRuntimeConfig更新運行時配置 
  10. UpdateRuntimeConfig(runtimeConfig *runtimeapi.RuntimeConfig) error 
  11.  
  12. // Status返回運行時的狀態(tài) 
  13. Status() (*runtimeapi.RuntimeStatus, error) 
  14.  
  15. // ImageManagerService接口必須由容器管理器實現(xiàn) 
  16. // 以下方法必須是線程安全的 
  17. type ImageManagerService interface { 
  18. // ListImages列出現(xiàn)有鏡像 
  19. ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error) 
  20.  
  21. // ImageStatus返回鏡像狀態(tài) 
  22. ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.Image, error) 
  23.  
  24. // PullImage用認證配置拉取鏡像 
  25. PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) 
  26.  
  27. // RemoveImage刪除鏡像 
  28. RemoveImage(image *runtimeapi.ImageSpec) error 
  29.  
  30. // ImageFsInfo返回存儲鏡像的文件系統(tǒng)信息 
  31. ImageFsInfo() ([]*runtimeapi.FilesystemUsage, error) 
  32. }  

Docker運行時被普遍使用,它的CRI shim被稱為dockershim,內(nèi)置在Kubernetes的kubelet中,由Kubernetes項目組開發(fā)和維護。其他運行時則需要提供外置的shim。containerd從1.1版本開始內(nèi)置了CRI plugin,不再需要外置shim來轉(zhuǎn)發(fā)請求,因此效率更高。在安裝Docker的最新版本時,會自動安裝containerd,所以在一些系統(tǒng)中,Docker和Kubernetes可以同時使用containerd來運行容器,但是二者的鏡像用了命名空間隔離,彼此是獨立的,即鏡像不可以共用。因為Docker和containerd常常同時存在,因此在不需要使用Docker的系統(tǒng)中只安裝containerd即可。

containerd最早是為Docker設(shè)計的代碼,包含一些用戶相關(guān)的功能。相比之下,CRI-O是替代Docker或者containerd的高效且輕量級的容器運行時方案,是CRI的一個實現(xiàn),能夠運行符合OCI規(guī)范的容器,所以被稱為CRI-O。CRI-O是原生為生產(chǎn)系統(tǒng)運行容器設(shè)計的,有個簡單的命令行工具供測試用,但并不能進行容器管理。CRI-O支持OCI的容器鏡像格式,可以從容器鏡像倉庫中下載鏡像。CRI-O支持runC和Kata Containers這兩種低層容器運行時。

責任編輯:未麗燕 來源: Dockone.io
相關(guān)推薦

2010-08-20 13:29:33

OFDM

2021-02-08 21:40:04

SockmapBPF存儲

2012-01-12 14:37:34

jQuery

2013-04-07 14:09:55

Android應(yīng)用基本

2020-03-21 14:57:14

手機定位智能手機APP

2009-02-24 09:43:00

IP電話原理

2019-04-30 08:15:31

2011-11-29 12:17:00

2010-03-17 13:35:02

2016-08-18 00:04:09

網(wǎng)絡(luò)爬蟲抓取系統(tǒng)服務(wù)器

2019-11-28 10:45:28

ZooKeeper源碼分布式

2016-08-17 23:53:29

網(wǎng)絡(luò)爬蟲抓取系統(tǒng)

2013-09-22 14:02:09

內(nèi)存數(shù)據(jù)庫

2010-06-18 17:28:37

Linux Anacr

2009-12-22 15:39:36

IPPBX技術(shù)

2020-12-29 16:55:44

ZooKeeper運維數(shù)據(jù)結(jié)構(gòu)

2009-06-11 09:56:09

MySQL Repli原理

2011-07-07 14:10:21

Cocoa 內(nèi)省 hash

2011-07-07 14:46:10

Cocoa Xcode

2010-03-18 20:13:03

Java socket
點贊
收藏

51CTO技術(shù)棧公眾號