前言

最近在調整 Kong Data Plane 的回應標頭時,遇到一個讓我有點困惑的現象:

同樣修改 kong.conf,restart 後符合預期,reload 卻像是沒有吃到設定。

一開始以為是 reload 沒有成功,後來才發現,問題不是「新設定沒有讀到」,而是「我沒有明確提供新值」。

發現問題:註解掉 off,卻沒有恢復

我的環境是安裝在 VM 上的 Kong Data Plane。

當時為了關閉 Kong 回應標頭,在 kong.conf 加入:

headers = off

需要恢復時,我的操作很直覺:把這行註解掉。

# headers = off

我原本的理解是:

不再指定 off,應該就會恢復預設值。

但執行 reload 後,透過 Postman 呼叫 API,仍然沒有看到預期恢復的 Via 標頭;改用 restart,結果才符合預期。

排查:明確指定值,reload 就生效了

排查過程中,我也嘗試在 Postman 請求加入 Connection: close,但沒有改變測試結果。

真正的轉折,是不再透過註解切換,而是明確寫入:

headers = server_tokens, latency_tokens, X-Kong-Request-Id

再次 reload,Via 就恢復了。

這讓問題變得更明確:

reload 可以套用明確指定的新值,但將設定註解掉,並沒有清除先前的值。

原始碼線索:舊設定加上新設定

接著查看 Kong 官方 reload.lua 原始碼,其中有一段合併設定的邏輯:

local kong_env = assert(pl_file.read(args.conf))

if pl_path.exists(new_config.kong_env) then
  kong_env = assert(pl_file.read(new_config.kong_env)) .. "\n" .. kong_env
end

這段程式不是先逐項比較設定,而是把兩份檔案的文字接起來:

既有 .kong_env 的內容
+ 換行
+ 這次指定的設定檔內容

接著寫回 .kong_env,再交給 conf_loader 載入。

要注意,這段合併邏輯有條件:指定了 -c,而且指定的設定檔存在。 不能只看這一段,就把所有 reload 呼叫方式都視為完全相同。

為什麼註解沒有清掉舊值?

套到這次的情境,舊 .kong_env 已經有:

headers = off

而新設定檔只有:

# headers = off

合併後,相當於:

headers = off
# headers = off

這時就比較容易理解了:

第二行只是註解,並不是「刪除第一行」的指令,也沒有提供新的設定值。

因此,與其說「註解蓋不過舊設定」,不如說:

舊設定被保留下來,而新內容沒有提供替代值。

嚴格來說,reload.lua 直接呈現的是文字合併流程;設定檔如何解析,還會經過 conf_loader。本次實測顯示,明確指定新值可以成功切換,單純註解沒有達到相同效果。

我的操作調整

經過這次測試,我會避免用「註解/取消註解」來切換這個參數,而是保留一行有效設定,明確修改它的值。

關閉時:

headers = off

恢復時:

headers = server_tokens, latency_tokens, X-Kong-Request-Id

再執行:

kong reload -c /etc/kong/kong.conf

這不是要把 reload 判定為不可靠,而是要區分兩件事:

  • 明確設定新值
  • 移除原本的設定宣告

在這次測試中,兩者並不等價。

最後的心得:檔案內容與執行狀態,不一定是同一件事

這次最值得記住的,不只是 headers 的操作方式,而是:

看到設定檔裡某行已被註解,不代表執行中的系統就一定恢復預設值。

如果載入流程會保留舊狀態,再合併新內容,那麼「沒有指定」可能代表沿用,而不是重設。

對設定管理而言,除了檢查檔案,也需要驗證實際執行結果。這次就是透過明確改值、觀察回應,再回頭看原始碼,才釐清兩者的差別。

驗證範圍

本文記錄的是本次 VM 環境中的實測結果。引用的 Kong 原始碼為 2026-10-20 查閱 master 分支時的 commit 2103212;不同 Kong 版本或不同 reload 呼叫方式,實作與結果可能不同。