作者: 鮑江南
引言
在 2021 年四月左右,我有幸在 sealer 啟動初期瞭解到其相關工作,並且不久後就作為初始的幾位開發同學之一,加入到了 sealer 的開發工作中。
本文,我將回顧個人參與 sealer 開源專案的機緣巧合,參與過程中的挑戰,以及從中獲取的所悟所感,寫下一段文字進行分享,希望對開源新人有所幫助,能夠激勵想參與開源工作但還未踏出第一步的同學。
個人簡介
各位讀者好,本文是我釋出到阿里雲的第一篇文章,所以我先簡單進行下自我介紹。
我是鮑江南,是 sealer [ 1] 的 maintainer。本科畢業於中南大學圖靈班。現就讀於浙江大學,是 SEL 實驗室的一名碩士研究生。目前主要研究方向是混部叢集排程。
GitHub: https://github.com/justadogis...
旅途的開始
剛開始研究生生活的我,別人看來可能是躊躇滿志、蓄勢待發,但當時的我有種莫名的焦慮與迷茫。讀研時,我的實驗室是浙江大學的 SEL 實驗,主要的研究領域是雲端計算,因此在雲端計算工業界,我們有眾多的師兄師姐們。當時我來到了一家高新科技雲端計算公司“諧雲科技”擔任雲原生研發實習生,諧雲科技與阿里雲有眾多前沿雲原生合作專案,核心團隊成員來自於浙大 SEL 實驗室。在機緣巧合之下,我進入了諧雲&阿里云云原生專案組,認識了在阿里云云原生團隊的實驗室師兄-孫巨集亮,又通過他,認識了 sealer 的發起人-方海濤。他們都有很豐富的開源經歷。在閒聊時,得知巨集亮師兄曾經是 Docker 的 maintainer 時,我視巨集亮師兄為標杆,作為我努力的方向,這應該是多數人確立目標的方法吧。其中有一段對話令我印象深刻,師兄問過我“今年(2021)最想做到的事是什麼?”,我的回答是“在開源方面留下一些痕跡(其實在當時,我自己並未想清楚做開源是為什麼)“。現在想來,可能就是”焦慮“+”個人規劃不清晰”產生的“病急亂投醫”的簡單想法。但不管如何,當時也給自己定下了初步的目標,我就抱著 “Make it happen” 的態度全心地投入了。
大概在 2021 年 4 月的時候,我加入了 sealer 開源團隊,與幾位同學著力於開發 sealer(當初叫叢集映象)的核心能力。
責任與挑戰
sealer 是一款由阿里雲開源的雲原生工具,旨在幫助分散式軟體進行更好的封裝、分發與執行。如今,由於其設計理念的新穎,行業使用者基數的增長,sealer 已經捐給 CNCF 基金會,成為一個 CNCF的 sandbox 專案,朝著更廣闊的行業標準邁進。
軟體誕生之初,往往是混沌伴隨著希望。大目標的背後,需要 sealer 團隊解決太多的技術問題,如使用者介面、映象格式、分發模式、執行效率,軟體架構等等。最初的 sealer 開發分工中,我主要負責的部分是映象模組,包含叢集映象快取、叢集依賴容器映象快取、叢集映象共享等能力。
叢集映象快取:如何通過叢集映象層的複用,大幅提供映象構建效率。如 docker build,每次 build 會首先查詢之前本地快取的映象 build 內容,複用 build cache,減少硬碟佔用與提升映象構建效率。
叢集依賴容器映象快取:如何將叢集依賴的所有容器映象,在使用者無感知的情況下進行快取。早期, sealer build 構建叢集映象時,需要真實拉起叢集,待所有負載正常啟動後,再打包叢集映象。其中,很重要的一個部分是快取所有該叢集依賴的容器映象,使其可打包。
叢集映象共享:任何人都可以如同使用 docker 工具使用 sealer,push/pull/save/load 等方式共享叢集映象。
第一個技術挑戰
在 sealer 的眾多挑戰中,我印象比較深刻的是叢集依賴容器映象快取與私有倉庫的容器映象代理;記得是海濤哥找到我,說想讓我負責 sealer 的一個核心功能,即 “sealer 如何支援在構建過程中,在使用者無需提供額外資訊,使用者無感知的情況下,快取所有在構建過程中拉取的所有容器映象”。下面先簡單介紹下相關背景。
- 為何 sealer 需要快取叢集依賴的所有容器映象?
docker 容器映象會打包一個應用所需的檔案系統/配置資訊等,藉助虛擬化技術,使得 docker run 可以在任何環境下直接執行,即使在與外網隔離的情況下(應用本身無訪問外網的邏輯)。sealer 致力於定義叢集交付的標準,同樣也需要解決外網隔離映象拉取的問題,尤其是專有云交付場景,這是剛需。而這些應用容器映象就是 sealer 叢集映象所需檔案系統的一部分。解決這個問題有很多方法,比如最簡單的方法是:讓使用者填寫,然後統一拉取後,進行打包;但是海濤哥與我都認為這樣不夠 user-friendly 與優雅,使用 sealer 的使用者應該都是“懶人”,煩於做這些瑣碎的事情。那麼就讓我們為使用者做了這些繁瑣的事情吧。
- 為何 sealer 要解決私有倉庫的容器映象代理?
docker 社群中有一個2015年 open 的 issue [ 2] ,該 issue 是請求在 docker daemon 配置中,支援私有映象倉庫的映象代理,但至今社群都未解決該問題,該問題直觀描述如圖 1 所示:
圖 1 原生 docker 的映象代理邏輯
sealer 在映象構建階段,會將該叢集需要的所有容器映象快取到本地 registry 中,隨後叢集啟動後,讓 cri 統一從registry 中拉取容器映象。但是由於 docker 不支援私有倉庫的映象代理配置,導致拉取“example.hub/library/centos (example.hub為除了 dockerhub 以外的任一映象倉庫地址)”時,無法通過 docker daemon 配置 mirror 地址拉取,而是會直接到 “example.hub” 拉取。
但這不是我們期望的,因為我們在構建階段快取的容器映象就是為當前啟動階段準備的,並且在專有云交付場景下,叢集網路是與外界隔離的。對於這個問題,我們最初的可選解決思路是使用 K8s 的 webhook 功能,在pod 建立前在所有映象字首替換/加上本地 registry 的地址,不過在跟海濤哥討論後,我們還是認為這樣對使用者填寫的應用 YAML 有所侵入,我們堅持要把這件事做得更加優雅。
為了解決叢集依賴容器映象快取/私有倉庫的容器映象代理兩個問題,我開始了對docker [ 3] / registry [ 4] 原始碼的學習與瞭解;很快在 docker 原始碼中定位到 mirror 的配置部分,另外也從官方文件中瞭解到 registry 本身支援映象快取(pull through cache)的能力,如程式碼塊1所示。但是 registry 僅支援單個 remoteurl 的配置,而使用者的映象會來源於多個遠端映象倉庫,所以 registry 的原生配置也無法直接使用。
proxy:
remoteurl: https://registry-1.docker.io
username: [username]
password: [password]
程式碼塊 1 registry pull through cache 配置項
既然社群不支援,且 docker 對私有倉庫的映象代理的推進緩慢,我就直接基於社群的現存能力進行增強,並且改動不影響 docker 其他邏輯,僅做一些增量的配置項,使其實現我們需要的功能。
最後我們提供的 docker 與 registry 可支援的能力如圖 2 所示。
主要特性是:
- docker 支援任意映象倉庫的映象代理。
- registry 支援多遠端映象倉庫的快取,並且可以不用任何使用者配置,當然使用者也可以選擇自行配置。
圖 2 sealer 增強的 docker/registry 能力示意圖
成就感與責任
模糊印象中,在我們將 sealer 開源後的兩至三個月,sealer 就迎來了第一個在生產環境落地的使用者——政採雲。
我的成長經歷過程中有幾個讓我感到十分喜悅的事件,如大四到北京抖音實習——初入大公司的新鮮感,成功推免浙大碩士等;比較近的就是我們的開源工具有了第一個願意在生產環境落地的客戶,這說明我們做的工作得到了別人的認可,而其中很大一部分工作,是我投入心血思考做出來的,讓我特有成就感。
不過,隨著外界對 sealer 紛至沓來的關注度,我所需要承擔的責任也越來越大。以前寫軟體,往往只關心功能,能執行即可;現在做 sealer 的開源,需要關心的技術多太多,比如:如何優雅的評判與實現開源使用者的需求;如何設計好的架構,支撐 sealer 可持續發展;如何分配精力完成 sealer 的軟體質量等等。而提升這方面最直接的方式就是向優秀的專案學習,那段時間應該是我學習效率最高的一段時間,大量地閱讀 docker/registry 的原始碼;從 docker 學來的其中一個部分是程式碼功能模組化;在最初的 sealer 開發階段,總共只有幾個開發者,為了更快地迭代,大家對底層依賴的檔案,後設資料資訊都是自己寫一個工具類,但是每個人負責的模組有所區別,依賴的後設資料/檔案在持續迭代過程中極有可能發生變化,這就存在較大隱患。
因為偷師了一段時間的 docker 程式碼,我決定從某個版本開始,將所有映象相關的操作全部收斂到映象模組,提供介面給別的模組,在下層依賴檔案等操作,又繼續抽象出一層檔案系統模組;通過此次部分模組的重構,我們的程式碼比之前更加整潔,且降低了其他同學誤操作底層檔案問題的風險。
政採雲使用 sealer 落地實踐的過程中,幫我們發現了許多的問題,還記得那段時間頻繁地與現在 sealer 的另一位 maintainer 摩羯溝通問題,解決問題。印象很深刻的是,當時去武漢華科大找女朋友,出於對 sealer 第一個客戶的負責,在華中科技大學的咖啡廳/圖書館/校史室裡一一解決摩羯在社群提出的 issue。
收穫與思考
自信:我相信多數人在遇到挫折與困難時,都會告訴自己“我曾經做成了什麼”,讓自己堅持下去吧。
開放與溝通:在做 sealer 的過程中,其實有很多設計都是參考於 docker,但仍然還是會有疑惑;那段時間,我會頻繁地與社群同學溝通,指的不單是 sealer 社群,是整個開源社群;當初在映象壓縮時遇到一些問題,思考許久沒有結論,隨後寫了一封郵件問了 tar-split 的作者 vbatts,順利解決了疑惑。我認為溝通是工作最重要的能力之一,充分溝通往往能解決很多問題,避免大量無用功。
去開源崇拜:在前文“旅途的開始”,我提到了我對 2021 年的期望是在開源留下痕跡,但是其實我當時並不清晰,為什麼是在開源留下痕跡。可能是為了所謂的 reputation。在我較為完整地參與完一個開源專案之後,發現迷信開源貢獻,收穫所謂的 reputation 其實毫無意義。一定要做自己認可,有價值的事情,其他的並不重要。
不斷學習:文中提及的主要挑戰私有倉庫的容器映象代理,當時解決了這個問題讓我頗有成就感,過程中也學到了很多東西。不過現在回過頭看還是存在一些不可忽略的缺陷,比如必須使用 sealer 專供的 docker,這其實是一個比較重的行為,雖然我們把這個元件作為 sealer 的 rootFS 好像也合理,但這樣的話我們就需要提供大部分版本的 docker,並及時 track 上游社群版本變化。所以現在來審視當時的解決方案,其實並算不上優雅。最近在逛社群的時候,看到一個名為 intel/cri-resource-manager [ 5] 的工具,我猜測該工具出現的背景是 docker/K8s 社群接入 rdt [ 6 ] 等技術過於緩慢,所以 intel 開發了一個外掛,墊在 kubelet 與 cri 之間,以無侵入的方式為上層 Kubernetes 提供一些容器執行時維度的前沿特性。在學習該專案整體架構後,就想到 sealer 的私有倉庫的容器映象代理也許也可以以無侵入的方法解決。
未來規劃
效能提升:持續優化,提高交付效率與穩定性,確保 sealer 能夠先在叢集交付這個點上做到極致。
架構優化:sealer 目前各子模組較為耦合,新人入手門檻高,難以發展開發者生態,後續我們將致力於抽象各功能模組,讓社群參與人員能夠更專注在子領域。如 runtime 模組,支援 k0s/k3s 等。
擴大生態:引導社群參與到叢集映象的構建當中,豐富 sealer 的應用生態。
吸收更多開發者:社群需要吸收更多的開發者,壯大社群;同時需要更加簡單的 quick start,降低開發門檻。
多社群合作:sealer 社群正在與更多開源社群建立合作,如 openyurt [ 7] ,sealos [ 8] 。以促成多方共贏的局面。
參考連結:
[1] sealer:
https://github.com/sealerio/s...
[2] Enable engine to mirror private registry:
https://github.com/moby/moby/...
[3] moby:
[4] distribution:
https://github.com/distributi...
[5] cri-resource-manager:
https://github.com/intel/cri-...
[6] Intel Resource Director Technology:
https://www.intel.com/content...
[7] openyurt:
https://github.com/openyurtio...
[8] sealos:
https://github.com/labring/se...
點選“此處”,立即瞭解 sealer 專案!