附錄:YAML 技巧

本指南的大部分內容都集中在編寫範本語言上。在這裡,我們將探討 YAML 格式。YAML 有一些實用的功能,我們作為範本作者,可以利用這些功能使我們的範本更不容易出錯且更易於閱讀。

純量和集合

根據 YAML 規格,有兩種类型的集合和許多純量类型。

這兩種类型的集合是映射和序列

map:
  one: 1
  two: 2
  three: 3

sequence:
  - one
  - two
  - three

純量值是單個值(而不是集合)

YAML 中的純量类型

在 Helm 的 YAML 方言中,值的純量資料类型由一組複雜的規則決定,包括資源定義的 Kubernetes 綱要。但在推斷类型時,以下規則往往適用。

如果整數或浮點數是不帶引號的純文字,則通常將其視為數值类型

count: 1
size: 2.34

但如果它們帶有引號,則將其視為字串

count: "1" # <-- string, not int
size: '2.34' # <-- string, not float

布林值也是如此

isGood: true   # bool
answer: "true" # string

空值的字詞是 null(而不是 nil)。

請注意,port: "80" 是有效的 YAML,並且可以通過範本引擎和 YAML 解析器,但如果 Kubernetes 預期 port 是整數,則會失敗。

在某些情況下,您可以使用 YAML 節點標籤強制執行特定类型推斷

coffee: "yes, please"
age: !!str 21
port: !!int "80"

在上面,!!str 告訴解析器 age 是字串,即使它看起來像整數。而 port 被視為整數,即使它帶有引號。

YAML 中的字串

我們放置在 YAML 文件中的大部分資料都是字串。YAML 有多種表示字串的方法。本節說明這些方法,並演示如何使用其中的一些方法。

有三種「內嵌」宣告字串的方法

way1: bare words
way2: "double-quoted strings"
way3: 'single-quoted strings'

所有內嵌樣式都必須在一行上。

  • 純文字是不帶引號的,並且沒有跳脫。因此,您必須小心使用的字元。
  • 雙引號字串可以使用 \ 跳脫特定字元。例如 "\"Hello\", she said"。您可以使用 \n 跳脫換行符。
  • 單引號字串是「字面量」字串,不使用 \ 跳脫字元。唯一的跳脫序列是 '',它被解碼為單個 '

除了單行字串之外,您還可以宣告多行字串

coffee: |
  Latte
  Cappuccino
  Espresso  

以上將把 coffee 的值視為等同於 Latte\nCappuccino\nEspresso\n 的單個字串。

請注意,| 之後的第一行必須正確縮排。因此,我們可以通過執行以下操作來破壞上面的範例

coffee: |
                  Latte
  Cappuccino
  Espresso

因為 Latte 縮排不正確,我們會收到如下錯誤

Error parsing file: error converting YAML to JSON: yaml: line 7: did not find expected key

在範本中,有時將虛假的「第一行」內容放入多行文件中更安全,只是為了防止出現上述錯誤

coffee: |
  # Commented first line
         Latte
  Cappuccino
  Espresso  

請注意,無論第一行是什麼,它都將保留在字串的輸出中。因此,例如,如果您使用此技術將檔案的內容注入 ConfigMap,則註釋應為讀取該條目的任何內容所期望的类型。

控制多行字串中的空格

在上面的範例中,我們使用 | 來表示多行字串。但請注意,我們的字串內容後面跟著一個尾隨的 \n。如果我們希望 YAML 處理器去除尾隨的換行符,我們可以在 | 之後添加一個 -

coffee: |-
  Latte
  Cappuccino
  Espresso  

現在 coffee 的值將是:Latte\nCappuccino\nEspresso(沒有尾隨的 \n)。

其他時候,我們可能希望保留所有尾隨空格。我們可以使用 |+ 符號來做到這一點

coffee: |+
  Latte
  Cappuccino
  Espresso  


another: value

現在 coffee 的值將是 Latte\nCappuccino\nEspresso\n\n\n

文字區塊內的縮排將被保留,並且也會導致換行符被保留

coffee: |-
  Latte
    12 oz
    16 oz
  Cappuccino
  Espresso  

在上面的情況下,coffee 將是 Latte\n 12 oz\n 16 oz\nCappuccino\nEspresso

縮排和範本

在編寫範本時,您可能會發現自己希望將檔案的內容注入範本中。正如我們在前面的章節中看到的,有兩種方法可以做到這一點

  • 使用 {{ .Files.Get "FILENAME" }} 獲取圖表中檔案的內容。
  • 使用 {{ include "TEMPLATE" . }} 渲染範本,然後將其內容放置到圖表中。

將檔案插入 YAML 時,最好了解上面的多行規則。通常,插入靜態檔案的最簡單方法是執行以下操作

myfile: |
{{ .Files.Get "myfile.txt" | indent 2 }}

請注意我們如何進行上述縮排:indent 2 告訴範本引擎將「myfile.txt」中的每一行縮排兩個空格。請注意,我們沒有縮排該範本行。這是因為如果我們這樣做了,第一行的檔案內容將會縮排兩次。

摺疊多行字串

有時您希望在 YAML 中用多行表示字串,但在解釋時希望將其視為一行長字串。這稱為「摺疊」。要宣告摺疊區塊,請使用 > 而不是 |

coffee: >
  Latte
  Cappuccino
  Espresso  

上面的 coffee 的值將是 Latte Cappuccino Espresso\n。請注意,除了最後一個換行符之外,所有換行符都將轉換為空格。您可以將空格控制與摺疊文字標記結合使用,因此 >- 將替換或修剪所有換行符。

請注意,在摺疊語法中,縮排文字將導致保留行。

coffee: >-
  Latte
    12 oz
    16 oz
  Cappuccino
  Espresso  

以上將產生 Latte\n 12 oz\n 16 oz\nCappuccino Espresso。請注意,空格和換行符仍然存在。

在一個檔案中嵌入多個文件

可以將多個 YAML 文件放置到單個檔案中。這是通過在新文件前面加上 --- 並在文件結尾加上 ... 來完成的


---
document:1
...
---
document: 2
...

在許多情況下,可以省略 ---...

Helm 中的某些檔案不能包含多個文件。例如,如果在 values.yaml 檔案中提供了多個文件,則只會使用第一個文件。

但是,範本檔案可能包含多個文件。發生這種情況時,在範本渲染期間,檔案(及其所有文件)將被視為一個物件。但在將生成的 YAML 送入 Kubernetes 之前,它會被分割成多個文件。

我們建議僅在絕對必要時才在每個檔案中使用多個文件。在檔案中包含多個文件可能難以除錯。

YAML 是 JSON 的超集

因為 YAML 是 JSON 的超集,所以任何有效的 JSON 文件應該都是有效的 YAML。

{
  "coffee": "yes, please",
  "coffees": [
    "Latte", "Cappuccino", "Espresso"
  ]
}

以上是表示此內容的另一種方法

coffee: yes, please
coffees:
- Latte
- Cappuccino
- Espresso

並且可以將兩者混合使用(小心)

coffee: "yes, please"
coffees: [ "Latte", "Cappuccino", "Espresso"]

這三者都應解析為相同的內部表示形式。

雖然這表示諸如 values.yaml 之類的檔案可能包含 JSON 資料,但 Helm 不會將檔案擴展名 .json 視為有效的後綴。

YAML 定位點

YAML 規格提供了一種儲存對值的參考的方法,並稍後通過參考引用該值。YAML 將此稱為「定位」

coffee: "yes, please"
favorite: &favoriteCoffee "Cappuccino"
coffees:
  - Latte
  - *favoriteCoffee
  - Espresso

在上面,&favoriteCoffee 設定了對 Cappuccino 的參考。稍後,該參考將用作 *favoriteCoffee。因此 coffees 變為 Latte, Cappuccino, Espresso

雖然在某些情況下定位點很有用,但它們的一個方面可能會導致細微的錯誤:第一次使用 YAML 時,參考會被展開然後丟棄。

因此,如果我們要解碼然後重新編碼上面的範例,則生成的 YAML 將是

coffee: yes, please
favorite: Cappuccino
coffees:
- Latte
- Cappuccino
- Espresso

因為 Helm 和 Kubernetes 經常讀取、修改然後重寫 YAML 檔案,所以定位點將會丟失。