ConfigMap
ConfigMap 是一個 API 物件,用於以鍵值對的形式儲存非機密資料。Pod 可以將 ConfigMap 作為環境變數、命令列引數或 卷 中的配置檔案使用。
ConfigMap 允許你將特定環境的配置與你的容器映象解耦,從而使你的應用程式易於移植。
注意
ConfigMap 不提供保密或加密。如果你想要儲存的資料是機密的,請使用 Secret 而不是 ConfigMap,或者使用額外的(第三方)工具來保護你的資料隱私。動機
使用 ConfigMap 將配置資料與應用程式程式碼分開設定。
例如,假設你正在開發一個應用程式,你可以在自己的計算機上執行(用於開發),也可以在雲端執行(處理實際流量)。你編寫的程式碼會查詢名為 DATABASE_HOST
的環境變數。在本地,你將該變數設定為 localhost
。在雲端,你將其設定為引用一個 Kubernetes Service,該服務將資料庫元件公開給你的叢集。這使得你可以在雲端獲取正在執行的容器映象,並在需要時在本地除錯完全相同的程式碼。
注意
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 開始,你可以向 ConfigMap 定義新增一個 immutable
欄位,以建立不可變 ConfigMap。
ConfigMaps 和 Pods
你可以編寫一個引用 ConfigMap 的 Pod spec
,並根據 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 個檔案。
使用 ConfigMaps
ConfigMaps 可以作為資料卷掛載。ConfigMaps 也可以由系統的其他部分使用,而無需直接暴露給 Pod。例如,ConfigMaps 可以儲存系統其他部分應用於配置的資料。
使用 ConfigMaps 最常見的方式是配置在同一名稱空間中的 Pod 中執行的容器的設定。你也可以單獨使用 ConfigMap。
例如,你可能會遇到外掛或操作員,它們根據 ConfigMap 調整其行為。
從 Pod 中將 ConfigMap 作為檔案使用
要在 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 可以透過 watch(預設)、基於 ttl 或透過將所有請求直接重定向到 API 伺服器進行傳播。因此,從 ConfigMap 更新到新鍵投影到 Pod 的總延遲可能與 kubelet 同步週期 + 快取傳播延遲一樣長,其中快取傳播延遲取決於所選的快取型別(它分別等於 watch 傳播延遲、快取的 ttl 或零)。
作為環境變數使用的 ConfigMaps 不會自動更新,需要重啟 Pod。
注意
使用 ConfigMap 作為 subPath 卷掛載的容器將不會收到 ConfigMap 更新。將 ConfigMap 用作環境變數
要在 Pod 中將 ConfigMap 用於環境變數:
- 對於 Pod 規範中的每個容器,為每個要使用的 ConfigMap 鍵將一個環境變數新增到
env[].valueFrom.configMapKeyRef
欄位。 - 修改你的映象和/或命令列,以便程式在指定的en環境變數中查詢值。
這是一個將 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 中的所有值。例如,你可能有一個只使用 ConfigMap 中的 username 值的其他 Pod。對於這種情況,你可以改用 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 特性“不可變 Secret 和 ConfigMap”提供了一個選項,可以將單個 Secret 和 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》,以瞭解將程式碼與配置分離的動機。