Kubernetes — ConfigMap

Ray Lee | 李宗叡
Learn or Die
Published in
25 min readMar 8, 2020

My Blog

概述

本篇為 ConfigMap 的介紹與使用筆記, 參考來源為 官方文件, 除了文件內容翻譯外, 也會有 Questions and Answers 區塊來將重點摘出。

建立 ConfigMap

你可以使用 kubectl create configmap 或是 kustomization.yaml 中的 ConfigMap 產生器來建立 ConfigMap。 kubectl 從 1.14 開始支援 kustomization.yaml

使用 kubectl 建立 ConfigMap

使用 kubectl create configmap 指令, 從 資料夾, 檔案, 或 輸入值 來建立 ConfigMaps

kubectl create configmap

是你想要給予這個 COnfigMap 的名字, 而 是資料的來源, 可以是資料夾, 檔案, 或是輸入值

當你從檔案建立 ConfigMap, 的 key 預設為檔案名稱, 而 value 為檔案內容

你可以使用 kubectl describe 或是 kubectl get 來取得 ConfigMap 的資訊

從資料夾建立 ConfigMap

你可以使用 kubectl create configmap 從一個資料夾裡頭多個檔案來建立 ConfigMap。 當你從資料夾建立 ConfigMap, kubernetes 會辨識出資料夾內合法的檔案名稱, 然後將這些檔案都裝到一個新的 ConfigMap。 所以非 regular 類型的檔案都會被無視 (像是, 子資料夾, 連結, 裝置, 管道, 等等) 舉例來說:

# 建立本地資料夾
mkdir -p configure-pod-container/configmap/

# 下載範例檔
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties

# 建立 configmap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/

上面的指令會打包每個檔案, 此範例中為 configure-pod-container/configmap/ 資料夾中的 game.properties 以及 ui.properties, 會裝到 game-config 這個 ConfigMap。 你可以使用下面的指令來顯示 ConfigMap 細節:

輸出類似這樣:

Name:         game-config
Namespace: default
Labels:
Annotations:

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

config-pod-container/configmap/ 資料夾中的 game.properties 以及 ui.properties 被列在 ConfigMap 中的 data 區塊

執行指令檢視:

輸出類似:

apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

從檔案建立 ConfigMaps

你可以使用 kubectl create configmap 從單檔或多檔案建立 ConfigMap 例如, 執行以下指令:

會建立以下 ConfigMap, 執行以下指令檢視:

輸出類似:

Name:         game-config-2
Namespace: default
Labels:
Annotations:

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

你可以多次使用 --from-file 這個 flag, 藉此從多個檔案建立 ConfigMap:

執行以下指令來顯示 game-config-2 細節資訊

輸出類似:

Name:         game-config-2
Namespace: default
Labels:
Annotations:

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

使用 --from-env-file 選項, 從 env-file 建立 ConfigMap, 例如以下為 env 範例

# Env-files 含有一系列的環境變數
# 以下為語法:
# env file 中的每行必須是 VAR=VAL 格式
# # 開頭的那行會被忽略 (也就是 comment)
# 空白行會被忽略
# quotation marks 在 configMap 中不具有特別意義, 也就是說會變成 configMap 的 value 一部分

# 下載範例檔案
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties

# 範例檔如下:
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"

# 這個 comment 以及上面的空行會被忽略

執行以下指令:

會產生以下 ConfigMap, 執行以下指令檢視這個 ConfigMap

輸出類似:

apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
data:
allowed: '"true"'
enemies: aliens
lives: "3"

注意: 當多次使用 --from-env-file 時, 只有最後一個會被採用

多次使用 --from-env-file 的行為如下:

# 下載範例
wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties

# 建立 ConfigMap
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties

會產生以下的 ConfigMap, 執行以下指令檢視這個 ConfigMap

輸出如下:

當從檔案建立 ConfigMap 時, 自己定義 key

當你使用 --from-file 來建立 ConfigMap 時, 你不一定要使用檔名為 key, 你也可以自己定義 key, 如以下語法:

kubectl create configmap game-config-3 --from-file==

<my-key-name> 為你想要的 key name, 而 <path-to-file> 為檔案來源 例如說

以上指令會產生一個 ConfigMap, 執行以下指令來檢視它

輸出類似:

從輸入值建立 ConfigMap

你可以使用 kubectl create configmap--from-literal flag, 從命令行來定義輸入值

這個 flag 可以使用多次, 每一次都會產生 ConfigMap 中的一個 key / value pair, 輸入以下指令檢視:

輸出類似:

從產生器建立 ConfigMap

從 1.14 開始, kubectl 支援使用 kustomization.yaml。 你可以使用產生器來建立 ConfigMap 並且在 Apiserver 中建立這個物件。 產生器必須被定義在 kustomization.yaml 檔案中

從檔案建立 ConfigMaps

舉例來說, 從 configure-pod-container/configmap/game.properties 這個檔案來建立 ConfigMap

apply 這個資料夾來建立 ConfigMap 物件

你可以像這樣來確認 ConfigMap 是否有被建立:

kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s


kubectl describe configmaps/game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels:
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events:

可以注意到, 被產生的 ConfigMap name 後面有串 hash 的字串, 這確保每次內容被修改時, 都會建立一個新的 ConfigMap

當從 file 產生 ConfigMap 時, 自定義 key

使用 ConfigMap 產生器時, 不一定要使用檔名來當作 key, 你也可以自訂義, 例如說, 從 configure-pod-container/configmap/game.properties 檔案來建立 ConfigMap, 並且使用 game-special-key 當作 key

# 使用 kustomization.yaml 定義 ConfigMapGenerator
cat <./kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF

Apply kustomization.yaml 所在資料夾來建立 ConfigMap 物件

kubectl apply -k .
configmap/game-config-5-m67dt67794 created

從輸入值來建立 ConfigMap

現在要從輸入值 special.type=charm 以及 special.how=very 來產生 ConfigMap, 先在 kustomization.yaml 檔案定義 ConfigMap 產生器

# Create a kustomization.yaml file with ConfigMapGenerator
cat <./kustomization.yaml
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
EOF

Apply kustomization.yaml 檔所在資料夾來建立 ConfigMap 物件

kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created

使用 ConfigMap 資料來定義容器環境變數

使用單一 ConfigMap 定義容器環境變數

  • 建立 configMap
  • 將 ConfigMap 的 special.how 的值指派給環境變數 SPECIAL_LEVEL_KEY, vim pods/pod-single-configmap-env-variable.yaml 並輸入以下值
  • 建立該 Pod

現在, 該 Pod 的輸出將包含環境變數 SPECIAL_LEVEL_KEY=very

使用多個 ConfigMap 定義容器環境變數

  • 跟上一個 example 一樣, 建立一個 ConfigMap, vim configmap/configmaps.yaml, 並輸入以下值:
  • 建立 ConfigMap
  • 定義一個 Pod 檔, 並定義該 Pod 環境變數, vim pods/pod-multiple-configmap-env-variable.yaml, 輸入以下值:
  • 建立該 Pod
  • 現在, 該 Pod 輸出包含環境變數 SPECIAL_LEVEL_KEY=very 以及 LOG_LEVE=INFO

在 ConfigMap 中配置所有的 key-value pairs 如容器環境變數

注意: 這個功能在 Kubernetes 1.6 以及之後版本才可用

  • 建立包含多組 key-value 的 ConfigMap, vim configmap/configmap-multikeys.yaml 並輸入以下內容:
  • 建立該 ConfigMap
  • 使用 envFrom 來將 ConfigMap 中的所有 data 都定義成容器環境變數。 ConfigMap.metadata.name 會成為 .spec.containers.envFrom.configMapRef.name
  • 建立 Pod
  • 現在, Pod 的輸出包含了環境變數 SPECIAL_LEVEL=very 以及 SPECIAL_TYPE=charm

在 Pod 的指令選項使用由 ConfigMap 定義的環境變數

你可以在 Pod 的 command 區塊使用由 ConfigMap 定義的環境變數, 語法為 $(VAR_NAME), 啥? 看不懂? 簡單來說, 如果 env 的 name 是 SPECIAL_LEVEL_KEY, 那你可以在 command 區塊中使用 $(SPECIAL_LEVEL_KEY), 這樣夠清楚明白了吧?

  • 範例如下:
  • 建立該 Pod
  • test-container 輸出如下:
very charm

將 ConfigMap 資料加到 Volume

如同 Create ConfigMaps from files 的解釋, 當你使用 --from-file 建立 ConfigMap, 檔名會變成存在 ConfigMap data 區塊中的 key, 而這個檔案的內容會是該 key 的值

  • 本節中的 ConfigMap 範例為 special-config, 如下:
  • 建立該 ConfigMap

將 ConfigMap 的資料載入到 Volume 中

將 ConfigMap 的 name 加到 Pod spec 中的 volumes 區塊。 這會將 ConfigMap 的資料加到由 volumeMounts.mountPath 指定的資料夾 (在本範例中, 為 /etc/config)。 command 列出在該資料中, 符合 ConfigMap key name 的檔案

  • 範例檔:
  • 建立該 Pod
  • 當該 Pod 運行時, 會執行 ls /etc/config/ 產生以下輸出:
SPECIAL_LEVEL
SPECIAL_TYPE

注意: 如果在 /etc/config 資料夾中有其他檔案的話, 他們會被刪除哦!

將 ConfigMap 資料加到 Volume 中特定的路徑

使用 path 欄位來指定特定的 ConfigMap item 到想要的檔案路徑。 在這個例子中, SPECIAL_LEVEL item 將會被掛載到 config-volume volume 中的 /etc/config/keys

  • 範例如下:
  • 建立該 Pod
  • 當 Pod 開始運行, 指定 cat /etc/config/keys 會產生以下輸出
very

投射 keys 到指定的路徑以及檔案權限

我們可以投射 keys 到指定的路徑以及特定的檔案權限, 根據每個檔案的狀況。 這部分會在 Secrets 有更詳細介紹, 這邊不多家贅述

掛載的 ConfigMap 會被自動更新

當已經被掛載到 volume 的 ConfigMap 更新了, 映射的 key 最終也會更新。 kubelet 會每一段時間確認一次掛載的 ConfigMap 是否有更新。 然而, kubelet 使用了 ttl-based cache 來取得 ConfigMap 當下值, 結果就是, 從 ConfigMap 更新之後到新的 key 被投射到 Pod 的延遲時間會等於 kubelet 同步頻率 (預設 1 分鐘) + ttl ConfigMap cache (預設 1 分鐘), 你也可以藉由更新該 pod 的 annotations 來觸發立即刷新 注意: 使用 ConfigMap 為 subPath volume 的容器將不會收到 ConfigMap 的更新

理解 ConfigMap 以及 Pods

ConfigMap API 資源以 key-value pairs 的方式儲存配置資料。 這個資料可以被 pods 所運用, 也可提供給系統元件的配置資料, 像是 controllers。 ConfigMap 跟 Secrets 很類似, 但主要是提供不含敏感資訊的字串用途。 使用者或系統元件可以使用 ConfigMap 儲存配置檔資料

注意: ConfigMap 需參照屬性檔案, 而非取代他們。 想像 ConfigMap 就像是類似 Linux /etc 資料夾以及其內容。 舉例來說, 如果你從 ConfigMap 建立了 Kubernetes Volume, volume 中的每個檔案就代表著 ConfigMap 當中的每一個 data item

ConfigMap 的 data 欄位含有設定檔資料。 如以下範例, 它可以很簡單 - 比如說使用 --from-literal 定義每一個 item, 或複雜一點 - 像使用 --from-file 定義一個JSON 格式的配置檔案

Restrictions

  • 你必須在 Pod specification 區塊中參考一個 ConfigMap 之間先建立它 (除非你把它標註為 optional)。 如果你參考一個不存在的 ConfigMap, 這個 Pod 不會開始。 同樣的, 如果你參考一個不存在的 key, 那 Pod 也是不會開始
  • 如果你使用 envFrom 從 ConfigMaps 定義環境變數, 若 keys 被判斷為不合法的話, 將會被忽略。 Pod 還是可以啟動, 但是不合法的名稱將會被記錄在事件 (InvalidVariableNames)。 log 的訊息會列出每一個忽略的 key, 例如說:
  • 輸出像是:
LASTSEEN FIRSTSEEN COUNT NAME          KIND  SUBOBJECT  TYPE      REASON                            SOURCE                MESSAGE
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
  • ConfigMap 隸屬於特定的 Namespace, 且只可被隸屬於同個 namespace 中的 pods 所使用。
  • ConfigMap 不可被用在 static pods 上, 因為 kubelet 不支援

Questions and Answers

Kubernetes ConfigMap 中, ConfigMap 可以被使用在不同 namespace 的 pod 嗎?

不行

Kubernetes ConfigMap 中, ConfigMap 可以被使用在 static pod 嗎?

不可

Kubernetes ConfigMap 中, 如果我建立了一個 Pod, 並 reference 一個不存在的 ConfigMap 的 key 那會怎麼樣?

該 Pod 不會開始

Kubernetes ConfigMap 中, 如果我建立了一個 Pod, 並 reference 一個不存在的 ConfigMap, 那會怎麼樣?

該 Pod 不會開始

Kubernetes ConfigMap 中, 如果我要立即觸發 ConfigMap 更新同步的話, 我可以怎麼做?

更新該 Pod 的 annotation

Kubernetes ConfigMap 中, 使用 ConfigMap 為 subPath volume 的容器會收到 ConfigMap 更新嗎?

不會

Kubernetes ConfigMap 中, ttl based cache 預設多久?

1 分鐘

Kubernetes ConfigMap 中, kubelet 預設多久會確認一次 ConfigMap 是否有更新?

1 分鐘

Kubernetes ConfigMap 中, 當掛載到 volume 的 ConfigMap 更新了, 同步到 Pod 的延遲時間跟哪兩個因素有關?

  • kubelet 確認變更的頻率
  • ttl cache 使用的時間

Kubernetes ConfigMap 中, 當掛載到 volume 的 ConfigMap 更新了, 會同步更新到 Pod 嗎?

會哦

Kubernetes 中, 如果我要在 Pod 的 command 區塊中使用 env 的話, 假設我 env 的 name 為 SPECIAL_LEVEL_KEY, 那在 command 區塊中的變數為?

$(SPECIAL_LEVEL_KEY)

**Kubernetes 中, 假設我有 ConfigMap 如下, 我該怎麼樣一次性的將此 ConfigMap 中的所有 data 都設成環境變數? 該使用哪一個 field? **

  • Example:
  • Answer:

請解釋以下的 kustomization.yaml 檔案

  • Example:
  • Answer:

以下的 kustomization.yaml 檔案中, 如果我要自定義 key, 我可以怎麼做?

  • Example:
  • Answer:

以下的 kubernetes kustomization.yaml 代表什麼意思?

  • Example:
  • Answer:

Kubernetes 中, 如果我想要使用產生器來建立 ConfigMap, 我可以在哪個檔案中定義?

kustomization.yaml

以下的 Kubernetes ConfigMap 範例中, 如果我不想使用檔名為 key, 我想要自己定義 key 的話, 我可以怎麼修改?

  • Example:
kubectl create configmap game-config-3 --from-file=
  • Answer:
kubectl create configmap game-config-3 --from-file==

Kubernetes ConfigMap 中, 當我使用 --from-file flag 來建立 ConfigMap 時, 除了使用檔名為 key 之外, 我可以自己定義 key 嗎?

可以

Kubernetes 中, 當我多次使用 --from-env-file 這個 flag 多次, 會發生什麼事?

只有最後一個會被採用

Kubernetes 中, 如果我想要從 env 檔來建立 ConfigMap, 我可以使用哪一個 flag?

--from-env-file

Kubernetes ConfigMap 中, 當我使用 --from-env-file 時, Kubernetes 會如何處理 quotation marks, 像是 ', 或 "

會將他們變成 ConfigMap value 的一部分

Kubernetes ConfigMap 中, 當我使用 --from-env-file 時, Kubernetes 會如何處理 # 開頭的 comment?

無視

Kubernetes ConfigMap 中, 當我使用 --from-env-file 時, Kubernetes 會如何處理空行?

無視

Kubernetes ConfigMap 中, 當我使用 --from-env-file 時, 內容必須是什麼格式?

VAR=VAL

以下的 K8s ConfigMap yaml 檔, 代表什麼意思?

  • yaml 檔:
  • Answer:
  • data:
  • data.1: 單個屬性, data.1 為 key, hello 為 value
  • data.2: 單個屬性, 同上
  • config: config 為整個配置文件, 內容如下
  • | 為 Block Style Indicator, literal style, 如果 string 當中有空行, 會被保留下來, 可參考範例

Kubernetes 中, 當我們不知道要怎麼樣建立一個資源時, 可以使用哪一個指令來檢視範例?

Kubernetes 中, 如果我在 tls 資料夾下有 4 個 檔案(如下), 現在我要建立一個 configMap, 這個 configMap 需同時包含這 4 個檔案, 檔名為 key, value 為檔案內容, 那我可以怎麼做?

  • 資料夾:
  • Answer:

Kubernetes 中, 如果我要 print 出 configMap 的內容, 我可以使用哪一個指令?

Kubernetes 中, 如果我在 tls 資料夾下有 4 個 檔案(如下), 現在我要建立一個 configMap, 這個 configMap 只包含 key.pem 的內容, 檔名為 key, value 為檔案內容, 那我可以怎麼做?

  • 資料夾:
  • Answer:

kubectl create configmap 中, --from-file 的 flag 可以重複使用嗎?

可以哦

** 以下的 Kubernetes Pod yaml 配置檔是什麼意思?**

  • 配置檔:
  • Answer:

以下的 Kubernetes yaml 檔是什麼意思?

  • yaml 檔:
  • Answer:

以下的 Kubernetes yaml 檔是什麼意思?

  • yaml 檔:
  • Answer:

以下的 Kubernetes yaml 檔是什麼意思?

  • yaml 檔:
  • Answer:

Kubernetes 中, 如果我要建立一個 configMap, key/value 不經由檔案提供, 而是透過我的指令輸入提供, 那我可以使用哪一個 flag?

Kubernetes 中, 當我建立 configMap 時, --from-literal 這個 flag 可以重複使用嗎?

可以

最後

人非聖賢, 孰能無過… 阿不是, 是人非草木, 豈能無情… 你清脆的掌聲於我, 有如浪頭與衝浪者的關係! 讓我找到存在的價值…

拍 1 下: 來都來了, 刻個到此一遊吧!
拍 10 下: 覺得小生寫得還可以, 馬馬虎虎普普通通淒淒慘慘戚戚...
拍 20~30 下: 這篇文章有幫助到你, 讓你的概念清晰了百分之零點零零一
拍 40~50 下: 看完覺得心情愉悅, 或是覺得 Ray 很帥

Write Medium in Markdown? Try Markdium!

--

--

Ray Lee | 李宗叡
Learn or Die

It's Ray. I do both backend and frontend, but more focus on backend. I like coding, and would like to see the whole picture of a product.