技術文章

Luna HSM 監控:SDK 與 SNMP 各自看得到什麼

監控 Luna HSM 有兩個資料來源:PKCS#11 SDK 與 SNMPv3。它們看到的不是同一台設備——各自有對方拿不到的指標,也有兩邊都拿不到的東西。本文以兩套 exporter 的實際指標清單逐項對照。

作者:雲杉科技更新於 2026/9/14
#Luna HSM#SNMP#PKCS11#Prometheus#監控#可觀測性
Luna HSM 監控:SDK 與 SNMP 各自看得到什麼

兩個資料來源,兩台不同的「HSM」

監控 Thales Luna HSM 時,你有兩條路可走:

  • PKCS#11 SDK(含 Luna 專有的 CA_* 延伸 API)
  • SNMPv3(HSM appliance 內建的 SNMP Agent)

常見的說法是「PKCS#11 是操作介面不是監控介面,所以監控要靠 SNMP」。這句話對了一半, 而錯的那一半會讓人做錯架構決策——SNMP 並不是 SDK 的超集。兩邊各自看得到對方看不到的 東西,而且缺口的位置和多數人的直覺相反。

最典型的例子:PKCS#11 Session 用了幾個、上限是多少。這是 HSM 監控最該盯的指標之一 (用滿了就再也建不了新連線),直覺上像是「設備管理面」的資訊、應該由 SNMP 提供。實際上 正好相反——SDK 一個標準呼叫就拿得到,SNMP 側一條都沒有

本文用兩套實際跑在生產環境的 exporter 逐項對照:luna-monitor(走 PKCS#11,指標前綴 hsm_*)與 snmp-monitor(走 SNMPv3,前綴 luna_*)。


SDK 看得到什麼

luna-monitor 從 PKCS#11 標準 API 與 Luna 的 CA_* 延伸取得 20 個指標,全部是 Gauge。

PKCS#11 標準的部分

不需要任何 vendor 延伸,任何 PKCS#11 實作都有:

指標來源為什麼重要
hsm_token_session_countC_GetTokenInfoulSessionCount目前開了幾個 session
hsm_token_max_session_countC_GetTokenInfoulMaxSessionCount上限;兩者一比就是飽和度
hsm_token_memory_total_bytesC_GetTokenInfopublic / private 各一組
hsm_token_memory_free_bytesC_GetTokenInfo同上
hsm_slot_flagsC_GetSlotInfoslot 狀態旗標
hsm_slot_hardware_versionC_GetSlotInfo硬體版本

Session 飽和度是這組裡最有價值的一項。它是即時的,而且 SNMP 完全沒有對應指標。

Luna CA_* 延伸的部分

指標來源 API
hsm_firmware_version_infoCA_GetFirmwareVersion
hsm_storage_total_bytes / used / free / container_overhead_bytesCA_GetHSMStorageInformation
hsm_token_storage_total_bytes / used / freeCA_GetTokenStorageInformation
hsm_token_object_countCA_GetTokenStorageInformation
hsm_stats_total_commandsCA_GetHSMStats(只取 ID=4)
hsm_capability / hsm_capability_countCA_GetHSMCapabilitySet
hsm_policy / hsm_policy_countCA_GetHSMPolicySet

不需要 HSM PIN。 這組指標全部可以在未登入的狀態下取得,exporter 不必持有任何密鑰材料 ——這對「監控元件不該握有生產憑證」的稽核要求是個實質優勢。


SDK 看不到什麼

限制的根源是:PKCS#11 的世界觀是「你連上的那個 slot」,不是「這台設備」

看不到說明
其他 partition只看得到自己連的那一個。整台設備有幾個 partition、各自用掉多少空間,一概不知
設備序號韌體版本拿得到,序號拿不到
License授權了哪些功能、授權 ID 是什麼,沒有
Policy 的文字說明hsm_policy{policy_id="7"} 只有數字 ID。那個 7 是什麼意思,要自己去翻文件
Client 註冊與分配關係哪些 client 註冊上來、各自被分配到哪些 partition,完全沒有
NTLS連線狀態、連線成敗累計、伺服器憑證到期日,一概沒有
安全狀態FIPS 模式、管理者登入失敗剩餘次數、是否被 zeroize
設備層運行資訊uptime、busy 時間、performance level、設備軟體版本

還有一個容易被忽略的部署面限制:走 SDK 就必須在 exporter 所在的機器上安裝 Luna Client 並設定好 Chrystoki.conf。這讓容器映像變胖,也把 exporter 綁死在有 client 的 節點上。


SNMP 看得到什麼

snmp-monitor 有 9 個 collector、61 個指標名稱。對一台 10 個 partition 的 Luna Network HSM 實測,產出 3,711 個 series

Collector涵蓋範圍
HsmTableCollector序號、型號、韌體版本、uptime、busy 時間、performance level、FIPS 模式、是否 zeroize、管理者登入失敗剩餘次數
HsmStatsCollector操作請求數、錯誤數、critical / non-critical 事件計數
NtlsCollector連線客戶端數、連線成敗累計、連線狀態、伺服器憑證到期
LicenseTableCollector授權 ID 與描述
PolicyTableCollectorHSM 政策:code、值、設定狀態、可讀的描述
PartitionPolicyCollector每個 partition 的完整政策樹
ClientRegistrationCollectorclient 名稱、IP、OTT 到期、是否需要 HTL
ClientSummaryCollectorpartition 清單與容量,加上 client ↔ partition 分配關係
ApplianceCollector設備軟體版本

SNMP 的獨特價值可以歸成三句話:

  1. 整台設備的視野。所有 partition 的標籤、序號、物件數、配置與可用容量,一次拿齊。
  2. 帶語意的中繼資料。Policy 不只是數字,而是 code + value + setting + description 四 欄。SDK 那邊的 policy_id="7" 在這裡是一行看得懂的文字。
  3. 設備與網路層的健康。NTLS 憑證到期這種資訊,只有這條路拿得到——而它過期的後果是 所有 client 連不上。

還有一個部署優勢:不需要安裝 Luna Client,只要網路連得到 HSM 的 SNMP Agent。exporter 可以是一個乾淨的小容器,也可以部署在跟 HSM 完全不同的網段。


SNMP 看不到什麼

看不到說明
PKCS#11 session 計數與上限mapper 的 56 條 OID 對照裡,session 相關是 0 條。這是兩邊落差最大的一項
token 記憶體的 public / private 細分SNMP 給的是 partition 的儲存容量,不是 token memory 的分區細節
即時性背景輪詢架構;指標的新鮮度取決於收集週期,不是「當下」

另外要付出兩個成本:

  • 憑證管理。SNMPv3 AuthPriv 要管 auth 與 priv 兩組密碼,而且是設備層的認證。相較之下 SDK 那條路連 PIN 都不用。
  • series 基數。3,711 個 series 來自一台設備。Policy、Partition Policy、Client 這幾張表 的列數很多,每列再乘上 indexoid 兩個 label。多台 HSM 時要把這件事算進 Prometheus 的容量規劃。

對照總表

想知道的事SDKSNMP
PKCS#11 session 使用數 / 上限
token 記憶體(public / private)
自己那個 partition 的儲存與物件數
所有 partition 的清單與容量
韌體版本
設備序號 / 型號
HSM 命令總數
操作錯誤數、事件計數
Capability / Policy(數字 ID)
Policy 的可讀描述
License
Client 註冊 / client↔partition 分配
NTLS 狀態與憑證到期
FIPS 模式、zeroize、登入失敗剩餘次數
uptime / busy / performance level
需要安裝 Luna Client
需要 HSM PIN否(但需 SNMPv3 帳密)

結論很簡單:兩者互補,不是二選一。 兩套 exporter 可以同時部署,指標前綴不同 (hsm_*luna_*)不會互相干擾。如果只能挑一個,就看你的痛點是「連線飽和」還是 「設備狀態」——前者選 SDK,後者選 SNMP。


兩邊都看不到什麼

這一節可能比前面兩節更重要,因為它決定了哪些問題不該指望監控系統回答:

  • 單把金鑰的使用統計。哪把金鑰被用了幾次、最後一次是什麼時候——兩邊都沒有。要這個 資訊只能在應用層自己記(這也正是稽核日誌存在的理由)。
  • 密碼學操作的延遲分布hsm_stats_total_commands 是累計計數,不是延遲。想知道 ML-DSA 簽章的 p99 是多少,得自己在呼叫端量。
  • 哪個應用在消耗資源。HSM 只知道有 session 連進來,不知道 session 背後是哪個服務。 要做歸因就得靠呼叫端的標籤。
  • 操作失敗的原因分類。SNMP 的 luna_hsm_operation_errors_total 是一個總數,不會告訴 你是 CKR_DEVICE_ERROR 還是 CKR_USER_NOT_LOGGED_IN。錯誤碼分類要在 client 端做。

換句話說:設備層的可觀測性到 partition 為止,再細的粒度必須由應用層提供。 規劃監控 時把這條界線畫清楚,可以省下很多「為什麼 HSM 不給我這個指標」的時間。


實作註記

以下是實際做這兩套 exporter 時值得留下的幾個細節。

快取的真正用途不是追趕收集速度

背景收集 + 快取是這類 exporter 的標準架構:Prometheus 來 scrape 時直接讀快取,不觸發 SNMP 收集。snmp-monitor 用的是三層快取:

層級TTL用途
Hot5 秒防止同一個 scrape 週期內重複觸發收集
Warm55 秒一輪收集完成後重設,涵蓋整個 scrape 週期
Cold無限SNMP 連線失敗時的最後保險,確保 scrape 永遠有資料

一個要澄清的數字:本文舊版聲稱「一次完整收集需要 60–90 秒,比 Prometheus 的 60 秒 scrape 週期還慢」,並以此作為三層快取的理由。這個數字查無來源。 專案中唯一的實測 記錄是對一台 10 個 partition 的 Luna Network HSM 收集,耗時 1.14 秒(產出 3,711 series)——快了將近兩個數量級。

收集之所以快,關鍵在 PartitionPolicyCollector 這類大表走的是 SNMP GETBULK Walk (每次最多回 50 行)而非逐筆 GET-NEXT;多分區環境下那棵政策樹可達 3,000+ OID,逐筆走 才會慢到分鐘級。

三層快取仍然值得保留,但理由要說對:它真正解的是把收集從 scrape 路徑上拿掉,以及 SNMP 暫時失聯時不要讓 Grafana 出現 No Data——Cold 層是為後者存在的,跟收集耗時無關。

Luna 的 OID 字串是非標準編碼

Luna 的 client 名稱在 OID 值裡不是直接的 UTF-8,而是 [長度, 字元1, 字元2, ...] 的格式。 少了這一步解碼,client 名稱會是一串亂碼。這是文件裡不顯眼、但一定會踩到的細節。

健康端點要能表達「資料太舊」

只回「服務活著」是不夠的——exporter 可以活得好好的,卻從三十分鐘前就沒收到新資料。 snmp-monitor/health 分三種狀態:

狀態條件HTTP code
initializing從未成功收集200
healthy快取在正常範圍內200
stale超過 2 倍收集週期未更新503

stale 回 503,Kubernetes liveness probe 或外部監控才抓得到「靜默供應陳舊資料」這種失能 模式。順帶一提,luna-monitor 目前沒有 /health 端點,容器健康檢查直接打 /metrics

多台 HSM 的部署形狀

每台 HSM 對應一個 exporter 實例,各自維護獨立的 session 與快取,用不同的 host port 區分, Grafana 再以 job label 區隔。SNMP 那條路在這裡特別省事——不需要在每個節點裝 Luna Client。


結語

「PKCS#11 是操作介面、SNMP 是監控介面」這個二分法聽起來乾淨,但它會讓人漏掉 session 飽和度這種只有 SDK 拿得到、卻又最該告警的指標。

比較實用的心智模型是:SDK 看的是「我這條連線的工作面」,SNMP 看的是「這台設備的管理 面」。 兩個面向都要,就兩套都部署;只能選一個,就先確認你最怕的故障模式落在哪一面。

最後,別忘了兩邊都看不到的那一塊——金鑰粒度的使用統計、操作延遲、應用歸因。那些不是 HSM 該給你的,是你的服務該自己記的。

如果你也在監控 Luna HSM 或其他 SNMP-only 設備,歡迎透過聯絡頁面交流。