一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

揭秘Google和Facebook不用Docker的原因

Linux愛(ài)好者 ? 來(lái)源:51cto博客 ? 作者:51cto博客 ? 2021-06-26 15:37 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

寫(xiě)作本文的起因是我想讓修改后的分布式 PyTorch 程序能更快的在 Facebook 的集群上啟動(dòng)。探索過(guò)程很有趣,也展示了工業(yè)機(jī)器學(xué)習(xí)需要的知識(shí)體系。

2007 年我剛畢業(yè)后在 Google 工作過(guò)三年。當(dāng)時(shí)覺(jué)得分布式操作系統(tǒng) Borg 真好用。

從 2010 年離開(kāi) Google 之后就一直盼著它開(kāi)源,直到 Kubernetes 的出現(xiàn)。

Kubernetes 調(diào)度的計(jì)算單元是 containers(準(zhǔn)確的翻譯是“集裝箱”,而不是意思泛泛的“容器”,看看 Docker 公司的 Logo 上畫(huà)的是啥就知道作者的心意了)。

而一個(gè) container 執(zhí)行一個(gè) image,就像一個(gè) process 執(zhí)行一個(gè) program。

無(wú)論 Googlers 還是 ex-Googlers,恐怕在用 Borg 的時(shí)候都未曾接觸過(guò) container 和 image 這兩個(gè)概念。為啥 Borg 里沒(méi)有,而 Kubernetes 卻要引入了這樣兩個(gè)概念呢?

這個(gè)曾經(jīng)問(wèn)題在我腦海中一閃而過(guò)就被忽略了。畢竟后來(lái)我負(fù)責(zé)開(kāi)源項(xiàng)目比較多,比如百度 Paddle 以及螞蟻的 SQLFlow 和 ElasticDL,Docker 用起來(lái)很順手。于是也就沒(méi)有多想。

今年(2021 年)初,我加入 Facebook。恰逢 Facebook 發(fā)論文[1]介紹了其分布式集群管理系統(tǒng) Tupperware。

不過(guò) Tupperware 是一個(gè)注冊(cè)于 1946 年的品牌 https://en.wikipedia.org/wiki/Tupperware_Brands,所以在論文里只好起了另一個(gè)名字 Twine。

因?yàn)樾袠I(yè)里知道 Tupperware 這個(gè)名字的朋友很多,本文就不說(shuō) Twine 了。

總之,這篇論文的發(fā)表又引發(fā)了我對(duì)于之前問(wèn)題的回顧——Facebook 里也沒(méi)有 Docker!

和 Facebook Tuppware 團(tuán)隊(duì)以及 Google Borg 幾位新老同事仔細(xì)聊了聊之后,方才恍然。因?yàn)樾袠I(yè)里沒(méi)有看到相關(guān)梳理,本文是為記錄。

一言蔽之

簡(jiǎn)單的說(shuō),如果用 monolithic repository 來(lái)管理代碼,則不需要 Docker image(或者 ZIP、tarball、RPM、deb)之類(lèi)的“包”。

所謂 monolithic repo 就是一家公司的所有項(xiàng)目的所有代碼都集中放在一個(gè)(或者極少數(shù))repo 里。

因?yàn)?monolithic repository 得有配套的統(tǒng)一構(gòu)建系統(tǒng)(build system)否則編譯不動(dòng)那么老大一坨代碼。

而既然有統(tǒng)一的 build system,一旦發(fā)現(xiàn)某個(gè)集群節(jié)點(diǎn)需要執(zhí)行的程序依賴(lài)的某個(gè)模塊變化了,同步這個(gè)模塊到此節(jié)點(diǎn)既可。完全不需要打包再同步。

反之,如果每個(gè)項(xiàng)目在一個(gè)獨(dú)立的 git/svn repo 里,各自用不同的 build system,比如各個(gè)開(kāi)源項(xiàng)目在不同的 GitHub repo 里,則需要把每個(gè)項(xiàng)目 build 的結(jié)果打包。

而 Docker image 這樣支持分層的包格式讓我們只需要傳輸那些容納被修改的項(xiàng)目的最上面幾層,而盡量復(fù)用被節(jié)點(diǎn) cache 了的下面的幾層。

Google 和 Facebook 都使用 monolithic repository,也都有自己的 build systems(我這篇老文尋找 Google Blaze[2] 解釋過(guò) Google 的 build system)所以不需要“包”,當(dāng)然也就不需要 Docker images。

不過(guò) Borg 和 Tupperware 都是有 container 的(使用 Linux kernel 提供的一些 system calls,比如 Google Borg 團(tuán)隊(duì)十多年前貢獻(xiàn)給 Linux kernel 的 cgroup)來(lái)實(shí)現(xiàn) jobs 之間的隔離。

只是因?yàn)槿绻恍枰蠹?build Docker image 了,那么 container 的存在就不容易被關(guān)注到了。

如果不想被上述蔽之,而要細(xì)究這個(gè)問(wèn)題,那就待我一層一層剝開(kāi) Google 和 Facebook 的研發(fā)技術(shù)體系和計(jì)算技術(shù)體系。

Packaging

當(dāng)我們提交一個(gè)分布式作業(yè)(job)到集群上去執(zhí)行,我們得把要執(zhí)行的程序(包括一個(gè)可執(zhí)行文件以及相關(guān)的文件,比如 *.so,*.py)傳送到調(diào)度系統(tǒng)分配給這個(gè) job 的一些機(jī)器(節(jié)點(diǎn)、nodes)上去。

這些待打包的文件是怎么來(lái)的呢?當(dāng)時(shí)是 build 出來(lái)的。在 Google 里有 Blaze,在 Facebook 里有 Buck。

感興趣的朋友們可以看看 Google Blaze 的“開(kāi)源版本”Bazel[3],以及 Facebook Buck 的開(kāi)源版本[4]。

不過(guò)提醒在先:Blaze 和 Facebook Buck 的內(nèi)部版都是用于 monolithic repo 的,而開(kāi)源版本都是方便大家使用非 mono repos 的,所以理念和實(shí)現(xiàn)上有不同,不過(guò)基本使用方法還是可以感受一下的。

假設(shè)我們有如下模塊依賴(lài)(module dependencies),用 Buck 或者 Bazel 語(yǔ)法描述(兩者語(yǔ)法幾乎一樣):

python_binary(name=“A”, srcs=[“A.py”], deps=[“B”, “C”], 。。.)

python_library(name=“B”, srcs=[“B.py”], deps=[“D”], 。。.)

python_library(name=“C”, srcs=[“C.py”], deps=[“E”], 。。.)

cxx_library(name=“D”, srcs=[“D.cxx”, “D.hpp”], deps=“F”, 。。.)

cxx_library(name=“E”, srcs=[“E.cxx”, “E.hpp”], deps=“F”, 。。.)

那么模塊(build 結(jié)果)依賴(lài)關(guān)系如下:

A.py --》 B.py --》 D.so -

-》 C.py --》 E.so --》 F.so

如果是開(kāi)源項(xiàng)目,請(qǐng)自行腦補(bǔ),把上述模塊(modules)替換成 GPT-3,PyTorch,cuDNN,libc++ 等項(xiàng)目(projects)。

當(dāng)然,每個(gè) projects 里包含多個(gè) modules 也依賴(lài)其他 projects,就像每個(gè) module 有多個(gè)子 modules 一樣。

Tarball

最簡(jiǎn)單的打包方式就是把上述文件 {A,B,C}.py, {D,E,F(xiàn)}.so 打包成一個(gè)文件 A.zip,或者 A.tar.gz。

更嚴(yán)謹(jǐn)?shù)恼f(shuō),文件名里應(yīng)該包括版本號(hào)。比如 A-953bc.zip,其中版本號(hào) 953bc 是 git/Mercurial commit ID。

引入版本號(hào),可以幫助在節(jié)點(diǎn)本地 cache,下次運(yùn)行同一個(gè) tarball 的時(shí)候,就不需要下載這個(gè)文件了。

請(qǐng)注意這里我引入了 package caching 的概念。為下文解釋 Docker 預(yù)備。

XAR

ZIP 或者 tarball 文件拷貝到集群節(jié)點(diǎn)上之后,需要解壓縮到本地文件系統(tǒng)的某個(gè)地方,比如:/var/packages/A-953bc/{A,B,C}.py,{D,E,F(xiàn)}.so。

一個(gè)稍顯酷炫的方式是不用 Tarball,而是把上述文件放在一個(gè) overlay filesystem 的 loopback device image 里。這樣“解壓”就變成了“mount”。

請(qǐng)注意這里我引入了 loopback device image 的概念。為下文解釋 Docker 預(yù)備。

什么叫 loopback device image 呢?在 Unix 里,一個(gè)目錄樹(shù)的文件們被稱(chēng)為一個(gè)文件系統(tǒng)(filesystem)。

通常一個(gè) filesystem 存儲(chǔ)在一個(gè) block device 上。什么是 block device 呢?

簡(jiǎn)單的說(shuō),但凡一個(gè)存儲(chǔ)空間可以被看作一個(gè) byte array 的,就是一個(gè) block device。

比如一塊硬盤(pán)就是一個(gè) block device。在一個(gè)新買(mǎi)的硬盤(pán)里創(chuàng)建一個(gè)空的目錄樹(shù)結(jié)構(gòu)的過(guò)程,就叫做格式化(format)。

既然 block device 只是一個(gè) byte array,那么一個(gè)文件不也是一個(gè) byte array 嗎?

是的!在 Unix 的世界里,我們完全可以創(chuàng)建一個(gè)固定大小的空文件(用 truncate 命令),然后“格式化”這個(gè)文件,在里面創(chuàng)建一個(gè)空的文件系統(tǒng)。然后把上述文件 {A,B,C}.py,{D,E,F(xiàn)}.so 放進(jìn)去。

比如 Facebook 開(kāi)源的 XAR 文件[5]格式。這是和 Buck 一起使用的。

如果我們運(yùn)行 buck build A 就會(huì)得到 A.xar 。 這個(gè)文件包括一個(gè) header,以及一個(gè) squashfs loopback device image,簡(jiǎn)稱(chēng) squanshfs image。

這里 squashfs 是一個(gè)開(kāi)源文件系統(tǒng)。感興趣的朋友們可以參考這個(gè)教程[6],創(chuàng)建一個(gè)空文件,把它格式化成 squashfs,然后 mount 到本地文件系統(tǒng)的某個(gè)目錄(mount point)里。

待到我們 umount 的時(shí)候,曾經(jīng)加入到 mount point 里的文件,就留在這個(gè)“空文件”里了。

我們可以把它拷貝分發(fā)給其他人,大家都可以 mount 之,看到我們加入其中的文件。

因?yàn)?XAR 是在 squashfs image 前面加上了一個(gè) header,所以沒(méi)法用 mount -t squashf 命令來(lái) mount,得用 mount -t xar 或者 xarexec -m 命令。

比如,一個(gè)節(jié)點(diǎn)上如果有了 /packages/A-953bc.xar,我們可以用如下命令看到它的內(nèi)容,而不需要耗費(fèi) CPU 資源來(lái)解壓縮:

xarexec -m A-953bc.xar

這個(gè)命令會(huì)打印出一個(gè)臨時(shí)目錄,是 XAR 文件的 mount point。

分層

如果我們現(xiàn)在修改了 A.py,那么不管是 build 成 tarball 還是 XAR,整個(gè)包都需要重新更新。

當(dāng)然,只要 build system 支持 cache,我們是不需要重新生成各個(gè) *.so 文件的。

但是這個(gè)不解決我們需要重新分發(fā) .tar.gz 和 .xar 文件到集群的各個(gè)節(jié)點(diǎn)的麻煩。

之前節(jié)點(diǎn)上可能有老版本的 A-953bc87fe.{tar.gz,xar} 了,但是不能復(fù)用。為了復(fù)用 ,需要分層。

對(duì)于上面情況,我們可以根據(jù)模塊依賴(lài)關(guān)系圖,構(gòu)造多個(gè) XAR 文件。

A-953bc.xar --》 B-953bc.xar --》 D-953bc.xar -

-》 C-953bc.xar --》 E-953bc.xar --》 F-953bc.xar

其中每個(gè) XAR 文件里只有對(duì)應(yīng)的 build rule 產(chǎn)生的文件。比如,F(xiàn)-953bc.xar 里只有 F.so。

這樣,如果我們只修改了 A.py,則只有 A.xar 需要重新 build 和傳送到集群節(jié)點(diǎn)上。這個(gè)節(jié)點(diǎn)可以復(fù)用之前已經(jīng) cache 了的 {B,C,D,E,F(xiàn)}-953bc.xar 文件。

假設(shè)一個(gè)節(jié)點(diǎn)上已經(jīng)有 /packages/{A,B,C,D,E,F(xiàn)}-953bc.xar,我們是不是可以按照模塊依賴(lài)順序,運(yùn)行 xarexec -m 命令,依次 mount 這些 XAR 文件到同一個(gè) mount point 目錄,既可得到其中所有的內(nèi)容了呢?

很遺憾,不行。因?yàn)楹笠粋€(gè) xarexec/mount 命令會(huì)報(bào)錯(cuò) —— 因?yàn)檫@個(gè) mount point 已經(jīng)被前一個(gè) xarexec/mount 命令占據(jù)了。

下面解釋為什么文件系統(tǒng) image 優(yōu)于 tarball。

那退一步,不用 XAR 了,用 ZIP 或者 tar.gz 不行嗎?可以,但是慢。我們可以把所有 .tar.gz 都解壓縮到同一個(gè)目錄里。

但是如果 A.py 更新了,我們沒(méi)法識(shí)別老的 A.py 并且替換為新的,而是得重新解壓所有 .tar.gz 文件,得到一個(gè)新的文件夾。而重新解壓所有的 {B,C,D,E,F(xiàn)}.tar.gz 很慢。

Overlay Filesystem

有一個(gè)申請(qǐng)的開(kāi)源工具 fuse-overlayfs。它可以把幾個(gè)目錄“疊加”(overlay)起來(lái)。

比如下面命令把 /tmp/{A,B,C,D,E,F(xiàn)}-953bc 這幾個(gè)目錄里的內(nèi)容都“疊加”到 /pacakges/A-953bc 這個(gè)目錄里。

fuse-overlayfs -o

lowerdir=“/tmp/A-953bc:/tmp/B-953bc:。。.”

/packages/A-953bc

而 /tmp/{A,B,C,D,E,F(xiàn)}-953bc 這幾個(gè)目錄來(lái)自 xarcexec -m /packages/{A,B,C,D,E,F(xiàn)}-953bc.xar。

請(qǐng)注意這里我引入了 overlay filesystem 的概念。為下文解釋 Docker 預(yù)備。fuse-overlayfs 是怎么做到這一點(diǎn)的呢?

當(dāng)我們?cè)L問(wèn)任何一個(gè)文件系統(tǒng)目錄,比如 /packages/A 的時(shí)候,我們使用的命令行工具(比如 ls )調(diào)用 system calls(比如 open/close/read/write) 來(lái)訪(fǎng)問(wèn)其中的文件。

這些 system calls 和文件系統(tǒng)的 driver 打交道 —— 它們會(huì)問(wèn) driver:/packages/A 這個(gè)目錄里有沒(méi)有一個(gè)叫 A.py 的文件呀?

如果我們使用 Linux,一般來(lái)說(shuō),硬盤(pán)上的文件系統(tǒng)是 ext4 或者 btrfs。也就是說(shuō),Linux universal filesystem driver 會(huì)看看每個(gè)分區(qū)的文件系統(tǒng)是啥,然后把 system call 轉(zhuǎn)發(fā)給對(duì)應(yīng)的 ext4/btrfs driver 去處理。

一般的 filesystem drivers 和其他設(shè)備的 drivers 一樣運(yùn)行在 kernel mode 里。

這是為什么一般我們運(yùn)行 mount 和 umount 這類(lèi)操作 filesystems 的命令的時(shí)候,都需要 sudo。而 FUSE 是一個(gè)在 userland 開(kāi)發(fā) filesystem driver 的庫(kù)。

fuse-overlayfs 這命令利用 FUSE 這個(gè)庫(kù),開(kāi)發(fā)了一個(gè)運(yùn)行在 userland 的 fuse-overlayfs driver。

當(dāng) ls 命令詢(xún)問(wèn)這個(gè) overlayfs driver /packages/A-953bc 目錄里有啥的時(shí)候,這個(gè) fuse-overlayfs driver 記得之前用戶(hù)運(yùn)行過(guò) fuse-overlayfs 命令把 /tmp/{A,B,C,D,E}-953bc 這幾個(gè)目錄給疊加上去過(guò),所以它返回這幾個(gè)目錄里的文件。

此時(shí),因?yàn)?/tmp/{A,B,C,D,E}-953bc 這幾個(gè)目錄其實(shí)是 /packages/{A,B,C,D,E,F(xiàn)}-953bc.xar 的 mount points,所以每個(gè) XAR 就相當(dāng)于一個(gè) layer。

像 fuse-overlayfs driver 這樣實(shí)現(xiàn)把多個(gè)目錄“疊加”起來(lái)的 filesystem driver 被稱(chēng)為 overlay filesystem driver,有時(shí)簡(jiǎn)稱(chēng)為 overlay filesystems。

Docker Image and Layer

上面說(shuō)到用 overlay filesystem 實(shí)現(xiàn)分層。用過(guò) Docker 的人都會(huì)熟悉一個(gè) Docker image 由多層構(gòu)成。

當(dāng)我們運(yùn)行 docker pull 《image-name》 命令的時(shí)候,如果本機(jī)已經(jīng) cache 了這個(gè) image 的一部分 layers,則省略下載這些 layers。這其實(shí)就是用 overlay filesystem 實(shí)現(xiàn)的。

Docker 團(tuán)隊(duì)開(kāi)發(fā)了一個(gè) filesystem(driver)叫做 overlayfs —— 這是一個(gè)特定的 filesystem 的名字。

顧名思義,Docker overlayfs 也實(shí)現(xiàn)了“疊加”(overlay)的能力,這就是我們看到每個(gè) Docker image 可以有多個(gè) layers 的原因。

Docker 的 overlayfs 以及它的后續(xù)版本 overlayfs2 都是運(yùn)行在 kernel mode 里的。

這也是 Docker 需要機(jī)器的 root 權(quán)限的原因之一,而這又是 Docker 被詬病容易導(dǎo)致安全漏斗的原因。

有一個(gè)叫 btrfs 的 filesystem,是 Linux 世界里最近幾年發(fā)展很迅速的,用于管理硬盤(pán)效果很好。

這個(gè) filesystem 的 driver 也支持 overlay。所以 Docker 也可以被配置為使用這個(gè) filesystem 而不是 overlayfs。

不過(guò)只有 Docker 用戶(hù)的電腦的 local filesystem 是 btrfs 的時(shí)候,Docker 才能用 btrfs 在上面疊加 layers。

所以說(shuō),如果你用的是 macOS 或者 Windows,那肯定沒(méi)法讓 Docker 使用 btrfs 了。

不過(guò)如果你用的是 fuse-overlayfs,那就是用了一副萬(wàn)靈藥了。只是通過(guò) FUSE 在 userland 運(yùn)行的 filesystem 的性能很一般,不過(guò)本文討論的情形對(duì)性能也沒(méi)啥需求。

其實(shí) Docker 也可以被配置使用 fuse-overlayfs。Docker 支持的分層 filesystem 列表在這里 Docker storage drivers[7]。

為什么需要 Docker Image

總結(jié)上文所述,從編程到可以在集群上跑起來(lái),我們要做幾個(gè)步驟:

編譯:把源碼編譯成可執(zhí)行的形式。

打包:把編譯結(jié)果納入一個(gè)“包”里,以便部署和分發(fā)

傳輸:通常是集群管理系統(tǒng)(Borg、Kubernetes、Tupperware 來(lái)做)。如果要在某個(gè)集群節(jié)點(diǎn)上啟動(dòng) container,則需要把“包”傳輸?shù)酱斯?jié)點(diǎn)上,除非這個(gè)節(jié)點(diǎn)曾經(jīng)運(yùn)行過(guò)這個(gè)程序,已經(jīng)有包的 cache。

解包:如果“包”是 tarball 或者 zip,到了集群節(jié)點(diǎn)上之后需要解壓縮;如果“包”是一個(gè) filesystem image,則需要 mount。

把源碼分成模塊,可以讓編譯這步充分利用每次修改只改動(dòng)一小部分代碼的特點(diǎn),只重新編譯被修改的模塊,從而節(jié)省時(shí)間。

為了節(jié)省 2,3 和 4 的時(shí)間,我們希望“包”是分層的。每一層最好只包含一個(gè)或者幾個(gè)代碼模塊。這樣,可以利用模塊之間的依賴(lài)關(guān)系,盡量復(fù)用容納底層模塊的“層”。

在開(kāi)源的世界里,我們用 Docker image 支持分層的特點(diǎn),一個(gè)基礎(chǔ)層可能只包括某個(gè) Linux distribution(比如 CentOS)的 userland programs,如 ls、cat、grep 等。

在其上,可以有一個(gè)層包括 CUDA。再其上安裝 Python 和 PyTorch。再再之上的一層里是 GPT-3 模型的訓(xùn)練程序。

這樣,如果我們只是修改了 GPT-3 訓(xùn)練程序,則不需要重新打包和傳輸下面三層。

這里的邏輯核心是:存在“項(xiàng)目”(project)的概念。每個(gè)項(xiàng)目可以有自己的 repo,自己的 building system(GNU make、CMake、Buck、Bazel 等),自己的發(fā)行版本(release)。

所以每個(gè)項(xiàng)目的 release 裝進(jìn) Docker image 的一層 layer。與其前置多層合稱(chēng)為一個(gè) image。

為什么 Google 和 Facebook 不需要 Docker

經(jīng)過(guò)上述這么多知識(shí)準(zhǔn)備,請(qǐng)我們終于可以點(diǎn)題了。

因?yàn)?Google 和 Facebook 使用 monolithic repository,使用統(tǒng)一的 build system(Google Blaze 或者 Facebook Buck)。

雖然也可以利用“項(xiàng)目”的概念,把每個(gè)項(xiàng)目的 build result 裝入 Docker image 的一層。但是實(shí)際上并不需要。

利用 Blaze 和 Buck 的 build rules 定義的模塊,以及模塊之間依賴(lài)關(guān)系,我們可以完全去打包和解包的概念。

沒(méi)有了包,當(dāng)然就不需要 zip、tarball、以及 Docker image 和 layers 了。

直接把每個(gè)模塊當(dāng)做一個(gè) layer 既可。如果 D.so 因?yàn)槲覀冃薷牧?D.cpp 被重新編譯,那么只重新傳輸 D.so 既可,而不需要去傳輸一個(gè) layer 其中包括 D.so。

于是,在 Google 和 Facebook 里,受益于 monolithic repository 和統(tǒng)一的 build 工具。

我們把上述四個(gè)步驟省略成了兩個(gè):

編譯:把源碼編譯成可執(zhí)行的形式。

傳輸:如果某個(gè)模塊被重新編譯,則傳輸這個(gè)模塊。

Google 和 Facebook 沒(méi)在用 Docker

上一節(jié)說(shuō)了 monolithic repo 可以讓 Google 和 Facebook 不需要 Docker image。

現(xiàn)實(shí)是 Google 和 Facebook 沒(méi)有在使用 Docker。這兩個(gè)概念有區(qū)別。

我們先說(shuō)“沒(méi)在用”。歷史上,Google 和 Facebook 使用超大規(guī)模集群先于 Docker 和 Kubernetes 的出現(xiàn)。當(dāng)時(shí)為了打包方便,連 tarball 都沒(méi)有。

對(duì)于 C/C++ 程序,直接全靜態(tài)鏈接,根本沒(méi)有 *.so。于是一個(gè) executable binary file 就是“包”了。

直到今天,大家用開(kāi)源的 Bazel 和 Buck 的時(shí)候,仍然可以看到默認(rèn)鏈接方式就是全靜態(tài)鏈接。

Java 語(yǔ)言雖然是一種“全動(dòng)態(tài)鏈接”的語(yǔ)言,不過(guò)其誕生和演進(jìn)扣準(zhǔn)了互聯(lián)網(wǎng)歷史機(jī)遇,其開(kāi)發(fā)者發(fā)明 jar 文件格式,從而支持了全靜態(tài)鏈接。

Python 語(yǔ)言本身沒(méi)有 jar 包,所以 Blaze 和 Bazel 發(fā)明了 PAR 文件格式(英語(yǔ)叫 subpar),相當(dāng)于為 Python 設(shè)計(jì)了一個(gè) jar。開(kāi)源實(shí)現(xiàn)在這里[8]。

類(lèi)似的,Buck 發(fā)明了 XAR 格式,也就是我上文所說(shuō)的 squashfs image 前面加了一個(gè) header。其開(kāi)源實(shí)現(xiàn)在這里[9]。

Go 語(yǔ)言默認(rèn)就是全靜態(tài)鏈接的。在 Rob Pike 早期的一些總結(jié)里提到,Go 的設(shè)計(jì),包括全靜態(tài)鏈接,基本就是繞坑而行,繞開(kāi) Google C/C++ 實(shí)踐中遇到過(guò)的各種坑。

熟悉 Google C++ style guide 的朋友們應(yīng)該感覺(jué)到了 Go 語(yǔ)法覆蓋了 guide 說(shuō)的“應(yīng)該用的 C++ 語(yǔ)法”,而不支持 guide 說(shuō)的 “不應(yīng)該用的 C++ 的部分”。

簡(jiǎn)單的說(shuō),歷史上 Google 和 Facebook 沒(méi)有在用 Docker image,很重要的一個(gè)原因是,其 build system 對(duì)各種常見(jiàn)語(yǔ)言的程序都可以全靜態(tài)鏈接,所以可執(zhí)行文件就是“包”。

但這并不是最好的解法,畢竟這樣就沒(méi)有分層了。哪怕我只是修改了 main 函數(shù)里的一行代碼,重新編譯和發(fā)布,都需要很長(zhǎng)時(shí)間,十分鐘甚至數(shù)十分鐘,要知道全靜態(tài)鏈接得到的可執(zhí)行文件往往大小以 GB 計(jì)。

所以全靜態(tài)鏈接雖然是 Google 和 Facebook 沒(méi)有在用 Docker 的原因之一,但是并不是一個(gè)好選擇。

所以也沒(méi)被其他公司效仿。大家還是更愿意用支持分層 cache 的 Docker image。

完美解法的技術(shù)挑戰(zhàn)

完美的解法應(yīng)該支持分層 cache(或者更精確的說(shuō)是分塊 cache)。所以還是應(yīng)該用上文介紹的 monolithic repo 和統(tǒng)一 build system 的特點(diǎn)。

但是這里有一個(gè)技術(shù)挑戰(zhàn),build system 描述的模塊,而模塊通常比“項(xiàng)目”細(xì)粒度太多了。

以 C/C++ 語(yǔ)言為例,如果每個(gè)模塊生成一個(gè) .so 文件,當(dāng)做一個(gè)“層”或者“塊”以便作為 cache 的單元,那么一個(gè)應(yīng)用程序可能需要的 .so 數(shù)量就太多了。

啟動(dòng)應(yīng)用的時(shí)候,恐怕要花幾十分鐘來(lái) resolve symbols 并且完成鏈接。

所以呢,雖然 monolithic repo 有很多好處,它也有一個(gè)缺點(diǎn),不像開(kāi)源世界里,大家人力的把代碼分解成“項(xiàng)目”。

每個(gè)項(xiàng)目通常是一個(gè) GitHub repo,其中可以有很多模塊,但是每個(gè)項(xiàng)目里所有模塊 build 成一個(gè) *.so 作為一個(gè) cache 的單元。

因?yàn)橐粋€(gè)應(yīng)用程序依賴(lài)的項(xiàng)目數(shù)量總不會(huì)太多,從而控制了 layer 的總數(shù)。

好在這個(gè)問(wèn)題并非無(wú)解。既然一個(gè)應(yīng)用程序?qū)Ω鱾€(gè)模塊的依賴(lài)關(guān)系是一個(gè) DAG,那么我們總可以想辦法做一個(gè) graph partitioning,把這個(gè) DAG 分解成不那么多的幾個(gè)子圖。

仍然以 C/C++ 程序?yàn)槔?,我們可以把每個(gè)子圖里的每個(gè)模塊編譯成一個(gè) .a,而每個(gè)子圖里的所有 .a 鏈接成一個(gè) *.so,作為一個(gè) cache 的單元。

于是,如何設(shè)計(jì)這個(gè) graph partitioning 算法就成了眼前最重要的問(wèn)題了。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Google
    +關(guān)注

    關(guān)注

    5

    文章

    1789

    瀏覽量

    59031
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    7152

    瀏覽量

    125582
  • 分布式
    +關(guān)注

    關(guān)注

    1

    文章

    997

    瀏覽量

    75402
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4900

    瀏覽量

    70739
  • pytorch
    +關(guān)注

    關(guān)注

    2

    文章

    809

    瀏覽量

    13962

原文標(biāo)題:Google 和 Facebook 為什么不用 Docker?

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    docker無(wú)法啟用怎么解決?

    mengxing@mengxing-virtual-machine:/etc/docker$ sudo systemctl daemon-reload
    發(fā)表于 06-23 07:17

    Docker Volume管理命令大全

    Docker Volume管理命令大全
    的頭像 發(fā)表于 05-28 17:14 ?203次閱讀

    如何使用Docker部署大模型

    隨著深度學(xué)習(xí)和大模型的快速發(fā)展,如何高效地部署這些模型成為了一個(gè)重要的挑戰(zhàn)。Docker 作為一種輕量級(jí)的容器化技術(shù),能夠?qū)⒛P图捌湟蕾?lài)環(huán)境打包成一個(gè)可移植的容器,極大地簡(jiǎn)化了部署流程。本文將詳細(xì)介紹如何使用 Docker 部署大模型,并給出具體的步驟和示例。
    的頭像 發(fā)表于 05-24 16:39 ?344次閱讀

    Docker Compose的常用命令

    大家好,今天給大家分享Docker Compose的常用命令,以及docker-compose文件的屬性。Docker Compose 是一個(gè)用于定義和運(yùn)行多容器 Docker 應(yīng)用應(yīng)
    的頭像 發(fā)表于 04-30 13:40 ?452次閱讀

    Docker常用命令大全

    Docker 是一種開(kāi)源的應(yīng)用容器引擎,廣泛應(yīng)用于開(kāi)發(fā)、部署和運(yùn)行分布式應(yīng)用。掌握 Docker 常用命令對(duì)于開(kāi)發(fā)人員和運(yùn)維人員來(lái)說(shuō)非常重要。本文將為大家整理常用的Docker 命令,并按照功能分為多個(gè)部分,幫助你高效使用
    的頭像 發(fā)表于 04-22 12:47 ?397次閱讀

    【技術(shù)案例】Android in Docker

    Docker介紹Docker是一個(gè)開(kāi)源的容器化平臺(tái),用于打包、分發(fā)和運(yùn)行應(yīng)用程序。它通過(guò)將應(yīng)用及其所有依賴(lài)打包到獨(dú)立的容器中,確保應(yīng)用在不同環(huán)境中一致運(yùn)行。Docker提供快速部署、隔離性強(qiáng)和高效
    的頭像 發(fā)表于 04-02 16:33 ?673次閱讀
    【技術(shù)案例】Android in <b class='flag-5'>Docker</b>

    基于Docker鏡像逆向生成Dockerfile

    在本文中, 我們將通過(guò)理解Docker鏡像如何存儲(chǔ)數(shù)據(jù), 以及如何使用工具查看鏡像方方面面的信息來(lái)逆向工程一個(gè)Docker鏡像; 以及如何使用Python的Docker API來(lái)構(gòu)建一個(gè)類(lèi)似Dedockify的工具來(lái)創(chuàng)建Dock
    的頭像 發(fā)表于 03-10 09:45 ?603次閱讀
    基于<b class='flag-5'>Docker</b>鏡像逆向生成Dockerfile

    docker-proxy鏡像加速倉(cāng)庫(kù)

    自建多平臺(tái)容器鏡像代理服務(wù),支持 Docker Hub, GitHub, Google, k8s, Quay, Microsoft 等鏡像倉(cāng)庫(kù)。
    的頭像 發(fā)表于 03-06 16:06 ?471次閱讀
    <b class='flag-5'>docker</b>-proxy鏡像加速倉(cāng)庫(kù)

    docker配置網(wǎng)絡(luò)代理

    有時(shí)因?yàn)榫W(wǎng)絡(luò)原因,比如公司 NAT,或其它啥的,需要使用代理。Docker 的代理配置,略顯復(fù)雜,因?yàn)橛腥N場(chǎng)景。但基本原理都是一致的,都是利用 Linux 的 http_proxy 等環(huán)境變量。
    的頭像 發(fā)表于 03-03 17:18 ?474次閱讀

    云服務(wù)器 Flexus X 實(shí)例,Docker 集成搭建 NGINX

    Docker 集成搭建 NGINX 1、購(gòu)買(mǎi)華為云 Flexus X 實(shí)例 Flexus云服務(wù)器X實(shí)例-華為云 (huaweicloud.com) ? 2、docker 安裝 yum?install
    的頭像 發(fā)表于 01-13 11:09 ?951次閱讀
    云服務(wù)器 Flexus X 實(shí)例,<b class='flag-5'>Docker</b> 集成搭建 NGINX

    深度揭秘造成插件電感引腳脫落的可能原因

    深度揭秘造成插件電感引腳脫落的可能原因 編輯:谷景電子 在電子元件領(lǐng)域,插件電感是一種特別重要的的電感元器件,我們?cè)诤芏嚯娮釉O(shè)備上都可以看到插件電感的身影。但在實(shí)際應(yīng)用中,有時(shí)候可能會(huì)遇到插件電感
    的頭像 發(fā)表于 10-30 18:24 ?641次閱讀

    Docker運(yùn)行環(huán)境安裝

    作者:京東科技 林中 Docker是一個(gè)開(kāi)放的平臺(tái),用于開(kāi)發(fā)、發(fā)布和運(yùn)行應(yīng)用程序。Docker分離了應(yīng)用程序和運(yùn)行應(yīng)用的基礎(chǔ)設(shè)施,從而實(shí)現(xiàn)了軟件的快速交付。利用docker提供的一系列功能,包括構(gòu)建
    的頭像 發(fā)表于 10-29 11:28 ?664次閱讀

    谷景揭秘磁環(huán)插件電感失效的原因

    谷景揭秘磁環(huán)插件電感失效的原因 編輯:谷景電子 磁環(huán)插件電感是最近電子產(chǎn)品領(lǐng)域熱度非常高的一種電感元件,它的應(yīng)用可謂是特別普遍的。但在磁環(huán)插件電感的應(yīng)用中,有時(shí)候會(huì)出現(xiàn)失效的情況!你知道都可
    的頭像 發(fā)表于 08-27 22:46 ?548次閱讀

    手動(dòng)構(gòu)建Docker鏡像的方法

    不推薦使用docker commit命令,而應(yīng)該使用更靈活、更強(qiáng)大的dockerfile來(lái)構(gòu)建docker鏡像。
    的頭像 發(fā)表于 08-05 15:30 ?918次閱讀
    手動(dòng)構(gòu)建<b class='flag-5'>Docker</b>鏡像的方法

    ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)

    平臺(tái)上,而不用擔(dān)心運(yùn)行環(huán)境的變化導(dǎo)致應(yīng)用無(wú)法正常運(yùn)行的情況。 更輕松的維護(hù)和拓展:Docker使用的分層存儲(chǔ)以及鏡像的技術(shù),使得應(yīng)用重復(fù)部分的復(fù)用更為容易,也使得應(yīng)用的維護(hù)更新更加簡(jiǎn)單,基于基礎(chǔ)鏡像
    發(fā)表于 07-25 14:36