在Kubernetes中引入Container Runtime Interface (CRI)
寫在前面
找這方面的資料.看到所以翻譯下
「 傍晚時分,你坐在屋檐下,看著天慢慢地黑下去,心里寂寞而凄涼,感到自己的生命被剝奪了。當(dāng)時我是個年輕人,但我害怕這樣生活下去,衰老下去。在我看來,這是比死亡更可怕的事。--------王小波」
Kubernetes節(jié)點的最低層是啟動和停止容器的軟件。我們稱之為“容器運行時”。最廣為人知的容器運行時是Docker,但它并不是唯一的容器運行時。事實上,容器運行時空間一直在快速發(fā)展。作為使Kubernetes更具可擴展性的努力的一部分,我們一直致力于Kubernetes中用于容器運行時的新插件API,稱為“CRI”。
CRI是什么? Kubernetes為什么需要它?
每個容器運行時都有自己的優(yōu)點,許多用戶要求Kubernetes支持更多的運行時。在Kubernetes 1.5版本中,我們自豪地引入了容器運行時接口(CRI)——一個插件接口,它使kubelet能夠使用各種各樣的容器運行時,而不需要重新編譯。CRI包括協(xié)議緩沖區(qū)、gRPC API和庫,以及正在積極開發(fā)的其他規(guī)范和工具。CRI在Kubernetes 1.5中以Alpha版本發(fā)布。
在Kubernetes中,支持可互換的容器運行時并不是一個新概念。在1.3版本中,我們宣布了rktnetes項目,以啟用rkt容器引擎作為Docker容器運行時的替代方案。然而,Docker和rkt都通過一個內(nèi)部和易變的接口直接和深入地集成到kubelet源代碼中。這樣的集成過程需要對Kubelet的內(nèi)部特性有深入的了解,并且會給Kubernetes社區(qū)帶來巨大的維護開銷。這些因素對新生的容器運行時形成了很高的進入壁壘。通過提供一個清晰定義的抽象層,我們消除了障礙,并允許開發(fā)人員專注于構(gòu)建他們的容器運行時。這是邁向真正實現(xiàn)可插拔容器運行時和構(gòu)建更健康的生態(tài)系統(tǒng)的一小步,但卻是重要的一步。
Kubelet使用gRPC框架通過Unix套接字與容器運行時(或運行時的CRI shim)通信,其中Kubelet作為客戶端,CRI shim作為服務(wù)器。
協(xié)議緩沖區(qū)API包括兩個gRPC服務(wù),ImageService和RuntimeService。ImageService提供了從存儲庫中提取圖像、檢查和刪除圖像的rpc。RuntimeService包含rpc來管理pod和容器的生命周期,以及與容器交互的調(diào)用(exec/attach/port-forward)。一個管理圖像和容器的單片容器運行時(例如,Docker和rkt)可以通過一個套接字同時提供兩個服務(wù)。套接字可以在Kubelet中通過——container-runtime-endpoint和——image-service-endpoint標(biāo)志來設(shè)置。Pod和容器生命周期管理
service RuntimeService { // Sandbox operations. rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {} rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {} rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {} rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {} rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {} // Container operations. rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {} rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {} rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {} rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {} rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {} rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {} ... }
Pod由一組應(yīng)用程序容器組成,它們位于具有資源約束的獨立環(huán)境中。在CRI中,這個環(huán)境稱為PodSandbox。我們有意為容器運行時留出一些空間,讓它們根據(jù)PodSandbox內(nèi)部的操作方式來不同地解釋PodSandbox。對于基于管理程序的運行時,PodSandbox可能代表一個虛擬機。對于其他的,比如Docker,它可能是Linux名稱空間。PodSandbox必須遵守pod資源規(guī)范。在v1alpha1 API中,這是通過啟動kubelet創(chuàng)建并傳遞給運行時的pod級cgroup中的所有進程來實現(xiàn)的。
在啟動一個pod之前,kubelet調(diào)用RuntimeService。RunPodSandbox來創(chuàng)建環(huán)境。這包括為pod設(shè)置網(wǎng)絡(luò)(例如,分配IP)。一旦PodSandbox是活動的,就可以獨立地創(chuàng)建/啟動/停止/刪除單個容器。要刪除pod, kubelet將在停止并刪除PodSandbox之前停止并刪除容器。
Kubelet負(fù)責(zé)通過rpc管理容器的生命周期,執(zhí)行容器生命周期鉤子和活動/就緒檢查,同時遵守pod的重啟策略。
為什么必須使用以容器為中心的接口?
Kubernetes有一個帶有Pod資源的聲明性API。我們考慮的一種可能的設(shè)計是,讓CRI在其抽象中重用聲明性Pod對象,讓容器運行時可以自由地實現(xiàn)和練習(xí)其自己的控制邏輯,以實現(xiàn)所需的狀態(tài)。這將極大地簡化API,并允許CRI在更廣泛的運行時范圍內(nèi)工作。我們在設(shè)計階段的早期就討論了這種方法,并基于幾個原因決定不采用它。首先,kubelet中有許多pod級別的特性和特定的機制(例如,崩潰循環(huán)回退邏輯),這將是所有運行時重新實現(xiàn)的重大負(fù)擔(dān)。第二,也是更重要的,Pod規(guī)范過去(現(xiàn)在)仍在快速發(fā)展。許多新特性(例如init容器)不需要對底層容器運行時進行任何更改,只要kubelet直接管理容器即可。CRI采用了一個命定的容器級接口,這樣運行時就可以共享這些公共特性,以獲得更好的開發(fā)速度。這并不意味著我們偏離了“水平觸發(fā)”的哲學(xué)——kubelet負(fù)責(zé)確保實際的狀態(tài)被驅(qū)動到聲明的狀態(tài)。
執(zhí)行/高度/左前請求
service RuntimeService { ... // ExecSync runs a command in a container synchronously. rpc ExecSync(ExecSyncRequest) returns (ExecSyncResponse) {} // Exec prepares a streaming endpoint to execute a command in the container. rpc Exec(ExecRequest) returns (ExecResponse) {} // Attach prepares a streaming endpoint to attach to a running container. rpc Attach(AttachRequest) returns (AttachResponse) {} // PortForward prepares a streaming endpoint to forward ports from a PodSandbox. rpc PortForward(PortForwardRequest) returns (PortForwardResponse) {} ... }
Kubernetes提供了一些特性(例如kubectl exec/attach/port-forward),讓用戶可以與pod和其中的容器進行交互。Kubelet現(xiàn)在通過調(diào)用容器運行時的本地方法調(diào)用或使用節(jié)點上可用的工具(例如nsenter和socat)來支持這些特性。在節(jié)點上使用工具不是一個可移植的解決方案,因為大多數(shù)工具都假定pod是使用Linux名稱空間隔離的。在CRI中,我們在API中顯式地定義這些調(diào)用,以允許特定于運行時的實現(xiàn)。
目前kubelet實現(xiàn)的另一個潛在問題是,kubelet處理所有流請求的連接,因此它可能成為節(jié)點上網(wǎng)絡(luò)流量的瓶頸。在設(shè)計CRI時,我們合并了這個反饋,以允許運行時消除中間人。容器運行時可以根據(jù)請求啟動一個單獨的流服務(wù)器(并可能將資源使用情況記錄到pod中!),并將服務(wù)器的位置返回給kubelet。然后Kubelet將此信息返回給Kubernetes API服務(wù)器,該服務(wù)器將直接打開到運行時提供的服務(wù)器的流連接,并將其連接到客戶端。
還有許多CRI的其他方面在這篇博文中沒有涉及。所有細(xì)節(jié)請參閱設(shè)計文件和方案的列表。
當(dāng)前的狀態(tài)
盡管CRI仍處于早期階段,但已經(jīng)有幾個項目在開發(fā)中使用CRI集成容器運行時。以下是一些例子:
cri-o: OCI conformant runtimes.
rktlet: the rkt container runtime.
frakti: hypervisor-based container runtimes.
docker CRI shim.
。 如果您有興趣嘗試這些可選的運行時,可以根據(jù)各個存儲庫了解最新的進度和說明。
對于有興趣集成新的容器運行時的開發(fā)人員,請參閱開發(fā)人員指南,了解API的已知限制和問題。我們正在積極地整合早期開發(fā)人員的反饋,以改進API。開發(fā)人員應(yīng)該期待偶爾的API破壞變化(畢竟是Alpha版本)。
嘗試新的CRI-Docker集成
Kubelet在默認(rèn)情況下還沒有使用CRI,但我們正在積極努力實現(xiàn)這一點。第一步是使用CRI重新集成Docker和kubelet。在1.5版中,我們擴展了kubelet以支持CRI,并為Docker添加了一個內(nèi)置CRI shim。這允許kubelet以Docker的名義啟動gRPC服務(wù)器。要嘗試新的kubelet- cri - docker集成,您只需使用——feature-gates=StreamingProxyRedirects=true啟動Kubernetes API服務(wù)器,以啟用新的流重定向特性,然后使用——experimental-cri=true啟動kubelet。
除了一些缺失的特性外,新集成始終通過了主要的端到端測試。我們計劃很快擴大測試覆蓋范圍,并鼓勵社區(qū)報告任何問題,以幫助過渡。
Docker Kubernetes
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。