FR-172 · 機制問答

Agent 獨立更新問答

每題先給結論,再給事實與程式位置

整理 PM 與業務最常問的 16 題。版號、流程、程式路徑以主系統 1.28.3、Agent 1.5.5 為準;完整交付內容看 FINAL-SPEC.md。

16 題 主系統 1.28.3/Agent 1.5.5
§1

更新方式

Q1 主系統和 Agent 現在是分開更新嗎?

結論:是。兩個安裝包、兩條版本線、各自升級,互不需要對方先升。

主系統 Agent
安裝包 guidant-ai-<版>.tar.gz(約 3.5 GB) guidant-agent-compose-<版>.tar.gz(約 1.7 GB)
更新站版本線 主系統 Agent
目前版號 1.28.3 1.5.5

主系統包裡已經不帶 Agent。修 Agent 不必再出一包主系統、也不必停主系統。

Q2 有哪幾種方式可以更新 Agent?

結論:三種,最後都走同一條升級流程。

方式 在哪按 適合
主系統更新中心 Agent 區 勾選要更新的台,按「更新選取的 N 台到 X」 管理員一次更新多台
Agent 主控台「更新到 X」 每台 Agent 自己的主控台(8444) 在現場、只更新這一台
Agent 主控台「離線上傳更新包」 同上 Agent 連不到主系統時

前兩種實際上都是主系統去下載、驗證、推送;主控台那顆只是「請主系統替這一台做」。

Q3 一定要先按「預先下載」嗎?

結論:不用。直接勾選按更新即可,主系統會自己判斷要不要先下載。

  • 主系統手上沒有包、或手上的包比更新站查到的新版舊,就先下載(畫面有進度、可取消),下載完自動推。
  • 手上已經是最新就直接推。
  • 「預先下載」保留為選用:想先把包抓下來、晚點再推時才用。

下載途中又有人按更新(例如另一台的主控台),會併進同一份待推清單,不會把先按的人選的台蓋掉。

程式:app/product_update/service/agent_release_service.py(bundle_is_latest、newer_on_site)、product_update_app_service.py(agent_push)。

Q4 按下更新後,從頭到尾發生什麼事?

結論:主系統下載並驗證包 → 直接推指令給 Agent → Agent 跟主系統拿包、寫升級單 → Agent 所在主機跑升級步驟 → 每一步即時回報主系統。

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
  autonumber
  participant P as 管理員
  participant M as 主系統
  participant U as 更新站
  participant A as Agent
  participant H as Agent 主機
  P->>M: 更新選取的台到 X
  opt 手上不是最新
    M->>U: 下載 Agent X 並驗章
  end
  M->>A: 推送更新指令(版號、雜湊、大小)
  Note over A: 進入維護模式,停收新工作
  A->>M: 下載包、核對雜湊
  A->>H: 寫升級單
  H->>H: 驗新版簽章 → 換版 → 健康檢查
  A-->>M: 每一步、結果、升級紀錄
  M-->>P: 畫面顯示每台進度
圖 1 — 從按下更新到 Agent 換好版本。

完整版時序圖(含端點名稱)看 FINAL-SPEC §2;每一步跑哪支程式看 upgrade-flow-guide.md。

Q5 Agent 怎麼收到更新指令?還有用心跳嗎?

結論:主系統直接連到 Agent 推指令,不靠心跳。心跳只代表「Agent 活著」,不帶任何指令或資料。

  • 主系統連 Agent 的 8443 埠,雙向憑證加上 60 秒有效、綁定這個動作的 JWT,呼叫 POST /update。
  • Agent 那時剛好離線,等它下次心跳回來,主系統會補推一次。
  • 進度與結果是 Agent 主動送事件給主系統(/agents/events),不是主系統去問。

程式:主系統 core/plugins/_agent_commands.py(push_update_soon);Agent guidant_agent/sync/api/cmd_update.py、sync/app/update_sync.py。通道設計見 FR-171。


§2

升級期間

Q6 Agent 升級時還能用嗎?

結論:不能,會進入維護模式。從收到更新指令那一刻起就停收新的掃描工作,進行中的工作先做完再換版,完成後自動恢復。

階段 算升級中
下載主系統推來的包 是
等進行中的工作做完 是
升級單已寫好、主機在換版 是

換版完成後主控台不必重新登入(登入狀態存在磁碟上,換容器不會掉)。

Q7 Agent 主控台什麼時候會鎖畫面?

結論:Agent 回報「升級中」時就整頁鎖住,只顯示進度。不管是誰發動的都一樣。

  • 在主控台自己按更新:按下的當下就鎖。
  • 由主系統發動:開著的主控台最慢 30 秒內鎖住(主控台平常每 30 秒問一次狀態);鎖住後每 3 秒更新一次進度。
  • 主控台沒開著:之後打開或重新整理,第一次問就會鎖。
  • 結束後:版本換了就整頁重新載入、回到按更新前所在的那一頁;失敗退回舊版就解鎖顯示結果。

這 30 秒內 Agent 已經停收新工作,使用者頂多看到畫面還能點,但送出的掃描會被拒絕。要做到「一收到就鎖」得讓 Agent 主動推給瀏覽器,目前裁示先不做。

程式:FE console/useUpdateStatus.js(輪詢與鎖定)、console/update.js(lockState)、console/components/UpdateLockMask.vue。

Q8 主系統自己升級時,使用者會看到什麼?

結論:按「更新到 X」的人看到全頁遮罩加進度;其他人在停機那幾步看到維護頁。

  • 下載與驗證期間系統照常可用。
  • 主機開始跑升級後,「等工作做完」到「換成新版」這幾步前門顯示維護頁。190 實測整次 6 分 42 秒,維護頁約 4.5 分鐘(資料量不同時間會不同,所以畫面不寫分鐘數)。
  • 任一步失敗會自動退回原版。

Q9 升級失敗會怎樣?看得到原因嗎?

結論:會自動退回原版;失敗原因分兩層,畫面看得到摘要,也能下載完整紀錄。

  • 畫面:失敗那一步標紅,「看原因」顯示該步錯誤輸出的最後 20 行。
  • 完整紀錄:Agent 會把整次升級的主機紀錄上傳主系統,更新紀錄頁按「下載升級紀錄」取得;主系統自己的升級成功或失敗也都能下載。
  • 每一步的結果與耗時寫進系統日誌。

§3

Agent 不連外網

Q10 Agent 不能連外網,包從哪裡來?

結論:一律經過主系統。主系統向更新站下載、驗證,再交給 Agent;Agent 從不直接連更新站。

主控台的「立即檢查」也是請主系統當下去更新站查,主系統再告訴 Agent 有沒有新版(全機 5 分鐘內只查一次)。主系統斷線時,主控台只提供離線上傳。

Q11 怎麼確定包沒有被改過?

結論:每一手都驗。驗章只認本機已經裝好的公鑰,不拿包裡附的公鑰驗自己。

誰驗 驗什麼
主系統下載後 發布清單的章(Agent 專用章型別)、整包雜湊
Agent 從主系統拿包 大小與雜湊(數字來自主系統驗過的清單)
Agent 主機升級前 用舊版 Agent 驗新版程式樹的完整性章
離線上傳 用現行版的公鑰驗章、雜湊、版本、磁碟

§4

維運與成本

Q12 更新包會一直佔空間嗎?

結論:不會,用完就清。

  • 主系統的 Agent 包:整批推送全部成功後,清掉用不到的舊包。
  • 主系統自己的升級包:升級成功後 incoming/ 只留清單(之後要重試會重新下載)。
  • 升級過程的暫存(解開的包、舊映像、舊資料庫快照)在最後一步「清理」處理。

Q13 主系統和 Agent 版本不相容怎麼辦?

結論:只擋一種情況——Agent 新版要求的主系統版本比現在的主系統新,按鈕會反灰並說明要先升主系統。

  • Agent 比主系統新是允許的。
  • 主系統新版要求 Agent 至少某版時,畫面標「建議更新」,不擋主系統升級。

Q14 同版重套是什麼?正式環境會出現嗎?

結論:測試機專用,把目前這一版照正式升級流程重跑一次。正式環境不會出現,因為按鈕要靠兩個環境變數才會打開,任何出貨範本都不帶這兩個鍵。

  • 主系統:PRODUCT_UPDATE_ALLOW_SAME_VERSION=1;Agent:AGENT_UPDATE_ALLOW_SAME_VERSION=1。
  • 降版、跨主版號不論開關一律擋。
  • 用途:測試機升到最新版之後,要再看一次升級畫面,不必為此再出一版。
  • 目前只開在 190。

Q15 出一版要多久?做了哪些加速?

結論:主系統完整出包約 51 分鐘、Agent 約 16 分鐘(測試包)。編譯只佔不到四成,大部分時間在打包壓縮與安全掃描。

段落 時間(主系統+Agent)
Nuitka 編譯 約 19.5 分
打包壓縮 約 13 分
SBOM+弱點掃描 約 9 分
建映像、smoke、其他 約 10 分

已做的加速:

  • 測試包略過 SBOM 與弱點掃描(正式包照掃):Agent 19 分 30 秒 → 15 分 52 秒,主系統約省 5 分。
  • 主系統封包改多核心壓縮:預估省約 4 分。
  • 版本固定的第三方映像(postgres、redis、seaweedfs、bugsink、證據分類)匯出一次就快取:每版不再重匯約 3 GB。
  • 只改一邊時只出那一邊。

Nuitka 在 build 機本來就沒開 LTO,--lto=no 不會更快。出版自動化(CI、Vault 簽章)在 FR-173。


§5

交付狀態

Q16 現在可以給客戶了嗎?

結論:功能已在 190 實測通過,但還沒出正式版。目前更新站上的都是測試章簽的內部測試包;第一個正式版是 1.29,用 FR-173 的自架 Vault 簽章。

機器 主系統 Agent
190 測試機 1.28.3 1.5.5
189 POC 1.27.x 1.4.x

189 升到 1.28.x 時,Agent 要手動升一次:1.4.x 的 Agent 沒有新的推送端點,主系統推不動它。之後就都能從主系統更新。