ConfigMaps
ConfigMap 是一個 API 物件,用於以鍵值組形式儲存非機密資料。Pod 可以將 ConfigMap 作為環境變數、命令列引數或組態檔在磁碟區中使用。
ConfigMap 允許您將環境特定的組態與容器映像檔解耦,以便您的應用程式可以輕鬆移植。
注意
ConfigMap 不提供機密性或加密。如果您要儲存的資料是機密的,請使用密鑰而不是 ConfigMap,或使用其他(第三方)工具來保護您的資料隱私。動機
使用 ConfigMap 將組態資料與應用程式程式碼分開設定。
例如,假設您正在開發一個應用程式,您可以在自己的電腦上(用於開發)和雲端中(用於處理真實流量)執行該應用程式。您編寫程式碼以在名為 DATABASE_HOST
的環境變數中尋找。在本機,您將該變數設定為 localhost
。在雲端中,您將其設定為參照 Kubernetes 服務,該服務將資料庫元件公開給您的叢集。這可讓您擷取在雲端中執行的容器映像檔,並在本機偵錯完全相同的程式碼(如果需要)。
注意
ConfigMap 並非設計用於保存大量資料。ConfigMap 中儲存的資料不能超過 1 MiB。如果您需要儲存大於此限制的設定,您可能需要考慮掛載磁碟區或使用單獨的資料庫或檔案服務。ConfigMap 物件
ConfigMap 是一個API 物件,可讓您儲存組態以供其他物件使用。與大多數具有 spec
的 Kubernetes 物件不同,ConfigMap 具有 data
和 binaryData
欄位。這些欄位接受鍵值組作為其值。data
欄位和 binaryData
都是可選的。data
欄位旨在包含 UTF-8 字串,而 binaryData
欄位旨在包含二進位資料作為 base64 編碼的字串。
ConfigMap 的名稱必須是有效的DNS 子網域名稱。
data
或 binaryData
欄位下的每個鍵都必須由字母數字字元、-
、_
或 .
組成。儲存在 data
中的鍵不得與 binaryData
欄位中的鍵重疊。
從 v1.19 開始,您可以將 immutable
欄位新增至 ConfigMap 定義,以建立不可變的 ConfigMap。
ConfigMap 和 Pod
您可以編寫 Pod spec
,該 spec
參照 ConfigMap 並根據 ConfigMap 中的資料設定該 Pod 中的容器。Pod 和 ConfigMap 必須在相同的命名空間中。
以下是一個 ConfigMap 範例,其中包含一些具有單一值的鍵,以及其他值看起來像組態格式片段的鍵。
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# property-like keys; each key maps to a simple value
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# file-like keys
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
您可以使用四種不同的方式,利用 ConfigMap 來設定 Pod 裡面的容器
- 在容器命令和引數中
- 容器的環境變數
- 在唯讀卷中新增檔案,供應用程式讀取
- 撰寫程式碼在 Pod 內執行,使用 Kubernetes API 讀取 ConfigMap
這些不同的方法適用於對所消耗資料進行不同方式的建模。對於前三種方法,kubelet 會在啟動 Pod 的容器時使用來自 ConfigMap 的資料。
第四種方法表示您必須撰寫程式碼來讀取 ConfigMap 及其資料。但是,由於您直接使用 Kubernetes API,您的應用程式可以訂閱以在 ConfigMap 變更時取得更新,並在發生變更時做出反應。透過直接存取 Kubernetes API,此技術也讓您可以存取不同命名空間中的 ConfigMap。
以下範例 Pod 使用來自 game-demo
的值來設定 Pod
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo-pod
spec:
containers:
- name: demo
image: alpine
command: ["sleep", "3600"]
env:
# Define the environment variable
- name: PLAYER_INITIAL_LIVES # Notice that the case is different here
# from the key name in the ConfigMap.
valueFrom:
configMapKeyRef:
name: game-demo # The ConfigMap this value comes from.
key: player_initial_lives # The key to fetch.
- name: UI_PROPERTIES_FILE_NAME
valueFrom:
configMapKeyRef:
name: game-demo
key: ui_properties_file_name
volumeMounts:
- name: config
mountPath: "/config"
readOnly: true
volumes:
# You set volumes at the Pod level, then mount them into containers inside that Pod
- name: config
configMap:
# Provide the name of the ConfigMap you want to mount.
name: game-demo
# An array of keys from the ConfigMap to create as files
items:
- key: "game.properties"
path: "game.properties"
- key: "user-interface.properties"
path: "user-interface.properties"
ConfigMap 不區分單行屬性值和多行檔案式值。重要的是 Pod 和其他物件如何使用這些值。
在此範例中,定義一個卷並將其掛載到 demo
容器中作為 /config
,會建立兩個檔案,/config/game.properties
和 /config/user-interface.properties
,即使 ConfigMap 中有四個鍵也是如此。這是因為 Pod 定義在 volumes
區段中指定了 items
陣列。如果您完全省略 items
陣列,則 ConfigMap 中的每個鍵都會變成一個檔案,其名稱與鍵相同,並且您會得到 4 個檔案。
使用 ConfigMap
ConfigMap 可以作為資料卷掛載。ConfigMap 也可以供系統的其他部分使用,而無需直接暴露給 Pod。例如,ConfigMap 可以保存系統其他部分應該用於組態的資料。
使用 ConfigMap 最常見的方式是設定在相同命名空間中 Pod 內執行的容器設定。您也可以單獨使用 ConfigMap。
例如,您可能會遇到根據 ConfigMap 調整其行為的附加元件或運算子。
將 ConfigMap 作為來自 Pod 的檔案使用
若要在 Pod 的卷中使用 ConfigMap
- 建立 ConfigMap 或使用現有的 ConfigMap。多個 Pod 可以參考相同的 ConfigMap。
- 修改您的 Pod 定義,在
.spec.volumes[]
下新增一個卷。為卷命名任何名稱,並將.spec.volumes[].configMap.name
欄位設定為參考您的 ConfigMap 物件。 - 為每個需要 ConfigMap 的容器新增
.spec.containers[].volumeMounts[]
。指定.spec.containers[].volumeMounts[].readOnly = true
和.spec.containers[].volumeMounts[].mountPath
為您想要 ConfigMap 出現的未使用目錄名稱。 - 修改您的映像檔或命令列,以便程式在該目錄中尋找檔案。ConfigMap
data
對映中的每個鍵都會變成mountPath
下的檔案名稱。
這是將 ConfigMap 掛載到卷中的 Pod 範例
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: myconfigmap
您想要使用的每個 ConfigMap 都需要在 .spec.volumes
中引用。
如果 Pod 中有多個容器,則每個容器都需要自己的 volumeMounts
區塊,但每個 ConfigMap 只需要一個 .spec.volumes
。
已掛載的 ConfigMap 會自動更新
當目前在卷中使用的 ConfigMap 更新時,投影鍵最終也會更新。kubelet 會在每次定期同步時檢查掛載的 ConfigMap 是否為最新狀態。但是,kubelet 使用其本機快取來取得 ConfigMap 的目前值。快取的類型可以使用 KubeletConfiguration 結構中的 configMapAndSecretChangeDetectionStrategy
欄位來設定。ConfigMap 可以透過監看 (預設)、基於 ttl 或將所有請求直接重新導向到 API 伺服器來傳播。因此,從 ConfigMap 更新到新鍵投影到 Pod 的時刻之間的總延遲可能長達 kubelet 同步週期 + 快取傳播延遲,其中快取傳播延遲取決於所選的快取類型 (它分別等於監看傳播延遲、快取的 ttl 或零)。
作為環境變數使用的 ConfigMap 不會自動更新,並且需要重新啟動 Pod。
注意
使用 ConfigMap 作為 子路徑 卷掛載的容器將不會收到 ConfigMap 更新。將 Configmap 作為環境變數使用
若要在 Pod 的環境變數中使用 Configmap
- 對於 Pod 規範中的每個容器,為您想要使用的每個 Configmap 鍵新增一個環境變數到
env[].valueFrom.configMapKeyRef
欄位。 - 修改您的映像檔和/或命令列,以便程式在指定的環境變數中尋找值。
以下範例說明如何將 ConfigMap 定義為 Pod 環境變數
以下 ConfigMap (myconfigmap.yaml) 儲存兩個屬性:username 和 access_level
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
username: k8s-admin
access_level: "1"
以下命令將建立 ConfigMap 物件
kubectl apply -f myconfigmap.yaml
以下 Pod 將 ConfigMap 的內容作為環境變數使用
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: app
command: ["/bin/sh", "-c", "printenv"]
image: busybox:latest
envFrom:
- configMapRef:
name: myconfigmap
envFrom
欄位指示 Kubernetes 從巢狀於其中的來源建立環境變數。內部的 configMapRef
透過名稱引用 ConfigMap,並選取其所有鍵值對。將 Pod 新增到您的叢集,然後檢索其日誌以查看來自 printenv 命令的輸出。這應該確認 ConfigMap 中的兩個鍵值對已設定為環境變數
kubectl apply -f env-configmap.yaml
kubectl logs pod/ env-configmap
輸出類似於此
...
username: "k8s-admin"
access_level: "1"
...
有時 Pod 不需要存取 ConfigMap 中的所有值。例如,您可能有另一個 Pod 僅使用 ConfigMap 中的 username 值。對於此使用案例,您可以使用 env.valueFrom
語法,讓您可以選取 ConfigMap 中的個別鍵。環境變數的名稱也可以與 ConfigMap 中的鍵不同。例如
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: CONFIGMAP_USERNAME
valueFrom:
configMapKeyRef:
name: myconfigmap
key: username
在從此資訊清單建立的 Pod 中,您會看到環境變數 CONFIGMAP_USERNAME
設定為 ConfigMap 中 username
值的值。ConfigMap 資料中的其他鍵不會複製到環境中。
請務必注意,Pod 中環境變數名稱允許的字元範圍是受限制的。如果任何鍵不符合規則,則這些鍵將無法供您的容器使用,但允許 Pod 啟動。
不可變的 ConfigMap
Kubernetes v1.21 [stable]
Kubernetes 功能不可變的密鑰和 ConfigMap 提供了一個選項,可將個別的密鑰和 ConfigMap 設定為不可變的。對於廣泛使用 ConfigMap 的叢集 (至少數萬個獨特的 ConfigMap 到 Pod 掛載),防止變更其資料具有以下優點
- 保護您免於意外 (或不想要的) 更新,這些更新可能會導致應用程式中斷
- 透過關閉標記為不可變的 ConfigMap 的監看,顯著降低 kube-apiserver 的負載,從而提高叢集的效能。
您可以透過將 immutable
欄位設定為 true
來建立不可變的 ConfigMap。例如
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
一旦 ConfigMap 標記為不可變,就無法還原此變更,也無法變更 data
或 binaryData
欄位的內容。您只能刪除並重新建立 ConfigMap。由於現有的 Pod 維護指向已刪除 ConfigMap 的掛載點,因此建議重新建立這些 Pod。
下一步
- 閱讀關於密鑰 (Secrets)。
- 閱讀設定 Pod 以使用 ConfigMap。
- 閱讀關於變更 ConfigMap (或任何其他 Kubernetes 物件)
- 閱讀 The Twelve-Factor App 以了解將程式碼與組態分離的動機。