題幹與適用場景
請設計一個供團隊發布和下載軟體包、容器映像或建置製品的倉庫。回答應涵蓋中繼資料、二進位 blob、版本標籤、權限、可用性、快取、撤回和稽核。
可以先選擇一種製品形態,再說明哪些抽象可重用。核心約束是同一內容只存一份、發布不可被部分讀取,下載方能驗證內容未被替換。
面試官考察點
中繼資料與內容分離
強回答會把套件名、版本、標籤、依賴和簽名與不可變內容 blob 分開,避免每次下載都掃描大檔案。
版本與一致性
候選人應說明語意版本、標籤移動、並發發布和刪除語義。版本解析錯誤會讓建置不可重現。
分發與成本
要解釋分塊上傳、斷點續傳、內容定址、CDN、跨區複製和垃圾回收,而不是只畫一個物件儲存。
安全與治理
權限、租戶隔離、簽名、SBOM、惡意製品掃描、稽核和撤回流程必須形成閉環。
回答前需要釐清的問題
- 製品是 npm 類套件、OCI 映像,還是任意建置檔案?
- 規模是每天多少發布、下載和總儲存量?
- 版本是否允許移動標籤,例如 latest?
- 發布後能否覆蓋版本,還是只能追加新版本?
- 是否需要私有租戶、代理上游倉庫和跨區容災?
- 撤回是阻止新下載、刪除內容,還是標記風險並保留稽核?
30 秒回答框架
「我先設計一個多租戶、內容定址的製品倉庫。發布端先上傳並校驗 blob,再提交不可變 manifest;標籤只是在中繼資料中指向已存在版本,移動標籤需要並發條件。下載端先讀中繼資料,再按 digest 從物件儲存或 CDN 取 blob,並校驗摘要與簽名。權限覆蓋命名空間和動作,撤回標記風險而不立即刪除稽核證據。熱門製品走 CDN,後台非同步複製、掃描和垃圾回收。」
分步驟深入解答
第一步:定義資源模型
資源包括 namespace、package、version、tag、manifest、blob、signature 和 provenance。manifest 只引用 digest、媒體類型和大小,blob 以 digest 作為不可變鍵。
第二步:設計發布流程
客戶端先申請上傳會話,分塊上傳到臨時空間;服務端校驗每塊和最終 digest,完成後原子提交 manifest。失敗會話過期清理,重複 digest 直接複用已有 blob。
第三步:處理版本與標籤
不可變版本一旦發布不能覆蓋;tag 可以移動但必須記錄操作者、前後指向和條件版本。解析依賴時優先鎖定精確版本和 digest,避免 latest 漂移。
第四步:設計下載路徑
中繼資料服務返回 manifest、依賴和簽名;blob 服務支援範圍請求、ETag 和 CDN。下載器校驗 digest,快取鍵包含 digest,標籤解析結果設定短 TTL。
第五步:擴展與容災
物件儲存承載大檔案,中繼資料儲存按 namespace 和 package 分片;跨區複製 manifest 後再複製 blob,並以複製狀態決定新區域是否可讀。
第六步:安全與營運
權限採用最小化的讀、寫、發布、改 tag 和刪除動作;掃描惡意內容、產生 SBOM、驗證簽名和來源證明。撤回把版本置為 blocked,阻止新下載但保留證據,所有動作寫稽核日誌。
高品質示範回答
「我把倉庫拆成中繼資料服務、blob 儲存和非同步治理任務。客戶端先建立分塊上傳會話,blob 完成摘要校驗後,manifest 以交易方式引用這些不可變 digest。版本不可覆蓋,tag 移動需要條件版本並記錄歷史。下載先解析精確版本,再從 CDN 或物件儲存按 digest 取內容並校驗簽名。
熱門 blob 用內容定址快取和範圍請求降低成本;後台做跨區複製、惡意掃描、SBOM 與 provenance 處理。私有 namespace 使用租戶級權限和配額。撤回標記 blocked、停止新下載並觸發建置系統告警,不刪除稽核證據。關鍵指標包括發布成功率、p95 下載延遲、快取命中率、複製滯後和未授權存取率。」
常見錯誤
- 讓客戶端直接改物件儲存 → 繞過權限和完整性校驗 → 用短期上傳會話並由服務端提交 manifest。
- 允許覆蓋已發布版本 → 建置不可重現 → 版本不可變,使用新版本修復。
- 把 latest 當永久快取鍵 → 內容悄悄漂移 → 按 digest 快取,標籤只做短 TTL 解析。
- 只存二進位不存 manifest → 無法表達依賴和簽名 → 保存結構化 manifest 與 provenance。
- 發布後立刻同步所有區域 → 跨區半成品可讀 → 先複製 blob 與 manifest,再更新可讀狀態。
- 刪除撤回製品 → 稽核和事故複盤丟失 → 標記 blocked,按保留策略非同步清理。
- 只做登入鑑權 → 租戶間可能越權 → 對 namespace、動作和製品逐層授權。
- 掃描阻塞發布請求 → 上傳高峰延遲失控 → 先存 quarantine,非同步掃描後改變可用狀態。
追問及應對
追問一:兩個發布者同時移動同一個 tag 怎麼辦?
使用條件版本或 compare-and-swap;衝突返回目前版本,讓客戶端重試並顯示歷史,禁止最後寫入靜默覆蓋。
追問二:如何保證下載到完整內容?
manifest 宣告 digest、大小和媒體類型;客戶端校驗摘要,失敗從其他副本重試,服務端記錄校驗失敗率。
追問三:跨區複製落後時能否發布?
主區域可以接受發布,但將版本標為複製中;目標區域只有 manifest、依賴 blob 和策略達到一致後才宣告可讀。
追問四:如何回收重複 blob?
從所有活躍 manifest、簽名和保留策略建立引用集合,標記無引用 blob,經過寬限期和並發檢查後刪除。
追問五:供應鏈證明如何進入下載決策?
把簽名、SBOM 和 provenance 與 manifest 關聯;策略引擎按租戶、環境和製品風險決定允許下載、隔離或只告警。
來源一:OCI Distribution Specification
OCI 規範把 manifest、descriptor 和 blob 作為分發核心,並定義 push、pull、digest 與錯誤語義,為內容定址倉庫的資源模型提供依據。
來源二:npm Registry 中繼資料
npm Registry 的中繼資料示例展示版本、dist-tags 與套件資訊分離,說明標籤解析和不可變版本需要不同的一致性與快取策略。
來源三:SLSA 供應鏈完整性
Google 對 SLSA 的介紹強調製品來源、可追溯性和防篡改證明;這些訊號可與倉庫的簽名、SBOM、掃描和下載策略組合。