iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
IT Operation

地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理系列 第 25 篇

Day 25|資產生命週期與授權 EOL 監看:到期日只是一個數字,通通收進 Prometheus 時間序列!

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20261009/201418168xKHHWaHki.png

稽核會議上才驚覺沒人知道的事,其實早就寫在設備裡

Day 24 在 FortiGate 上掛網頁過濾時,第一筆日誌就是 eventtype="ftgd_err",Web Filtering 的授權早就過期了,當時沒有人說得出是哪一天。同一天改 viewer 的 Dockerfile,發現建置映像用的 Node 20 在 2026 年 4 月就停止支援,CI 其實一直跑在 22 上。這兩件事都不是故障,監控不會跳提醒,日誌不會寫,卻都是稽核會問的「你們的資產有沒有在支援期內」。

今天直接來問防火牆本人,這一台的答案是 2025 年 9 月 20 日,而且不只 Web Filtering。60F 回報 20 項 FortiGuard 服務同一天到期,防毒、IPS、應用程式控制、韌體更新都在裡面,FortiCare 那一欄沒有任何支援合約。一張合約過期,二十項功能一起停,過了一年才在別的工作裡仔細彙整出來。

這個場域有十幾樣東西各自有一個會到期的日子。防火牆的韌體與授權、兩台 FortiAP、兩台 Spark 的 DGX OS、兩台 PVE 的 Proxmox VE 與底下的 Debian、QDevice 那台小 VM、收集端 VM、NAS 的 QuTS hero,還有 viewer 的建置環境。它們的日期分散在六個廠商的網頁上,格式各異,而且會動。今天把這些日子整合成一張表,寫成 Day 19 那條管線裡的一個指標,到期前 90 天跳提醒一次、30 天再跳提醒一次、過了就一直提醒。程式碼在 onprem-metrics v0.3.0 的 eol/ 與 textfile/eol-textfile.py。

先說結論裡最不好看的一筆。Day 15 給 QDevice 裝的那台 VM 是 Debian 12,一般安全支援在 2026 年 7 月 11 日已經結束,LTS 團隊接手到 2028 年 6 月。那台 VM 在 Day 15 收尾時已經只收金鑰,不必登入也看得出來,SSH 的版本字串是 OpenSSH_9.2p1 Debian-2+deb12u10,deb12 就是 bookworm 的套件。清單一建好,AssetEolPassed 留到最後的就是它,結果直接過期 90 天。XD

一、清單:一列一個日子,每一列寫依據

eol/assets.tsv 一列一個(資產、元件、里程碑)。選 TSV 的理由是 Day 26 要用的那個,改一個日期是一行 diff,commit 訊息寫出處,不用再裝 YAML 的程式庫。欄位有十個,關鍵的是三個。

欄位 值 為什麼需要
milestone end_of_support、end_of_engineering、security_support_end、lts_end、end_of_order、expires 廠商的「結束」不只一種。FortiOS 的 End of Engineering Support 之後只修嚴重問題與 PSIRT,End of Support 才是真的沒人管。Debian 的一般安全支援結束後還有 LTS 兩年。一個資產可以有兩列
basis vendor、estimate、licence、unknown 日期是廠商公布的、推算的、裝置上即時讀的,還是根本沒人公布。推算的要在 note 寫推法
date YYYY-MM-DD 或 ? 不知道就寫 ?。它不會消失,會變成 asset_eol_unknown,在儀表板上是一個數字

這一版 20 列,13 列有日期,6 列是 ?,1 列是授權的占位。來源逐列列在 eol/README.md,讀取日 2026-10-09,幾個值得探究的點如下。

資產 讀到的 來源 怎麼處理
FortiOS 7.6 EOES 2028-07-25,EOS 2030-01-25 endoflife.date,Fortinet CSB-260330-1 Fortinet 在 2026 年 3 月把 7.4 與 7.6 各延一年,原本是 2027-07-25 與 2029-01-25。日期的變動是第三節要處理的事
FortiGate 60F 硬體 沒有公告 Fortinet 支援入口的 Product Life Cycle(要登入) 截至 2026 年 10 月,60F 還沒有 End of Order。Fortinet 會至少提前 90 天公告,硬體支援到 End of Order 後 60 個月,所以最早也是 2031 年。?,unknown
FortiGuard 授權 裝置即時讀 GET /api/v2/monitor/license/status 第二節
FortiAP 221E End of Order 2025-12-30,End of Support 2030-12-30 第三方追蹤站轉引 Fortinet 的生命週期紀錄 兩台。停售對已經在用的設備只影響加購,清單看 End of Support,End of Order 與最後一次延長服務(2029-12-30)寫在 note。官方頁面要登入,查到再核對
DGX OS 7 沒有終止日 NVIDIA 的 Release Notes 兩台都是 7.6.0,2026-09-14 出的最新版,也是升到 DGX OS 8 的必經版本。NVIDIA 沒公布 7 的終止日,? 一列,底層 Ubuntu 24.04 的 2029-05-31 當下限,另一列 estimate。要不要升 8 是 Day 26 的變更
Proxmox VE 9 沒有終止日 endoflife.date 兩台是 9.2,底下 Debian 13.7。Proxmox 說「至少與對應的 Debian 一樣長」,PVE 8 在 2026-08-31 結束,與 Debian 12 差一個多月。PVE 9 用 Debian 13 的 2028-08-09 當推算值,estimate。eol_ref 指向 endoflife.date 的 proxmox-ve/9,那裡現在也沒有日期,Proxmox 一公布,比對就會變成不一致
Debian 12(QDevice) 安全支援 2026-07-11,LTS 2028-06-30 endoflife.date 已過。前言說的那一筆
Ubuntu 24.04(收集端) 標準支援 2029-05-31 endoflife.date 收集端 VM 是 24.04.5 LTS。ESM 到 2034 年要 Pro 訂閱
QuTS hero、TS-464 支援中,終止日未定 QNAP 產品支援狀態頁 QNAP 以機型公布支援狀態,QuTS hero 沒有逐版的日期。兩台 NAS 都是 QuTS hero 6.0.2,另一台的硬體不放進公開清單。endoflife.date 沒有 QNAP 的產品,第三方的 endoflife.ai 列 TS-464 為支援中。?
Node.js 22 2027-04-30 endoflife.date viewer 的建置映像。Node 20 的 2026-04-30 就是 Day 24 踩到的

![eol/assets.tsv 的 20 列與 git log]https://ithelp.ithome.com.tw/upload/images/20261009/20141816pQaW7291Li.png

二、授權:裝置上讀,不手抄

FortiGuard 的授權到期日不該抄進 TSV,它會隨續約改,而且防火牆自己知道。eol-textfile.py --fortigate 用 Day 22 的 REST 做法,一個唯讀的 API 使用者,trusted host 只有收集端,讀 /api/v2/monitor/license/status。回傳的 JSON 裡每一個帶數字 expires 的物件都是一個授權,不管它在哪一層,鍵的路徑就是元件名稱,新的授權種類出現時不用改程式。

60F(FortiOS 7.6.7 build 3704)的回應有 49 個頂層鍵,帶 expires 的有 22 個,實際寫出 20 個:

asset_eol_timestamp_seconds{asset="fgt-edge",component="web_filtering",kind="licence",version="-",milestone="expires",basis="licence"} 1758326400
asset_licence_status{asset="fgt-edge",component="web_filtering",status="expired"} 1

1758326400 是 2025-09-20。20 項全是 expired、全是同一天:antivirus、ips、appctrl、web_filtering、firmware_updates、botnet_domain、malicious_urls、outbreak_prevention、iot_detection 等等。少掉的兩個是規則刻意跳過的。forticloud_sandbox 的狀態是 free_license,免費額度帶著合約的日期,但不會因此停用。iot_detection.definitions 是 iot_detection 底下的特徵碼物件,日期與父層相同,算一次就好。

韌體更新那一項值得多看一眼。FortiOS 7.6 的 End of Support 在 2030 年。授權過期之後,要從支援入口下載新版韌體就得先續約,兩件事要分開看,這也是為什麼授權要跟作業系統放在同一張表。

repo 裡原本的 tests/fixtures/eol/fortigate-license-status.json 是照文件寫的,只有 7 個頂層鍵,forticare.support 底下有 hardware 與 enhanced 兩份合約。實機的 forticare.support 是空物件,這台沒有任何 FortiCare 支援合約,fixture 假設的路徑根本不存在。fixture 已換成這次的實機回應,序號、WAN 位址、註冊公司名遮掉。

FortiGate 這邊要做的只有一件事,建唯讀使用者,寫進系統變更單:

config system accprofile
    edit "eol-reader"
        set sysgrp custom
        config sysgrp-permission
            set upd read
        end
    next
end
config system api-user
    edit "eol-reader"
        set accprofile "eol-reader"
        set vdom "root"
        config trusthost
            edit 1
                set ipv4-trusthost 192.168.2.49 255.255.255.255
            next
        end
    next
end
execute api-user generate-key eol-reader

7.6.7 的 accprofile 欄位名稱就是這些,所有權限群組預設都是 none。第一版用 set sysgrp read,讀得到授權,但從收集端試了幾個端點,它也讀得到防火牆的 4 條政策與系統全域設定,fwgrp 明明是 none。改成 custom 只開 upd(FortiGuard 更新與授權)之後,授權照讀,政策、全域設定、管理員清單都回 403,寫入回 403,從收集端以外的位址連線回 401。

金鑰放收集端的 /etc/onprem-metrics/fgt.token,metrics 唯讀,0600。還有一個小地方,這台的管理介面在另一個連接埠,--fortigate 要寫 https://ip:8443,少了埠號,443 那邊沒有東西在聽,連線會一直等到逾時。

三、到期日其實會變動,找 endoflife.date 當第二個眼睛

Fortinet 把 FortiOS 7.6 的日期延了一年,如果 TSV 裡抄的是舊的,告警會早一年跳出提示,然後有人去查,發現不用急,下次就不信它了。反過來更糟,廠商把日期提前,TSV 沒跟上。

因此決定用這個服務,它具備社群回報與收集來的EOL 資訊。--refresh 讀 endoflife.date 的 v1 API,每個產品一個 JSON,快取一天。TSV 的 eol_ref 欄寫 fortios/7.6、debian/13 這種「產品/版本」,腳本依里程碑對應欄位,比對 TSV 的日期。相同寫 asset_eol_source_mismatch 0,不同寫 1 並在 log 留一行「TSV 2030-01-25,endoflife.date 2031-01-25」。它不改 TSV。人去看兩邊,改日期與 note,commit 訊息寫為什麼,日期的變動就跟其他變更一樣留下軌跡。

真的 API 回應鍵名與文件相同,result.releases[] 裡有 eoasFrom、eolFrom、eoesFrom、isMaintained。差在語意。這三個欄位是「積極支援結束」「生命週期結束」「延伸支援結束」,在不同產品代表不同的事:

產品 eoasFrom eolFrom eoesFrom
Debian 12 2026-07-11,一般安全支援結束 2028-06-30,LTS 結束 2033-06-30,ELTS 結束
Ubuntu 24.04 2029-05-31 2029-05-31 2034-04-25,ESM
FortiOS 7.6 2028-07-25,End of Engineering Support 2030-01-25,End of Support 無

原版的對應是 security_support_end 對 eolFrom、lts_end 對 eoesFrom,fixture 也照同一個假設寫,本機測試當然全過。拿原版程式與原版清單對真的 API 回應跑一次,結果是這樣:

eol-textfile: pve1 Proxmox VE end_of_support: TSV 2028-08-09, endoflife.date 2030-06-30 (debian/13.eolFrom)
eol-textfile: pve1 Debian (PVE base) security_support_end: TSV 2028-08-09, endoflife.date 2030-06-30 (debian/13.eolFrom)
eol-textfile: pve2 Proxmox VE end_of_support: TSV 2028-08-09, endoflife.date 2030-06-30 (debian/13.eolFrom)
eol-textfile: pve2 Debian (PVE base) security_support_end: TSV 2028-08-09, endoflife.date 2030-06-30 (debian/13.eolFrom)
eol-textfile: qdevice Debian security_support_end: TSV 2026-07-11, endoflife.date 2028-06-30 (debian/12.eolFrom)
eol-textfile: qdevice Debian lts_end: TSV 2028-06-30, endoflife.date 2033-06-30 (debian/12.eoesFrom)

6 列不一致,6 列都是 TSV 對、程式錯。這正是「第二個眼睛」最怕的情形,它天天說有 6 件事要查,查了都不用改,一個月後就沒人看那個數字了。改成 security_support_end 對 eoasFrom、lts_end 對 eolFrom、extended_support_end 對 eoesFrom 之後,Ubuntu 兩欄同值不受影響,FortiOS 沒用到這兩個里程碑,收集端上的結果:

$ grep '^asset_eol_source_mismatch' /var/lib/node_exporter/textfile/eol.prom | awk '{print $NF}' | sort | uniq -c
     10 0

13 列有日期的裡面比對了 10 列,全部一致。沒比對的 3 列,FortiAP 不在 endoflife.date 上,兩列 Proxmox VE 指向的 proxmox-ve/9 還沒有日期,等它有了就會比。fixture 已換成這次的真回應,假設不會再跟程式一起錯。

endoflife.date 是社群維護的彙整,日期來自各廠商的公告,拿它當第二個眼睛,不當唯一來源。

四、從日期到告警

eol-textfile.py 每天 07:35 跑一次,寫 eol.prom,走 Day 19 的 textfile。一天一次就夠,日期不會在一天內變兩次,而且 endoflife.date 的 API 要求的也是這個頻率。

eol.yml 八條:

規則 門檻 為什麼
AssetEolWithin90Days 剩 90 天以內,warning 90 天是這個場域一個採購週期,報價、Day 26 的變更單、維護窗,再留一點給廠商
AssetEolWithin30Days 剩 30 天以內,critical 這時還沒動,就是要在到期後動了
AssetEolPassed 已過,critical 過了安全支援的發行版、過了支援期的硬體都是稽核發現。它會一直響,直到升級、換掉,或在 note 寫明接受風險並把那一列改成看下一個里程碑
AssetLicenceExpired 有授權已過期,每台一條,critical 授權跟著合約一起到期。20 項同一天過期,是一件事,不是 20 件
AssetLicenceExpiring 有授權剩 90 天以內,每台一條,warning 同上,續約是一張採購單
AssetEolUnknown 日期是 ?,info 不叫人,進每日彙整。清單上有幾件事還沒查,儀表板上是一個數字
AssetEolSourceMismatch endoflife.date 與 TSV 不同,info 第三節
EolTextfileStale 兩天沒跑,warning Day 19 的靜默失效規則,同一個形狀。Alertmanager 加了 inhibit,它響的時候不再對 Asset(Eol|Licence).* 告警

前三條排除 kind="licence",授權只走自己那兩條。原本的設計是每項授權一條,在這台 60F 上就是同時 20 個 critical,每條說的都是「2025-09-20 那張合約過期了」。儀表板照樣逐項列,告警只說一次,附上項目數。

第一次載入時 AssetEolPassed 其實是兩筆,另一筆是 FortiAP 221E 的 End of Order,「283 天前」。停售對已經裝在牆上的兩台不是問題,這正是清單規則寫的那種情況,把那一列改成看 End of Support,End of Order 寫進 note,commit 訊息寫為什麼。告警逼人做的就是這種決定,而且決定留在 git log 裡。

promtool test rules 的案例讓一個資產從剩 91 天走到過期 3 天,91 天不響,90 天 warning,30 天 warning 與 critical 同時在,過期後兩條「以內」安靜、AssetEolPassed 說「3 天前」。授權的案例放兩項過期、一項剩 91 天:AssetEolPassed 不響,AssetLicenceExpired 說「2 licences expired」,再過兩天剩 89 天時 AssetLicenceExpiring 才響。promtool 的時鐘從 1970 年開始,fixture 的日期是相對的。

AssetEolPassed 的訊息裡「幾天前」是在 PromQL 裡算的,不在範本裡。範本沒有 time(),第一版寫在範本裡,promtool check rules 直接拒絕。

Prometheus 的 eol 規則群組,AssetEolPassed 對 QDevice 的 Debian 12 在跳提醒通知

收集端載入後的狀態:AssetEolPassed 1 筆(qdevice Debian 12,security_support_end 90 天前),AssetLicenceExpired 1 筆(fgt-edge,20 項),AssetEolUnknown 6 筆(60F 的 End of Order、兩台 DGX OS、兩台 NAS 的 QuTS hero、TS-464),其餘五條安靜。

五、儀表板上的一列

Day 20 的儀表板多一列「資產生命週期」。六個數字,沒有日期的、已過期的、過期授權、90 天內的、與 endoflife.date 不一致的、清單幾天前更新。下面兩張表,左邊每一列一個資產,剩餘天數排序,負數在最上面,30 天內紅、90 天內橘,右邊是授權逐項。basis 那一欄留著,Proxmox VE 那個 2028 年是推的。

儀表板的資產生命週期列

第一次載入時六個數字是 6、1、20、0、0、0.0 天。資產表的前五列:

資產 元件 里程碑 依據 剩餘天數
qdevice Debian 12 security_support_end vendor -90
viewer Node.js 22 end_of_support vendor 203
qdevice Debian 12 lts_end vendor 630
fgt-edge FortiOS 7.6.7 end_of_engineering vendor 655
pve1 Proxmox VE 9.2 end_of_support estimate 670

授權表 20 列全是 -384。

做這一列時發現一件 Day 20 留下的事。build-dashboard.py 用 Grafana 的 organize 轉換排欄位順序,順序表寫的是改名後的欄名,但 organize 先排序、後改名,比對的是原始欄名,所以從 Day 20 起每一張指定順序的表其實都照標籤字母排,磁碟表的「NAS」一直跑在「槽」和「型號」後面。改成用原始欄名查之後,所有表格的順序一起回來。剩餘天數原本用單位 d,Grafana 會自動換算成「-12.9 weeks」,改成整數天。

六、這張 EoL 表沒辦法處理的事

它不替人決定要不要升級。DGX OS 8 已經出了,7.6.0 是必經版本,升不升、何時升是 Day 26 的變更單要回答的,這張表只讓「DGX OS 7 沒有公布終止日」這件事每天出現一次。它也不替人決定要不要續約,20 項授權過期是事實,續約或寫明接受風險是決定,決定之前 AssetLicenceExpired 會一直響。它不追蹤版本漂移,Prometheus、Grafana、VictoriaLogs 這些有新版就該跟的軟體,用的是 Day 3 的 digest 釘住加定期更新,與 EOL 是兩件事。它不查硬體保固,60F 與 TS-464 的保固到期日在發票上,不在任何 API 裡,要的話加一列 warranty_end,basis 寫 vendor,來源寫發票編號。它也不會知道清單漏了什麼,交換器與 UPS 這次都沒放進來。

怎麼跑

# FortiGate:第二節的唯讀使用者,金鑰存成 fgt.token

# 收集端
sudo install -d -o metrics -g metrics /var/lib/onprem-metrics/eol /var/log/onprem-metrics
sudo install -d -m 0755 /etc/onprem-metrics
sudo install -m 0600 -o metrics -g metrics fgt.token /etc/onprem-metrics/fgt.token
sudo -u metrics ./textfile/eol-textfile.py --assets eol/assets.tsv --refresh --cache /var/lib/onprem-metrics/eol \
    --fortigate https://192.168.2.99:10443 --token-file /etc/onprem-metrics/fgt.token --insecure   # 先看一次
sed -n '/Day 25/,$p' systemd/collector.cron | sudo tee -a /etc/cron.d/onprem-metrics

# 規則、inhibit、儀表板
promtool check rules prometheus/rules/eol.yml && (cd tests && promtool test rules rules_eol_test.yml)
# alertmanager.yml 照 example 加上 EolTextfileStale 對 Asset(Eol|Licence).* 的 inhibit,reload 兩邊
python3 grafana/build-dashboard.py     # provisioning 每 60 秒重讀,不必重啟 Grafana

# 加一列
$EDITOR eol/assets.tsv && python3 -m unittest tests.test_eol_textfile && git commit -m "eol: <資產> <里程碑> <日期>, source <URL>"

明天

Day 26 是變更管理。這一段從 Day 19 到今天,每一篇都說「寫進變更單」,符合或接近 ISO27001 的變更單長什麼樣、放在哪、誰批、怎麼跟 Day 21 的日誌與今天的清單對起來等等問題,明天把它做出來。第一張就是 QDevice 的 Debian 12 升 13。


本系列文章與程式碼索引:onprem-ops-30days

今天的程式碼:onprem-metrics v0.3.0

參考資料

Day 1|系列規劃與場域總覽:從跑得起來到可長期維運,先談為什麼要封裝
Day 2|Container Station 薄殼架構:QPKG 骨架、生命週期腳本與狀態頁
Day 3|版本鎖定與供應鏈:image digest、SHA256SUMS 與授權檔
Day 4|GitHub Actions 自動打包與 release:從 git tag 到可驗證的套件
Day 5|案例 Jellyfin 與 Roon:硬體轉碼的裝置直通與主機網路
Day 6|案例 changedetection.io 與 Homepage:資安與資訊公告監看 + 整合入口
Day 7|在地自建 ComfyUI 的生存指南:自建 Image 鎖定、GPU 直通與三層目錄架構
Day 8|案例實戰:Open WebUI + Ollama 重構記,把專案回到通用框架會省下什麼呢?
Day 9|容量規劃:用模型與硬體搭配矩陣決定地端節點與儲存規格
Day 10|上游引擎一改版,地端 AI 環境用的配方壞了怎麼辦 ? patch 移植實戰紀錄
Day 11|DGX Spark 節點基線:DGX OS 初始設定、帳號與 SSH 加固
Day 12|熱與統一記憶體守護:取樣器、自動降載與長時間負載實測
Day 13|別讓節點踩爆模型!NFS 集中模型庫的單寫多讀、權限凍結與完整性治理
Day 14|儲存規劃與路徑實測:RAID 60 與 RAIDZ2 試算,SSD、NFS、iSCSI 載入時間解析
Day 15|Proxmox VE 雙節點 HA:Virtualization Station 上的 QDevice
Day 16|Proxmox VE 備份與還原:HDP for Business Beta 的排程、保留與還原演練
Day 17|儲存設備備份策略與還原演練:快照、HBS 3 與 3-2-1 備份策略
Day 18|3-2-1 的最後一步:異地物件儲存、保留政策與冷熱資料成本精算
Day 19|指標收集:把前十八天的取樣器接進同一個時間序列
Day 20|儀表板與告警,打造一個簡潔的單一面板
Day 21|日誌集中與保存:節點不裝新代理,封存要能比對
Day 22|被擋下的封包才是便宜情報:從防火牆靜默盲點到日誌降噪與自動化告警
Day 23|日誌找不到原因?從 tcpdump 最小權限封包擷取到 WORM 封存的網路排錯實戰
Day 24|稽核問「某台工作站上個月連到哪裡了」?FortiGate AUP 雙軌日誌實踐:線上 LogsQL 檢索與離線對帳修煉
Day 25|資產生命週期與授權 EOL 監看:到期日只是一個數字,通通收進 Prometheus 時間序列!
Day 26|變更管理實戰:串起 Git 變更單、監控與日誌,讓每次改動都有跡可循
Day 27|自動化稽核比對:當機器留下的日誌,對上工程師寫的變更單(VictoriaLogs × FortiGate × PVE)
Day 28|Rollback 實戰演練:沒真正執行過的復原步驟,永遠只是一場美麗的假設
Day 29|打造地端維運的 AI 圍欄:Agent 授權閘道實作,無工單即無工具,無核准即無不可逆變更
Day 30|完賽總結|算清一年的電費、硬體折舊與雲端代價:地端 AI 維運 30 天留下的真實資產


上一篇
Day 24|稽核問「某台工作站上個月連到哪裡了」?FortiGate AUP 雙軌日誌實踐:線上 LogsQL 檢索與離線對帳修煉
下一篇
Day 26|變更管理實戰:串起 Git 變更單、監控與日誌,讓每次改動都有跡可循
系列文
地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言