OTA 更新

無線更新 (OTA) 是一種作業系統更新機制 紫紅色。本文件將詳細說明 OTA 更新機制在 Fuchsia 上的運作方式。

更新程序分為以下幾個階段:

正在檢查更新

作業系統更新程序的兩個進入點是 omaha-clientsystem-update-checker 元件

omaha-clientsystem-update-checker 都放送相同廣告 來確認是否有作業系統更新,並開始更新。

一般來說,產品應使用 omaha-client 才能 並使用 Omaha 來判斷更新的可用性。產品應使用 如果不想使用 Omaha,請system-update-checker 直接從套件存放區檢查更新。

在任何指定的 Fuchsia 系統上,只能執行下列其中一項元件:

更新 omaha-client 檢查流程

在啟動程序中,omaha-client 會啟動並開始定期更新 檢查。進行這些檢查時,omaha-client 會輪詢 Omaha 伺服器進行檢查 更新。

使用 Omaha 的好處如下:

  • 可在多個階段中分批推出系統更新 Fuchsia 裝置。舉例來說,您可以設定為 裝置機群都會更新換言之,這類裝置中只有 10%。 會在輪詢 Omaha 時看到可用的更新。 剩餘的 90% 裝置都沒有可用的更新。
  • 這種方式有多種更新管道。舉例來說,測試裝置 並取得最新版本 (可能不穩定) 軟體這可讓正式版裝置從正式版中取得更新 並取得最穩定的軟體頻道資訊可以 視需要一併提供產品和版本給 Omaha。

圖:使用 omaha-client 檢查更新

圖 1. 簡化版更新檢查程序,使用 omaha-client。另有 用於限制「omaha-client」可否檢查更新或套用更新的政策。

omaha-client 從 Omaha 伺服器取得更新套件網址後,omaha-client 會指示 system-updater 開始更新。

使用 system-update-checker 更新檢查

非使用 omaha-client 的裝置會採用 system-update-checker。視情況而定 的設定方式,system-update-checker 會定期輪詢 更新套件如果沒有 auto_update,這些檢查會預設為停用 。

如要檢查是否有可用的更新,system-update-checker 會檢查 下列情況:

  • 目前執行中系統映像檔 (位於 /pkgfs/system/meta) 的雜湊與 更新套件中系統映像檔的雜湊值 (位於 packages.json 中)?
  • 如果系統映像檔並非不同,表示系統目前執行的 vbmeta 不同 是否與更新套件的 vbmeta 不同?
  • 如果沒有 vbmeta,表示目前在系統上執行的 ZBI 和 ZBI 不同 更新套件?

如果上述任一答案皆為「是」,則 system-update-checker 知道 update 套件已變更。System-update-checker 偵測到更新後 套件已變更,system-update-checker 會觸發 system-updater 使用預設更新套件 (fuchsia-pkg://fuchsia.com/update) 來開始更新。

圖:使用 system-update-checker 檢查更新

圖 2. 使用 system-update-checker 的簡化版更新檢查程序。

如果不需要更新,更新檢查工具會儲存上次已知的 並更新在伺服器上看到的套件後續檢查更新時 系統會根據上次檢查的更新套件,檢查擷取的更新套件 伺服器上已知的雜湊值如果最新更新套件的雜湊值 更新檢查工具會比對 vbmeta 和 更新中相關映像檔的 ZBI 套件。如果 vbmeta 或 ZBI 在 並安裝更新套件後,檢查工具就會開始系統更新。

監控

如果客戶想監控更新進度和狀態,可以 fuchsia.update.AttemptsMonitor 通訊協定和用戶端 fuchsia.update.Manager FIDL 的 MonitorAllUpdateChecks() 方法 因此效能相當卓越fuchsia.update.AttemptsMonitor 執行個體只會接收 訊息。這個 不會觸發新的更新

fuchsia.update.AttemptsMonitor 執行個體會收到 OnStart 訊息 來包含伺服器端的 fuchsia.update.Monitor 通訊協定。這樣一來, 用戶端接收及處理 OnState 訊息,告知更新狀態變更。

另一種做法是實作 fuchsia.update.Monitor 並提供用戶端 變更為 fuchsia.update.Manager 通訊協定的 CheckNow() 方法。這將 開始檢查更新。它只會監控 並在更新完成後關閉控點。

暫存更新

無論更新是否由 omaha-clientsystem-update-checker 觸發, 或甚至強制更新檢查時,必須將更新寫入磁碟。

更新程序分為下列步驟:

圖:起始狀態圖

圖 3. 裝置目前正在執行假設的 OS 版本 1 (位於插槽 A),並且開始執行 更新至假設 OS 第 2 版 (至插槽 B)。警告:這可能與磁碟不同 各行各業

擷取更新套件

system-updater 會使用 提供的更新套件網址。接著,動態索引會更新為 參照新的更新套件更新套件範例如下所示:

/board
/epoch.json
/firmware
/fuchsia.vbmeta
/packages.json
/recovery.vbmeta
/version
/zbi.signed
/zedboot.signed
/meta/contents
/meta/package

如果因空間不足而擷取失敗,system-updater 會觸發垃圾 「集合」來刪除未在靜態或動態索引中參照的所有 BLOB,或是 保留套件組合垃圾收集後,system-updater 會重試擷取。如果 重試失敗,system-updater替換 僅含有其嘗試擷取的更新套件 (如果更新套件網址) 設定的套件 包含雜湊,否則系統會清除 保留套件集),然後再次觸發垃圾收集作業,並重試更新套件 擷取。

圖:擷取更新套件

圖 4. system-updater 會指示 pkg-resolver 解析版本 2 update 套件。我們假設 system-updater 無法擷取更新套件,原因如下: 空間不足,觸發垃圾收集以收回運算單元 B 參照的第 0 版 blob。 然後重試以成功擷取第 2 版的更新套件。

如有需要,更新套件可能包含 update-mode 檔案。這個檔案 判斷系統更新是發生在一般復原還是 ForceRecovery 程序中 模式。如果找不到更新模式檔案,system-updater 會預設為一般模式

模式為 ForceRecovery 時,system-updater 會將映像檔寫入復原。 將運算單元 A 和 B 標示為無法啟動,然後啟動復原作業。如需更多資訊 請參閱 ForceRecovery 的實作

確認董事會相符

目前執行系統中的 Jamboard 檔案位於 /config/build-info/boardsystem-updater 會驗證系統上的主面板檔案是否與面板相符 該檔案位於更新套件中

圖:確認董事會相符

圖 5system-updater 會驗證更新套件中的 Jamboard 與主機板相符 版位 A。

確認是否支援 Epoch

update 套件含有 Epoch 檔案 (epoch.json)。如果更新週期 套件 (目標週期) 小於 system-updater 的週期 (來源週期),OTA 會失敗。如需其他相關資訊 請參閱 RFC-0071

圖:確認支援週期

圖 6. system-updater 會驗證下列執行個體是否支援更新套件中的 Epoch: 並與目前 OS 的週期進行比較

取代保留的套件組合

以目前更新套件替換保留的套件設定 以及之後在 OTA 程序中擷取的所有套件。

保留的套件集是一組受到垃圾收集 ( 靜態和動態索引中的套件)。可用來防止垃圾流量 收集不會刪除目前更新程序所需的 BLOB。舉個例子,假設 擷取更新作業所需的部分套件,隨後因不相關原因而重新啟動。時間 裝置會再次啟動 OTA,重新啟動前仍需要擷取到的套件, 套件不受動態索引保護 (就像已保留的套件集一樣) 時)。將這些套件新增至保留的套件組合後,system-updater 就可以 觸發垃圾收集 (例如移除舊版系統版本所使用的 blob) 而不復原 過去的工作

觸發垃圾收集作業

已觸發垃圾收集,刪除了舊系統獨有的所有 BLOB。 這個步驟可以釋出額外空間,供任何新的套裝方案使用。

圖:垃圾收集

圖 7. system-updater 會指示 pkg-cache 垃圾收集專屬 BLOB , 以及舊系統在這個範例中,這代表 pkg-cache 只會剔除 BLOB 參照的 BLOB 第 1 版更新套件

擷取其餘套件

system-updater 會剖析更新套件中的 packages.json 檔案。 packages.json 如下所示:

{
  "version": 1,
  "content": [
    "fuchsia-pkg://fuchsia.com/sshd-host/0?hash=123..abc",
    "fuchsia-pkg://fuchsia.com/system-image/0?hash=456..def"
    ...
  ]
}

system-updater 會指示 pkg-resolver 解析所有套件網址。解決方式 套件管理系統只會擷取更新所需的 BLOB,即 也就是尚未出現的 BLOB。套件管理系統會擷取整個 BLOB 而不是目前系統上任何元件的差異

擷取完所有套件後,會觸發 BlobFS 同步處理作業來清除 從 BLOB 轉換為永久儲存空間。此程序可確保所有必要的 BLOB ,更新就在 BlobFS。

圖:擷取其餘套件

圖 8. system-updater 會指示 pkg-Resolver 解析版本 2 packages.json 中參照的套件。

寫入圖片即可封鎖裝置

system-updater 決定要將哪些圖片寫入區塊 裝置。映像檔、資產和韌體有兩種。

接著,system-updater 會指示分區映像檔安裝工具編寫系統啟動載入程式,並 韌體。這些圖片的最終位置不會因 裝置支援 ABR ,直接在 Google Cloud 控制台實際操作。為了避免閃光燈 只有在映像檔不同於 封鎖裝置上現有的映像檔。

接著,system-updater 會指示分區映像檔安裝工具編寫 Fuchsia ZBI 及其其 vbmeta。這些圖片的最終位置取決於裝置是否 支持 ABR ,直接在 Google Cloud 控制台實際操作。如果裝置支援 ABR ,分區映像檔安裝工具寫出 Fuchsia ZBI, 將 vbmeta 與目前未啟動的插槽 (替代運算單元) 相同。 否則,分區映像檔安裝工具會將資料寫入 A 和 B 分區 (假設為 B 分區已存在)。

最後,system-updater 會指示分區映像檔安裝工具寫入復原作業 ZBI 及其 vbmeta。如同系統啟動載入程式和韌體, 位置不會取決於裝置是否支援 ABR ,直接在 Google Cloud 控制台實際操作。

圖:撰寫要封鎖裝置的圖片

圖 9. system-updater 會透過分區映像檔安裝工具將第 2 版映像檔寫入插槽 B。

將替代分區設為有效

如果裝置支援 ABR,system-updater 會使用分區映像檔安裝工具設定 同時啟用替代分區功能如此一來,裝置就會開機 都會在下次啟動

參照運算單元狀態的方法有很多種。例如,內部 分區映像檔安裝工具使用 SuccessfulFIDL 服務會使用 Healthy,而其他 案例可以使用主動、閒置、可開機、無法啟動、目前、替代等...

重要的中繼資料是為每個核心儲存的 3 項資訊 。這項資訊有助於判斷每個核心運算單元的狀態。適用對象 例如,在版位 B 標示為有效前,中繼資料可能如下所示:

中繼資料 插槽 A 插槽 B
優先順序 15 0
剩餘行程數 0 0
健康* 1 0

將版位 B 標示為有效後,中繼資料看起來會像這樣:

中繼資料 插槽 A 插槽 B
優先順序 14 15**
剩餘行程數 0 7**
健康料理 1 0

如果裝置不支援 ABR,由於沒有替代分區,因此系統會略過這項檢查。 如果有一項更新,系統會寫入一個使用中的分區。

圖:將替代分區設為有效

圖 10. system-updater 會將插槽 B 設為使用中,以便裝置啟動到插槽 B 下次啟動時 這個功能會相當實用

重新啟動

視更新設定而定,裝置不一定會重新啟動。裝置之後 裝置就會開機,並移至新的插槽。

圖:重新啟動

圖 11. 裝置會重新啟動進入插槽 B,並開始執行版本 2。

驗證更新

驗證更新後,系統會提交更新。

系統會按照以下方式驗證更新:

正在重新啟動,以進入更新版本

下次啟動時,系統啟動載入程式需要決定要開機的運算單元。 在此範例中,系統啟動載入程式決定啟動位置 B, 版位 B 的優先順序較高,剩餘嘗試次數超過 0 次 (請參閱 將替代分區設為有效)。接著, 系統啟動載入程式會驗證 B 的 ZBI 與 B 的 vbmeta 相符,最後啟動 插槽 B。

早期啟動後,fshost 會使用新的系統映像檔套件啟動 pkgfs。 這是 packages.json 中參照的系統映像檔套件 同時執行更新作業system-image 套件含有 static_packages 檔案 裡面會列出新系統的基本套件。例如:

pkg-resolver/0 = new-version-hash-pkg-resolver
foo/0 = new-version-hash-foo
bar/0 = new-version-hash-bar
...
// Note the system-image package is not referenced in static_packages
// because it's impossible for it to refer to its own hash.

pkgfs 接著,將這些套件載入為基本套件。套件會顯示在 /pkgfs/{packages, versions},表示已安裝套件 已啟用或已啟動然後啟動 pkg-resolverpkg-cachenetstack等...

提交更新

system-update-committer 元件會執行多項檢查,確認 已成功更新例如,它會指示 BlobF 讀取 1 MiB 的資料。如果系統在啟動時已承諾執行,這些檢查就會 略過。如果檢查失敗,並且視系統的設定方式而定, system-update-committer 可能會觸發重新啟動作業。

更新驗證完畢後,目前的分區 (版位 B) 會標示為 Healthy。請參考 將替代分區設為有效 (啟動) 中繼資料現在看起來可能像這樣:

中繼資料 插槽 A 插槽 B
優先順序 14 15
剩餘行程數 7 0
健康料理 0 1

接著,替代分區 (運算單元 A) 會標示為無法啟動。現在, 開機中繼資料可能如下所示:

中繼資料 插槽 A 插槽 B
優先順序 0 15
剩餘行程數 0 0
健康料理 0 1

之後,系統會將更新視為已確認。因此:

  • 系統一律會啟動至插槽 B,直到下一次系統更新為止。
  • 系統將啟動到插槽 A,直到下一次系統更新 覆寫運算單元 A。
  • 運算單元 A 參照的 BLOB 現在可以進行垃圾收集作業。
  • 現已允許後續的系統更新。更新檢查工具之後 如果發現新的更新,整個更新程序就會重新啟動。