KYAML 是什麼?KEP-5295 導讀筆記
前陣子剛好在執行 Release Signal 日常任務的時候,翻到一個名為 KYAML 的 PR,難道 Kubernetes 社群想要制定另一個 YAML 標準?還是有什麼特別呢?
本篇文章為繁體中文版本,英文版本請點擊這裡。
This article is in Traditional Chinese. For the English version, please click here.
今天讓我們來一起閱讀 KEP-5295: Introducing KYAML, a safer, less ambiguous YAML subset / encoding 吧!
本篇內容當下撰寫是 2025/7/31,會以此 commit 當前內容來介紹。
為何會有此 KEP?
有實際玩過 Kubernetes 的人就會知道,不管你是 DevOps 或 SRE 職位,有時候也會被戲稱 YAML 工程師。
除了要清楚了解 Kubernetes 的 Pod、Deployment、Node 等概念外,另一個絕對會碰到的就是 YAML (YAML Ain’t a Markup Language)。
撰寫這些描述檔,很多都是使用 YAML,但原始設計其實有些缺陷?
YAML 究竟有哪些問題?
YAML 的經典問題就是「挪威問題 The Norway Problem」,你可以把接下來一些 YAML 都放到 Online YAML Parser 網站實驗。
1 |
|
轉換後的 JSON 會變成:
1 |
|
這個看起來沒問題,接下來新增挪威:
1 |
|
邏輯上來講,轉換後的 JSON 要變成這樣:
1 |
|
但實際轉換後是變成:
1 |
|
現在讀到這裡一定是這個表情:
YAML 1.1 的規格書當中提及:
YAML allows scalar content to be presented in several formats. For example, the boolean “true” might also be written as “yes”.
換而言之,這可不是 bug,而是 feature,寫 Yes
理論上應該是字串,但實際轉換後給的是布林值 True
。
YAML 1.2 之後的 spec 已經移除相關規定,不過這要注意的是,1.2.0 發佈於 2009/07/21,筆者撰寫這篇文已經是 2025 年,時至今日,可以看 Online YAML Parser 還是會把 NO
轉換成 False
,這就需要看各家套件如何跟進了。
這種類似隱式轉換也很多,像下面的內容來看:
1 |
|
轉換 JSON 後會變成:
1 |
|
4_________2__
變成數字,11:00
也是數字(變成 60 進位),雖然雙引號在字串來說是可選,但在某些情況下是很重要的。
替代方案呢?JSON 應該能吧?
寫過 operator 就知道 Kubernetes 一定有支援 JSON,不過 JSON 也有缺點,它不能註解。
如果面對的是程式互相交換傳輸,需不需要看中間交換內容,確實沒那麼重要。
不過面對使用者那就不一樣了,撰寫了設定檔,卻不能寫註解,可維護性角度來說絕對大打折扣;再加上許多工具 (e.g., Helm) 都圍繞在 YAML 上,與其全面改用 JSON,不如專心把 YAML 寫更嚴謹。於是,有開發者就提出 KYAML 的想法!
KYAML 的目標 (Goals) 和非目標 (Non-Goals)
看起來 KYAML 想要大破大立,建立新標準?其實對,但也不對。
這裡先列出目標 (Goals) 的原文:
- Specify a YAML dialect which is 100% compatible with existing parsers and tooling.
- Provide libraries and tooling for encoding and converting to this formatting, with stable (idempotent) conversion.
- Provide a KYAML output format for kubectl.
- Update examples and documentation throughout the project.
- Address common YAML pitfalls through an opinionated formatting approach.
- Document the design and reasons for KYAML and the 100% compatibility with tooling expecting arbitrary YAML.
還有非目標 (Non-Goals) 的原文:
- Introduce alternative configuration languages that are not compatible with existing tooling.
- Server-side support for KYAML distinct from what we support in YAML already.
- Require projects to migrate to KYAML by default.
- Change the YAML library used by Kubernetes.
先來説説對的地方,從目標的第五點:
Address common YAML pitfalls through an opinionated formatting approach.
意思大概是,透過一種”有主見” (opinionated) 的格式化方式來解決常見的 YAML 問題,像剛剛前面提及到的挪威問題,明明是字串的 NO
但因為隱式轉換變成布林值的 false
。
至於不對的地方,還是可以看到目標的第一點和第六點:
Specify a YAML dialect which is 100% compatible with existing parsers and tooling.
Document the design and reasons for KYAML and the 100% compatibility with tooling expecting arbitrary YAML.
KYAML 必須要和指定或現有的 YAML 解析器和工具 100% 相容,技術上來說,KYAML 並不會取代 YAML,也不會建立新的標準。這部分可以先往下看缺點 (Drawbacks) 段落找到相關敘述:
Yet another standard. Rebuttal: KYAML is YAML and users can provide vanilla YAML anywhere that can accept KYAML.
除此之外,這不單純只有輸出格式而已,目標的第二點和第四點:
Provide libraries and tooling for encoding and converting to this formatting, with stable (idempotent) conversion.
Update examples and documentation throughout the project.
KYAML 會提供轉換函式庫和工具,也會把目前現有文件的 YAML 範例轉換為 KYAML。
接著看非目標 (Non-Goals) 的論述,很有趣了,可以看看第二點和第四點:
Server-side support for KYAML distinct from what we support in YAML already.
Change the YAML library used by Kubernetes.
等等,不是說要寫 KYAML?為什麼現在又說 Server-side 不會支援?還說不要改 Kubernetes 現有的 YAML 函式庫?
筆者當初看這段時候覺得超矛盾,但後來重新反思了一下,Server-side 確實可以不用支援,回到 Goals 的第一點和第六點,要和指定或現有的 YAML 解析器和工具相容,所以 Server-side 就不用特別寫解析器支援了。
解析完這次的動機,就可以來看看要如何實際提案和設計吧!
提案
這邊先列出原文,KEP 要如何解 YAML 問題:
- Always double-quoting value strings (no ambiguity around things like “NO”).
- Unquoted keys, unless they are not obviously “safe” (e.g. “no” would always be quoted).
- Always using
{}
for structs and maps (no more obscure errors about mapping values).- Always using
[]
for lists (no more trying to figure out if a dash changes the meaning).
字串一律加上雙引號,Key-Value 的 Key 原則上不加入雙引號(除非它明顯不安全,就像 no
),使用 {}
表達所有的 struct 和 map;使用 []
表達所有的 list。
綜合以上想法,它不會是 whitespace-sensitive,這些寫法就會回到 flow style,而非普遍 YAML 常見的 block style。
讀到這邊就會覺得:「這不就是 JSON 嗎?」恭喜問了就是!跟 JSON 不同的地方在於:
- Allows comments (when authored by users).
- Allows trailing commas on the last item in a list or struct/map.
- Does not require quoted keys.
可以寫註解、可以在 map 或 struct 加上結尾逗號、不需要在每個 key 加入引號。
如果每個 struct 或 map 都會有 {}
,問題就來了,請看下列的內容:
1 |
|
這些內容是非法 JSON,因為 JSON 不允許有註解,但這是合法 YAML。
KYAML 以 struct 開頭是 {
,JSON 也是用 {
做開頭,要如何辨識內容是 YAML 還是 JSON?
為了做這部分區別,KYAML 規定開頭一定會有分隔號 (---
),這樣同時解決 KYAML 和 JSON 歧義問題,並且區隔了有格式缺陷 (ill-formed) 的 JSON。
出現了 {}
和 []
之後,接下來就會有宗教戰爭(括號下放、寫在一起等),以 KEP 來說,比較偏好寫在一起可以節省垂直空間,以下是原文敘述:
KYAML also tries to economize on vertical space by “cuddling” some kinds of brackets together.
設計理念差不多介紹到這裡,因為文章篇幅關係,對設計細節有興趣的可以直接去翻該 KEP 來閱讀。
總之,最終結果大約會長這樣 kubectl get -o kyaml svc hostnames
:
1 |
|
如何使用
Feature gate 對於使用者端的 CLI kubectl
並沒有太實用,不過很類似的就是環境變數,可以設定 KUBECTL_KYAML
。這點其實跟 kuberc
差不多。
Alpha 階段會需要在環境變數中設定 KUBECTL_KYAML
為 true
,目前依照追蹤來看,會在 1.34 出現。
Beta 階段會預設啟用,除非把 KUBECTL_KYAML
設定為 false
。
GA 階段會無視 KUBECTL_KYAML
變數,都可以任意使用。
確定在哪個階段後,就可以像這樣 kubectl get -o kyaml ...
,欸對,就是 -o yaml
中間多打一個 k
就好,就是這麼簡單!
總結
結論一句話就是:「KYAML 是 YAML,但不是所有 YAML 是 KYAML。」
筆者自己認為,YAML 其實就像 JavaScript,本身是弱型別,但帶來的問題是各種千奇百怪(e.g., 9 + "1" => "91"
或 91 - "1" = 9
);然而 KYAML 就像 TypeScript,變成強型別改善 JavaScript 本身的缺陷。不全然相同的地方是,KYAML 本身輸出還是符合 YAML 規範。
後續如果沒有太多問題,個人很看好這部分的改善,少了很多 YAML 本身的歧義,解決 JSON 不能註解的缺點,區隔有問題的 JSON,還不需要去變更現有 Kube API Server 引用的函式庫。
可以說是一舉多得,期待後續其他被 YAML 深受其害的專案跟上,一同消除 YAML 所帶來的潛在問題。
這算是我第一篇認真閱讀 KEP,並實際用文章記錄出思考歷程,如果喜歡這類型文章,幫我多按表情或留下想法。
後記
前陣子有人在 Medium 號稱自己拿到 “Kubernetes 2.0 秘密內部測試”,然後有些人轉發到社群媒體開始說 Kubernetes 2.0 要出了,哪些功能要被移除,還說不需要學 Helm 或 Argo。
我也在 CNTUG 常常宣導和鼓勵大家,使用開源軟體有心力,最好參與一下社群,這樣才不會被一些群魔亂舞或假訊息騙。
KubeCon 演講一定會有 SIG 的成員出來分享新功能或時程規劃,像這種大版號變更一定會要求所有 SIG 成員跟進,2025 年中現在版本出到 1.34,SIG Storage 的時程規劃都已經排到 1.39,大概可以說 2 年內不太可能會有大版本更新。
加上 Kubernetes Slack 的所有討論,根本沒人在講 2.0 的時程,如果真的要讓 2.0 實現出來,趕快丟 KEP 改個架構可能還比較實際。