作者 | Anarcat
譯者 | Andy Song (pinewall) ? ? 共計翻譯:6 篇 貢獻時間:39 天
最近幾年,開源專案 Docker (已更名為Moby[1]) 在容器普及化方面建樹頗多。然而,它的功能特性不斷集中到一個單一、龐大的系統,該系統由具有 root 許可權執行的守護行程 dockerd
管控,這引發了人們的焦慮。對這些焦慮的闡述,具有代表性的是 Red Hat 公司的容器團隊負責人 Dan Walsh 在 KubeCon + CloudNativecon[2] 會議中的演講[3]。Walsh 講述了他的容器團隊目前的工作方向,即使用一系列更小、可協同工作的元件替代 Docker。他的戰鬥口號是“拒絕臃腫的守護行程”,理由是與公認的 Unix 哲學相違背。
Docker 模組化實踐
就像我們在早期文獻[4]中看到的那樣,容器的基礎操作不複雜:你首先拉取一個容器映象,利用該映象建立一個容器,最後啟動這個容器。除此之外,你要懂得如何構建映象並推送至映象倉庫。大多數人在上述這些步驟中使用 Docker,但其實 Docker 並不是唯一的選擇,目前的可替換選擇是 rkt
。rkt 引發了一系列標準的建立,包括執行時標準 CRI,映象標準 OCI 及網路標準 CNI 等。遵守這些標準的後端,如 CRI-O[5] 和 Docker,可以與 Kubernetes[6] 為代表的管理軟體協同工作。
這些標準促使 Red Hat 公司開發了一系列實現了部分標準的“核心應用”供 Kubernetes 使用,例如 CRI-O 執行時。但 Kubernetes 提供的功能不足以滿足 Red Hat 公司的 OpenShift[7] 專案所需。開發者可能需要構建容器並推送至映象倉庫,實現這些操作需要額外的一整套方案。
事實上,目前市面上已有多種構建容器的工具。來自 Sysdig 公司的 Michael Ducy 在分會場[8]中回顧了 Docker 本身之外的 8 種映象構建工具,而這也很可能不是全部。Ducy 將理想的構建工具定義如下:可以用可重現的方式建立最小化映象。最小化映象並不包含作業系統,只包含應用本身及其依賴。Ducy 認為 Distroless[9], Smith[10] 及 Source-to-Image[11]都是很好的工具,可用於構建最小化映象。Ducy 將最小化映象稱為“微容器”。
可重現映象是指構建多次結果保持不變的映象。為達到這個標的,Ducy 表示應該使用“宣告式”而不是“命令式”的方式。考慮到 Ducy 來自 Chef 配置管理工具領域,你應該能理解他的意思。Ducy 給出了符合標準的幾個不錯的實現,包括 Ansible 容器[12]、 Habitat[13]、 nixos-容器[14]和 Simth[10] 等,但你需要瞭解這些專案對應的程式語言。Ducy 額外指出 Habitat 構建的容器自帶管理功能,如果你已經使用了 systemd、 Docker 或 Kubernetes 等外部管理工具,Habitat 的管理功能可能是冗餘的。除此之外,我們還要提到從 Docker 和 Buildah[15] 專案誕生的新專案 BuildKit[16], 它是 Red Hat 公司 Atomic 工程[17]的一個元件。
使用 Buildah 構建容器
Buildah logo
Buildah 名稱顯然來自於 Walsh 風趣的 波士頓口音[18]; 該工具的品牌宣傳中充滿了波士頓風格,例如 logo 使用了波士頓梗犬(如圖所示)。該專案的實現思路與 Ducy 不同:為了構建容器,與其被迫使用宣告式配置管理的方案,不如構建一些簡單工具,結合你最喜歡的配置管理工具使用。這樣你可以如願的使用命令列,例如使用 cp
命令代替 Docker 的自定義指令 COPY
。除此之外,你可以使用如下工具為容器提供內容:1) 配置管理工具,例如Ansible 或 Puppet;2) 作業系統相關或程式語言相關的安裝工具,例如 APT 和 pip; 3) 其它系統。下麵展示了基於通用 shell 命令的容器構建場景,其中只需要使用 make
命令即可為容器安裝可執行檔案。
# 拉取基礎映象, 類似 Dockerfile 中的 FROM 命令
buildah from redhat
# 掛載基礎映象, 在其基礎上工作
crt=$(buildah mount)
ap foo $crt
make install DESTDIR=$crt
# 下一步,生成快照
buildah commit
有趣的是,基於這個思路,你可以復用主機環境中的構建工具,無需在映象中安裝這些依賴,故可以構建非常微小的映象。通常情況下,構建容器映象時需要在容器中安裝標的應用的構建依賴。例如,從原始碼構建需要容器中有編譯器工具鏈,這是因為構建並不在主機環境進行。大量的容器也包含了 ps
和 bash
這樣的 Unix 命令,對微容器而言其實是多餘的。開發者經常忘記或無法從構建好的容器中移除一些依賴,增加了不必要的開銷和攻擊面。
Buildah 的模組化方案能夠以非 root 方式進行部分構建;但mount
命令仍然需要 CAP_SYS_ADMIN
,有一個 工單[19] 試圖解決該問題。但 Buildah 與 Docker 都有[20]同樣的限制[21],即無法在容器內構建容器。對於 Docker,你需要使用“特權”樣式執行容器,一些特殊的環境很難滿足這個條件,例如 GitLab 持續整合[22];即使滿足該條件,配置也特別繁瑣[23]。
手動提交的步驟可以對建立容器快照的時間節點進行細粒度控制。Dockerfile 每一行都會建立一個新的快照;相比而言,Buildah 的提交檢查點都是事先選擇好的,這可以減少不必要的快照並節省磁碟空間。這也有利於隔離私鑰或密碼等敏感資訊,避免其出現在公共映象中。
Docker 構建的映象是非標準的、僅供其自身使用;相比而言,Buildah 提供多種輸出格式[24],其中包括符合 OCI 標準的映象。為向後相容,Buildah 提供了一個“使用 Dockerfile 構建”的命令,即 buildah bud
[25], 它可以解析標準的 Dockerfile。Buildah 提供 enter
命令直接檢視映象內部資訊,run
命令啟動一個容器。實現這些功能僅使用了 runc
在內的標準工具,無需在後臺執行一個“臃腫的守護行程”。
Ducy 對 Buildah 表示質疑,認為採用非宣告性不利於可重現性。如果允許使用 shell 命令,可能產生很多預想不到的情況;例如,一個 shell 指令碼下載了任意的可執行程式,但後續無法追溯檔案的來源。shell 命令的執行受環境變數影響,執行結果可能大相徑庭。與基於 shell 的工具相比,Puppet 或 Chef 這樣的配置管理系統在理論上更加可靠,因為它們的設計初衷就是收斂於最終配置;事實上,可以透過配置管理系統呼叫 shell 命令。但 Walsh 對此提出反駁,認為已有的配置管理工具可以在 Buildah 的基礎上工作,使用者可以選擇是否使用配置管理;這樣更加符合“機制與策略分離”的經典 Unix 哲學。
目前 Buildah 處於測試階段,Red Hat 公司正努力將其整合到 OpenShift。我寫這篇文章時已經測試過 Buildah,它缺少一些檔案,但基本可以穩定執行。儘管在錯誤處理方面仍有待提高,但它確實是一款值得你關註的容器工具。
替換其它 Docker 命令列
Walsh 在其演講中還簡單介紹了 Red hat 公司 正在開發的另一個暫時叫做 libpod[23] 的專案。專案名稱來源於 Kubernetes 中的 “pod”, 在 Kubernetes 中 “pod” 用於分組主機內的容器,分享名字空間等。
Libpod 提供 kpod
命令,用於直接檢查和操作容器儲存。Walsh 分析了該命令發揮作用的場景,例如 dockerd
停止響應或 Kubernetes 叢集崩潰。基本上,kpod
獨立地再次實現了 docker
命令列工具。kpod ps
傳回執行中的容器串列,kpod images
傳回映象串列。事實上,命令轉換速查手冊[26] 中給出了每一條 Docker 命令對應的 kpod
命令。
這種模組化實現的一個好處是,當你使用 kpod run
執行容器時,容器直接作為當前 shell 而不是 dockerd
的子行程啟動。理論上,可以直接使用 systemd 啟動容器,這樣可以消除 dockerd
引入的冗餘。這讓由套接字啟用的容器[27]成為可能,但暫時基於 Docker 實現該特性並不容易[28],即使藉助 Kubernetes[29] 也是如此。但我在測試過程中發現,使用 kpod
啟動的容器有一些基礎功能性缺失,具體而言是網路功能(!),相關實現在活躍開發[30]過程中。
我們最後提到的命令是 push
。雖然上述命令已經足以滿足本地使用容器的需求,但沒有提到遠端倉庫,藉助遠端倉庫開發者可以活躍地進行應用打包協作。倉庫也是持續部署框架的核心元件。skopeo[31] 專案用於填補這個空白,它是另一個 Atomic 成員專案,按其 README
檔案描述,“包含容器映象及映象庫的多種操作”。該專案的設計初衷是,在不用類似 docker pull
那樣實際去下載可能體積龐大的映象的前提下,檢查容器映象的內容。Docker 拒絕加入[32] 檢查功能,建議透過一個額外的工具實現該功能,這促成了 Skopeo 專案。除了 pull
、push
,Skopeo 現在還可以完成很多其它操作,例如在,不產生本地副本的情況下將映象在不同的倉庫中複製和轉換。由於部分功能比較基礎,可供其它專案使用,目前很大一部分 Skopeo 程式碼位於一個叫做 containers/image[33] 的基礎庫。Pivotal[34]、 Google 的 container-diff[35] 、kpod push
及 buildah push
都使用了該庫。
kpod
與 Kubernetes 並沒有緊密的聯絡,故未來可能會更換名稱(事實上,在本文刊發過程中,已經更名為 podman
[36]),畢竟 Red Hat 法務部門還沒有明確其名稱。該團隊希望實現更多 pod 級別的命令,這樣可以對多個容器進行操作,有點類似於 docker compose
[37]實現的功能。但在這方面,Kompose[38] 是更好的工具,可以透過 複合 YAML 檔案[39] 在 Kubernetes 叢集中執行容器。按計劃,我們不會實現類似於 [swarm
] 的 Docker 命令,這部分功能最好由 Kubernetes 本身完成。
目前看來,已經持續數年的 Docker 模組化努力終將碩果纍纍。但目前 kpod
處於快速迭代過程中,不太適合用於生產環境,不過那些工具的與眾不同的設計理念讓人很感興趣,而且其中大部分的工具已經可以用於開發環境。目前只能透過編譯原始碼的方式安裝 libpod,但最終會提供各個發行版的二進位制包。
本文最初發表[40]於 Linux Weekly News[41]。
via: https://anarc.at/blog/2017-12-20-docker-without-docker/
作者:Anarcat[43] 譯者:pinewall 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出