Sia-Minio Integration Postmortem

Michael Lynch

Sia-Minio 整合事後檢討

原文由 Michael Lynch 發布,訂閱此部落格

我在 Google 工作期間學到最受用的事情之一,就是無究責事後檢討的做法。當出了問題,你會等風波平息後,再撰寫一份報告來分析整個經過。這份報告會說明問題是如何發生的,並列出團隊未來可以採取哪些具體步驟來預防類似問題再度發生。

上週我看到一個很適合做事後檢討的機會。一個由懸賞資助、將 Sia 支援整合進 Minio 的專案雖然已正式完工,但比預期多花了好幾個月,而且期間經歷了多次大規模的重寫。

Sia 是一項去中心化的雲端儲存技術。我之前就寫過相關文章,因為它是我最喜歡的技術之一。Minio 則是一套開源、相容於 S3 的檔案伺服器。兩者整合後,代表使用者現在可以透過任何相容於 Amazon S3 的備份軟體,將資料備份到 Sia 網路上。

這項整合是一件大事,等 Sia 在十二月發布後的軟體趨於穩定,我打算再寫更多相關內容。在此同時,我認為這是個帶領大家對整合過程進行事後檢討的寶貴機會。我向 Nebulous Labs 團隊提出了這個想法,他們也很認同。我聯繫了 Sia-Minio 整合程式碼的作者,他也相當支持,並同意與我一起撰寫這份報告。Nebulous Labs 與 Minio 團隊都已審閱並核准發布,因此你可以在下方看到我們的完整報告:


Minio 整合懸賞事後檢討

Nebulous Labs 事件 #1

日期:2017-12-01

作者

  • Michael Lynch - @mtlynch - Sia 部落客、/r/siacoin 版主。
  • David Gore - @dvstate - 開發者、懸賞得主

審閱者

  • David Vorick - @taek42 - 首席開發者,Nebulous Labs
  • Zach Herbert - @zherbert - 營運副總裁,Nebulous Labs
  • @harshavardhana - Minio 維護者

背景:什麼是事後檢討?

事後檢討是一種練習,目的是從不如預期的近期經驗中學習。

事後檢討是無究責的:我們要找出的是導致不良結果的「流程」問題,而非追究或羞辱「個人」。我們假設所有參與相關事件的人都是有能力且出於善意的。

詳情請參閱《SRE 寶典》中的「Postmortem Culture: Learning from Failure」一章。

摘要

7 月 19 日,Nebulous Labs 宣布懸賞 300,000 SC,徵求可實際運作的 Sia 與 Minio(開源、相容於 S3 的檔案伺服器)整合方案。開發者 David Gore(@dvstate)在五天後就發布了概念驗證,並在不到十天後獲頒全額獎金。

然而,這項整合又花了額外三個月才被合併進 Minio 的程式碼庫。要讓程式碼被 Minio 接受,需要對程式碼進行全面性的重新架構,而 @dvstate 為此付出了大量工作,這些都未在懸賞中獲得正式報酬。

整合雖然完成了,但必須加上幾個在當初懸賞中未預期的限制:

  • 僅支援有限的檔名白名單字元,比 Sia 允許的範圍更為嚴格。
  • 不支援分段上傳(multipart)檔案傳輸。
  • 僅有兩個極簡單的函式具備自動化測試涵蓋率。

影響

這次事件最重大的影響,是與關鍵夥伴的整合被延後了好幾個月。Sia 獲得 S3 相容性是一項巨大的里程碑,但由於整個過程被拉得太長,我們感覺這項成就的力道與氣勢也被削弱了。

過程中的波折也讓外界對 Sia 產生了負面觀感:

  • 與 Sia 整合很困難,即使使用 Sia 原生的 Go 語言,也需要重複造輪子。
  • 要完成 Sia 的懸賞很困難,因為驗收標準不明確。

經驗教訓

哪些方面做得好

  • Sia 已成功整合至 Minio。
  • Sia 社群成員使用多種 S3 用戶端,在不同情境下協助測試 Minio 整合。

哪些方面出了問題

  • 對於功能與需求的溝通不良,導致整合程式碼被多次重寫。
  • Minio 維護者的審查與 PR 更新之間存在很長的延遲(有些情況下長達數週)。
  • 由於 Sia 整合的 PR 還在進行期間 Minio 程式碼庫本身也在變動,@dvstate 不得不花費相當多時間解決合併衝突。

哪些方面算是幸運

  • 在 Nebulous 已支付懸賞後,@dvstate 仍自願投入時間,花了數個月繼續處理整合工作。
  • @dvstate 自行出資啟動、設定並提供一台 Sia 測試伺服器供 Minio 團隊測試使用。
  • Minio 維護者慷慨地投入時間,持續數個月審查同一個 PR。

時程

觀察到的問題

需求不明確

懸賞說明中對 Sia-Minio 整合的許多細節都未定義清楚。它只規定「使用者必須能夠使用 Minio 用戶端上傳/下載 Sia 檔案」,卻未提及來自 Minio 維護者的任何限制或要求。

此外,有數位 Sia 使用者透過 Sia Slack 的 #bounties 頻道或私訊聯繫 @dvstate 要求加入功能。由於沒有權威的需求定義,@dvstate 擔心若忽略這些要求會失去獲獎資格,因此實作了這些額外功能。

因此,@dvstate、Minio 維護者與 Sia 使用者之間對於下列問題產生了混淆:

  • 哪些第三方函式庫可被接受
  • Sia 整合是否可在檔案系統上維護快取以保存狀態資訊與中繼資料
  • Sia 整合是否必須實作分段檔案傳輸
  • Sia 整合是否必須支援儲存桶(bucket)政策設定
  • 需要支援哪些 S3 用戶端應用程式(例如 mc、s3cmd)
  • 需要何種程度的手動測試來證明功能正常
  • Sia 整合可使用多少個 Sia 專屬的環境變數
  • 需要多少測試涵蓋率
  • 對 Minio UI 需要/允許做哪些變更
  • 對 Minio 文件需要做哪些變更

@dvstate 最終因應 Minio 維護者提出、但未在原始懸賞說明中載明的要求,寫了三個截然不同的整合版本(第一版第二版第三版)。

建議行動項目

  • 對於未來的 Sia 懸賞,應事先與第三方維護者合作確立需求,並將其納入懸賞的獲獎標準。

  • 為懸賞建立客觀的驗收測試。例如:

    1. 伺服器上已部署 siad,並有 500 SC 的額度(allowance)。

    2. 用戶端使用下列指令啟動 minio:

      export MINIO_ACCESS_KEY=minioaccesskey
      export MINIO_SECRET_KEY=miniosecretkey
      ./minio gateway sia
      
    3. 用戶端機器在 ~/test-data 資料夾中有 100 個檔案,大小從 1 KB 到 10 GB 不等,總計不超過 4 TB。檔案包含巢狀資料夾,資料夾深度最多為 3 層。

    4. 用戶端機器成功執行下列指令:

      SERVER=insert.server.hostname # replace with actual server
      mc config host add minio-sia \
       "http://${SERVER}" minioaccesskey miniosecretkey S3v4
      
      mc mb minio-sia/sia-test-bucket
      
      # Upload test files.
      mc cp --recursive ~/test-data/* minio-sia/sia-test-bucket/
      
      # Download test files.
      mc cp --recursive \
       minio-sia/sia-test-bucket/* ~/test-data-downloaded/
      
    5. 下載檔案的 SHA-1 雜湊值與原始檔案的 SHA-1 雜湊值相符

  • 若在懸賞公告中發現含糊之處,應在整個競賽期間持續更新公告,並附上變更日誌說明修改內容。

  • 明確指出懸賞的 issue tracker 是獲獎要求的權威來源。

  • 懸賞參賽者無需滿足出現在官方懸賞追蹤器以外的要求。

懸賞是依概念驗證而非成功整合來支付

Nebulous 是在經 Sia 核心開發者審查後、但在獲得 Minio 維護者核准前就頒發了懸賞。懸賞的真正目標是整合進 Minio 的程式碼庫,否則使用者會不願意部署來自 @dvstate 未再維護的分支(fork)的程式碼。

Sia 很幸運,@dvstate 在責任結束後仍長期持續處理 PR,但懸賞真正目標的完成不應仰賴得獎者的善意。

在懸賞頒發前,存在爭取獎金的急迫感——被要求的修改都在數小時或數天內完成。頒發之後,延遲就增加到以週為單位。

這是可以預期且合理的,因為 @dvstate 是以志工、盡力而為的基礎在工作。Sia 能得到任何小於無限大的回應延遲,都算是幸運的了。

建議行動項目

  • 應以成功整合而非概念驗證作為懸賞支付依據。
  • 將成功合併至目標程式碼庫列為未來懸賞的明確要求。

Minio 整合重複了 siac 命令列用戶端的邏輯

Minio 整合程式碼中有 30-40% 只是用來實作 Sia API 的邏輯。這與 Sia 核心程式碼庫中已存在的程式碼重複,因為 siac 命令列用戶端已實作了相同的功能。

目前沒有任何語言的官方 Sia API 綁定,包含 Sia 原生語言 Go 在內也沒有。

建議行動項目

  • 為 Sia API 建立官方的 Go 用戶端函式庫。讓 siac 成為此函式庫的參考用戶端,並重構 Minio 整合以使用該函式庫。
  • 對於未來需要非 Go 程式碼的懸賞,要求投稿作品建立一個用於實作所需 Sia API 功能的函式庫。此函式庫應獨立於應用程式本身的程式碼。

Minio 整合的測試涵蓋率極低

僅有兩個極簡單的函式有測試涵蓋率,難以偵測對 Sia Minio 程式碼的變更是否會破壞 Minio 的功能。

建議行動項目

  • 將自動化測試列為未來 Sia 懸賞的要求。

審查期間的資訊孤島

關於 PR 所需變更的關鍵討論都是私下進行的。除了 @dvstate 或 @harshavardhana 之外,沒有人能追蹤進度或協助推動 PR。

建議行動項目

  • 應以成功整合而非概念驗證作為懸賞支付依據。
  • 要求討論在集中地點進行(例如懸賞的 GitHub issue),讓所有懸賞申請人都能取得相同資訊。

「先完成先得」的懸賞會造成扭曲的誘因

懸賞計畫的規則寫道:

每個懸賞僅會支付一次給一份投稿,除非另有說明,否則將支付給第一個符合懸賞所有條件的個人或團隊。

這會誘使懸賞投稿者將解決方案最佳化以最小化實作成本,進而降低了他們花時間提升可讀性、可維護性或撰寫清楚文件的意願。

以 Minio 整合為例,程式碼雖然有詳盡的文件,但缺乏測試,且將 Sia 邏輯與 Minio 邏輯混雜在一起,未來在維護上可能會帶來挑戰。

這個制度也會抑制協作或改進的動機。如果某位開發者已發布解決方案,其他開發者就沒有動力再嘗試,因為懸賞很可能會頒給第一位投稿者。規則也未涵蓋如何在他人投稿基礎上進行改進的途徑,因此沒有改進他人作品的機制。

建議行動項目

  • 採用無差別的「投稿窗口」
  • 指定一段投稿速度不影響結果的期間(例如,懸賞競賽前兩週內收到的所有投稿皆視為同等)。
  • 申請人可以提早投稿,但允許他人 fork 並改進其作品(必須是實質改進,而不只是重新命名一些符號)。在此情況下,懸賞由 Nebulous 斟酌分配給有貢獻的開發者。
  • 初始投稿窗口結束後,獎項頒給第一個有效的投稿。

第三方驗證的困難

Minio 團隊先前沒有使用 Sia 的經驗。在 Minio 安心合併 PR 之前,@dvstate 不得不自費建置一台測試伺服器,並與 Minio 維護者合作完成一系列先前未公布的手動驗證步驟。

建議行動項目

  • 對於未來涉及第三方整合的懸賞,懸賞主辦方應負責驗證解決方案,並與第三方夥伴合作協助他們進行驗證。
  • 為懸賞建立客觀的驗收測試。(參見「需求不明確」一節)。

本文章由 muse-spark-1.2-contributor 進行翻譯

留言