伦伦影院久久影视,天天操天天干天天射,ririsao久久精品一区 ,一本大道香蕉大久在红桃,999久久久免费精品国产色夜,色悠悠久久综合88,亚洲国产精品久久无套麻豆,亚洲香蕉毛片久久网站,一本一道久久综合狠狠老

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

k8s容器運行時演進歷史

Linux愛好者 ? 來源:Linux愛好者 ? 作者:Frank范 ? 2021-02-02 13:50 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在docker/k8s時代,經常聽到CRI, OCI,containerd和各種shim等名詞,看完本篇博文,您會有個徹底的理解。

典型的K8S Runtime架構

從最常見的Docker說起,kubelet和Docker的集成方案圖如下:

32017316-5f10-11eb-8b86-12bb97331649.png

當kubelet要創建一個容器時,需要以下幾步:

Kubelet 通過 CRI 接口(gRPC)調用 dockershim,請求創建一個容器。CRI 即容器運行時接口(Container Runtime Interface),這一步中,Kubelet 可以視作一個簡單的 CRI Client,而 dockershim 就是接收請求的 Server。目前 dockershim 的代碼其實是內嵌在 Kubelet 中的,所以接收調用的湊巧就是 Kubelet 進程;

dockershim 收到請求后,轉化成 Docker Daemon 能聽懂的請求,發到 Docker Daemon 上請求創建一個容器。

Docker Daemon 早在 1.12 版本中就已經將針對容器的操作移到另一個守護進程——containerd 中了,因此 Docker Daemon 仍然不能幫我們創建容器,而是要請求 containerd 創建一個容器;

containerd 收到請求后,并不會自己直接去操作容器,而是創建一個叫做 containerd-shim 的進程,讓 containerd-shim 去操作容器。這是因為容器進程需要一個父進程來做諸如收集狀態,維持 stdin 等 fd 打開等工作。而假如這個父進程就是 containerd,那每次 containerd 掛掉或升級,整個宿主機上所有的容器都得退出了。而引入了 containerd-shim 就規避了這個問題(containerd 和 shim 并不是父子進程關系);

我們知道創建容器需要做一些設置 namespaces 和 cgroups,掛載 root filesystem 等等操作,而這些事該怎么做已經有了公開的規范了,那就是 OCI(Open Container Initiative,開放容器標準)。它的一個參考實現叫做 runC。于是,containerd-shim 在這一步需要調用 runC 這個命令行工具,來啟動容器;

runC 啟動完容器后本身會直接退出,containerd-shim 則會成為容器進程的父進程,負責收集容器進程的狀態,上報給 containerd,并在容器中 pid 為 1 的進程退出后接管容器中的子進程進行清理,確保不會出現僵尸進程。

這個過程乍一看像是在搞我們:Docker Daemon 和 dockershim 看上去就是兩個不干活躺在中間劃水的啊,Kubelet 為啥不直接調用 containerd 呢?

當然可以,先看下現在的架構為什么如此繁雜。

容器歷史小敘

早期的k8s runtime架構,遠沒這么復雜,kubelet創建容器,直接調用docker daemon,docker daemon自己調用libcontainer就把容器運行起來。

但往往,事情不會如此簡單,一系列政治斗爭開始了,先是大佬們認為運行時標準不能被 Docker 一家公司控制,于是就攛掇著搞了開放容器標準 OCI。Docker 則把 libcontainer 封裝了一下,變成 runC 捐獻出來作為 OCI 的參考實現。

再接下來就是 rkt(coreos推出的,類似docker) 想從 Docker 那邊分一杯羹,希望 Kubernetes 原生支持 rkt 作為運行時,而且 PR 還真的合進去了。維護過一塊業務同時接兩個需求方的讀者老爺應該都知道類似的事情有多坑,Kubernetes 中負責維護 kubelet 的小組 sig-node 也是被狠狠坑了一把。

大家一看這么搞可不行,今天能有 rkt,明天就能有更多幺蛾子出來,這么搞下去我們小組也不用干活了,整天搞兼容性的 bug 就夠嗆。于是乎,Kubernetes 1.5 推出了 CRI 機制,即容器運行時接口(Container Runtime Interface),Kubernetes 告訴大家,你們想做 Runtime 可以啊,我們也資瓷歡迎,實現這個接口就成,成功反客為主。

不過 CRI 本身只是 Kubernetes 推的一個標準,當時的 Kubernetes 尚未達到如今這般武林盟主的地位,容器運行時當然不能說我跟 Kubernetes 綁死了只提供 CRI 接口,于是就有了 shim(墊片)這個說法,一個 shim 的職責就是作為 Adapter 將各種容器運行時本身的接口適配到 Kubernetes 的 CRI 接口上。

接下來就是 Docker 要搞 Swarm 進軍 PaaS 市場,于是做了個架構切分,把容器操作都移動到一個單獨的 Daemon 進程 containerd 中去,讓 Docker Daemon 專門負責上層的封裝編排。可惜 Swarm 在 Kubernetes 面前實在是不夠打,慘敗之后 Docker 公司就把 containerd 項目捐給 CNCF 縮回去安心搞 Docker 企業版了。

最后就是我們在上一張圖里看到的這一坨東西了,盡管現在已經有 CRI-O,containerd-plugin 這樣更精簡輕量的 Runtime 架構,dockershim 這一套作為經受了最多生產環境考驗的方案,迄今為止仍是 Kubernetes 默認的 Runtime 實現。

OCI, CRI

OCI(開放容器標準),規定了2點:

容器鏡像要長啥樣,即 ImageSpec。里面的大致規定就是你這個東西需要是一個壓縮了的文件夾,文件夾里以 xxx 結構放 xxx 文件;

容器要需要能接收哪些指令,這些指令的行為是什么,即 RuntimeSpec。這里面的大致內容就是“容器”要能夠執行 “create”,“start”,“stop”,“delete” 這些命令,并且行為要規范。

runC 為啥叫參考實現呢,就是它能按照標準將符合標準的容器鏡像運行起來,標準的好處就是方便搞創新,反正只要我符合標準,生態圈里的其它工具都能和我一起愉快地工作(……當然 OCI 這個標準本身制定得不怎么樣,真正工程上還是要做一些 adapter 的),那我的鏡像就可以用任意的工具去構建,我的“容器”就不一定非要用 namespace 和 cgroups 來做隔離。這就讓各種虛擬化容器可以更好地參與到游戲當中,我們暫且不表。

而 CRI 更簡單,單純是一組 gRPC 接口,掃一眼 kubelet/apis/cri/services.go 就能歸納出幾套核心接口:

一套針對容器操作的接口,包括創建,啟停容器等等;

一套針對鏡像操作的接口,包括拉取鏡像刪除鏡像等;

一套針對 PodSandbox(容器沙箱環境)的操作接口,我們之后再說。

現在我們可以找到很多符合 OCI 標準或兼容了 CRI 接口的項目,而這些項目就大體構成了整個 Kuberentes 的 Runtime 生態:

OCI Compatible:runC,Kata(以及它的前身 runV 和 Clear Containers),gVisor。其它比較偏門的還有 Rust 寫的 railcar

CRI Compatible:Docker(借助 dockershim),containerd(借助 CRI-containerd),CRI-O,Frakti,etc

OCI, CRI 確實不是一個好名字,在這篇文章的語境中更準確的說法:cri-runtime 和 oci-runtime。通過這個粗略的分類,我們其實可以總結出整個 Runtime 架構萬變不離其宗的三層抽象:

Orchestration API -> Container API(cri-runtime) -> Kernel API(oci-runtime)

根據這個思路,我們就很容易理解下面這兩種東西:

各種更為精簡的 cri-runtime(反正就是要干掉 Docker)

各種“強隔離”容器方案

Containerd和CRI-O

上一節看到現在的 Runtime 實在是有點復雜了,而復雜是萬惡之源(其實本質上就是想干掉 Docker),于是就有了直接拿 containerd 做 oci-runtime 的方案。當然,除了 Kubernetes 之外,containerd 還要接諸如 Swarm 等調度系統,因此它不會去直接實現 CRI,這個適配工作當然就要交給一個 shim 了。

containerd 1.0 中,對 CRI 的適配通過一個單獨的進程 CRI-containerd 來完成:

32a9dbdc-5f10-11eb-8b86-12bb97331649.png

containerd 1.1 中做的又更漂亮一點,砍掉了 CRI-containerd 這個進程,直接把適配邏輯作為插件放進了 containerd 主進程中:

3370f6e0-5f10-11eb-8b86-12bb97331649.png

但在 containerd 做這些事情前,社區就已經有了一個更為專注的 cri-runtime:CRI-O,它非常純粹,就是兼容 CRI 和 OCI,做一個 Kubernetes 專用的運行時:

350a75c6-5f10-11eb-8b86-12bb97331649.png

其中 conmon 就對應 containerd-shim,大體意圖是一樣的。

CRI-O 和(直接調用)containerd 的方案比起默認的 dockershim 確實簡潔很多,但沒啥生產環境的驗證案例,我所知道的僅僅是 containerd 在 GKE 上是 beta 狀態。因此假如你對 Docker 沒有特殊的政治恨意,大可不必把 dockershim 這套換掉。

強隔離容器:Kata,gVisor,Firecracker

一直以來,K8S都難以實現真正的多租戶。

理想來說,平臺的各個租戶(tenant)之間應該無法感受到彼此的存在,表現得就像每個租戶獨占這整個平臺一樣。具體來說,我不能看到其它租戶的資源,我的資源跑滿了不能影響其它租戶的資源使用,我也無法從網絡或內核上攻擊其它租戶。
Kubernetes 當然做不到,其中最大的兩個原因是:

kube-apiserver 是整個集群中的單例,并且沒有多租戶概念

默認的 oci-runtime 是 runC,而 runC 啟動的容器是共享內核的

對于第二個問題,一個典型的解決方案就是提供一個新的 OCI 實現,用 VM 來跑容器,實現內核上的硬隔離。runV 和 Clear Containers 都是這個思路。因為這兩個項目做得事情是很類似,后來就合并成了一個項目 Kata Container。Kata 的一張圖很好地解釋了基于虛擬機的容器與基于 namespaces 和 cgroups 的容器間的區別:

35d3881c-5f10-11eb-8b86-12bb97331649.png

當然,沒有系統是完全安全的,假如 hypervisor 存在漏洞,那么用戶仍有可能攻破隔離。但所有的事情都要對比而言,在共享內核的情況下,暴露的攻擊面是非常大的,做安全隔離的難度就像在美利堅和墨西哥之間修 The Great Wall,而當內核隔離之后,只要守住 hypervisor 這道關子就后顧無虞了。

嗯,一個 VM 里跑一個容器,聽上去隔離性很不錯,但不是說虛擬機又笨重又不好管理才切換到容器的嗎,怎么又要走回去了?

Kata 告訴你,虛擬機沒那么邪惡,只是以前沒玩好:

不好管理是因為沒有遵循“不可變基礎設施”,大家都去虛擬機上這摸摸那碰碰,這臺裝 Java 8 那臺裝 Java 6,Admin 是要 angry 的。Kata 則支持 OCI 鏡像,完全可以用上 Dockerfile + 鏡像,讓不好管理成為了過去時;

笨重是因為之前要虛擬化整個系統,現在我們只著眼于虛擬化應用,那就可以裁剪掉很多功能,把 VM 做得很輕量,因此即便用虛擬機來做容器,Kata 還是可以將容器啟動時間壓縮得非常短,啟動后在內存上和 IO 上的 overhead 也盡可能去優化。

不過話說回來,Kubernetes 上的調度單位是 Pod,是容器組啊,Kata 這樣一個虛擬機里一個容器,同一個 Pod 間的容器還怎么做 namespace 的共享?

這就要說回我們前面講到的 CRI 中針對 PodSandbox(容器沙箱環境)的操作接口了。第一節中,我們刻意簡化了場景,只考慮創建一個容器,而沒有討論創建一個 Pod。大家都知道,真正啟動 Pod 里定義的容器之前,kubelet 會先啟動一個 infra 容器,并執行 /pause 讓 infra 容器的主進程永遠掛起。這個容器存在的目的就是維持住整個 Pod 的各種 namespace,真正的業務容器只要加入 infra 容器的 network 等 namespace 就能實現對應 namespace 的共享。而 infra 容器創造的這個共享環境則被抽象為 PodSandbox。每次 kubelet 在創建 Pod 時,就會先調用 CRI 的 RunPodSandbox 接口啟動一個沙箱環境,再調用 CreateContainer 在沙箱中創建容器。

這里就已經說出答案了,對于 Kata Container 而言,只要在 RunPodSandbox 調用中創建一個 VM,之后再往 VM 中添加容器就可以了。最后運行 Pod 的樣子就是這樣的:

350a75c6-5f10-11eb-8b86-12bb97331649.png

說完了 Kata,其實 gVisor 和 Firecracker 都不言自明了,大體上都是類似的,只是:

gVisor 并不會去創建一個完整的 VM,而是實現了一個叫 “Sentry” 的用戶態進程來處理容器的 syscall,而攔截 syscall 并重定向到 Sentry 的過程則由 KVM 或 ptrace 實現。

Firecracker 稱自己為 microVM,即輕量級虛擬機,它本身還是基于 KVM 的,不過 KVM 通常使用 QEMU 來虛擬化除 CPU 和內存外的資源,比如 IO 設備,網絡設備。Firecracker 則使用 rust 實現了最精簡的設備虛擬化,為的就是壓榨虛擬化的開銷,越輕量越好。

責任編輯:xj

原文標題:淺析 k8s 容器運行時演進

文章出處:【微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 容器
    +關注

    關注

    0

    文章

    533

    瀏覽量

    23012
  • CRI
    CRI
    +關注

    關注

    1

    文章

    16

    瀏覽量

    12492
  • Docker
    +關注

    關注

    0

    文章

    535

    瀏覽量

    14363

原文標題:淺析 k8s 容器運行時演進

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    ELF-RV112B RKNN模型加載與運行時初始化

    ELF-RV112B RKNN模型加載與運行時初始化
    的頭像 發表于 04-03 16:08 ?117次閱讀
    ELF-RV112B RKNN模型加載與<b class='flag-5'>運行時</b>初始化

    S32K322可以在運行時在時鐘選項 A 和選項 F (A ? F) 之間動態切換嗎?

    我正在使用S32K322并使用預定義的時鐘選項(當前選項 A)S32K3xx 數據表和參考手冊中所述。 我想確認一下是否是支持在運行時在選項 A (PLL @160 MHz) 之間動態切換
    發表于 04-02 07:43

    Kubernetes容器運行時containerd與CRI-O如何選擇

    Kubernetes 1.24版本正式移除了dockershim,Docker不再是K8s的默認容器運行時。這個變化直接影響了所有K8s集群的運維方式——升級到1.24+必須切換到co
    的頭像 發表于 02-26 09:54 ?362次閱讀

    一文帶你徹底搞懂K8s網絡

    說實話,K8s 網絡是我見過最讓新手頭疼的知識點,沒有之一。記得我剛接觸 K8s 那會兒,看著流量在 Pod、Service、Node 之間穿梭,完全是一臉懵逼。后來踩了無數坑,熬了無數夜,總算把這套網絡模型摸透了。今天這篇文章,我會用最接地氣的方式,帶你徹底搞懂
    的頭像 發表于 02-06 10:15 ?646次閱讀

    K8s生產環境10大踩坑記錄復盤

    這篇文章記錄了我這些年在 K8s 生產環境踩過的坑。每一個案例都是血淚教訓,有些甚至導致了生產事故。希望通過分享這些經歷,能幫助大家避免重蹈覆轍。
    的頭像 發表于 02-05 15:51 ?628次閱讀

    請問如何在運行時調整mcu的主頻?

    能不能實現在運行時切換mcu的主頻,但不重啟mcu?
    發表于 01-16 07:12

    使用Nuclei Studio IDE計算程序運行時

    在使用Nuclei Studio IDE進行程序運行時,我們想知道我們編寫的程序運行時間有多長怎么辦呢?可以選擇調用IDE里面時間記錄函數_gettimeofday(),該函數用于記錄程序運行到本
    發表于 10-28 08:25

    怎么實現一套容器運行時,并符合OCI規范?

    如題,怎么實現一套容器運行時,并符合OCI規范
    發表于 10-10 07:35

    K8s集群性能調優實戰技巧

    大多數團隊在遇到K8s性能問題時,第一反應是"加機器"。但根據我對超過50個生產集群的分析,80%的性能問題源于配置不當,而非資源不足。
    的頭像 發表于 09-08 09:36 ?870次閱讀

    K8s存儲類設計與Ceph集成實戰

    在云原生時代,存儲是制約應用性能的關鍵瓶頸。本文將帶你深入理解K8s存儲類的設計原理,并手把手實現與Ceph的完美集成,讓你的集群存儲性能提升300%!
    的頭像 發表于 08-22 11:50 ?1020次閱讀

    解析K8S實用命令

    前言: 作為運維工程師,掌握 Kubernetes 命令行工具是日常工作的核心技能。本文將深入解析 K8S 最實用的命令,從基礎操作到高級技巧,助你成為容器化集群管理專家。
    的頭像 發表于 07-24 14:07 ?974次閱讀

    k8s權限管理指南說明

    我們在目前的k8s集群環境里面,只能在master節點上執行kubectl的一些命令,在其他節點上執行就會報錯。
    的頭像 發表于 06-26 14:06 ?855次閱讀

    什么是 K8S,如何使用 K8S

    Kubernetes(簡稱K8S)是一個用于管理容器化應用程序的開源平臺。以下是關于K8S及其使用方法的介紹: 一、什么是 K8S 核心特點 自動化
    發表于 06-25 06:45

    PLC設備運行時間數據采集到運維管理平臺如何實現

    在工廠設備管理工作中,往往需要統計各個設備的運行時間,能夠衡量其運行性能,主要為了方便管理人員對設備進行定期維護,以保障設備處于穩定高效的運行狀態,減少故障停機導致生產停工的問題。 對此,物通博聯
    的頭像 發表于 06-20 16:02 ?907次閱讀
    PLC設備<b class='flag-5'>運行時</b>間數據采集到運維管理平臺如何實現

    簡述K3SK8S的區別

    K3s 是CNCF 認證的 Kubernetes 發行版和Sandbox項目,專為低資源環境而設計。由 Rancher Labs 維護著 K3s
    的頭像 發表于 04-18 10:27 ?1920次閱讀