ConfigMaps

ConfigMap 是一個 API 物件,用於以鍵值組形式儲存非機密資料。Pod 可以將 ConfigMap 作為環境變數、命令列引數或組態檔在磁碟區中使用。

ConfigMap 允許您將環境特定的組態與容器映像檔解耦,以便您的應用程式可以輕鬆移植。

動機

使用 ConfigMap 將組態資料與應用程式程式碼分開設定。

例如,假設您正在開發一個應用程式,您可以在自己的電腦上(用於開發)和雲端中(用於處理真實流量)執行該應用程式。您編寫程式碼以在名為 DATABASE_HOST 的環境變數中尋找。在本機,您將該變數設定為 localhost。在雲端中,您將其設定為參照 Kubernetes 服務,該服務將資料庫元件公開給您的叢集。這可讓您擷取在雲端中執行的容器映像檔,並在本機偵錯完全相同的程式碼(如果需要)。

ConfigMap 物件

ConfigMap 是一個API 物件,可讓您儲存組態以供其他物件使用。與大多數具有 spec 的 Kubernetes 物件不同,ConfigMap 具有 databinaryData 欄位。這些欄位接受鍵值組作為其值。data 欄位和 binaryData 都是可選的。data 欄位旨在包含 UTF-8 字串,而 binaryData 欄位旨在包含二進位資料作為 base64 編碼的字串。

ConfigMap 的名稱必須是有效的DNS 子網域名稱

databinaryData 欄位下的每個鍵都必須由字母數字字元、-_. 組成。儲存在 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 裡面的容器

  1. 在容器命令和引數中
  2. 容器的環境變數
  3. 在唯讀卷中新增檔案,供應用程式讀取
  4. 撰寫程式碼在 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

  1. 建立 ConfigMap 或使用現有的 ConfigMap。多個 Pod 可以參考相同的 ConfigMap。
  2. 修改您的 Pod 定義,在 .spec.volumes[] 下新增一個卷。為卷命名任何名稱,並將 .spec.volumes[].configMap.name 欄位設定為參考您的 ConfigMap 物件。
  3. 為每個需要 ConfigMap 的容器新增 .spec.containers[].volumeMounts[]。指定 .spec.containers[].volumeMounts[].readOnly = true.spec.containers[].volumeMounts[].mountPath 為您想要 ConfigMap 出現的未使用目錄名稱。
  4. 修改您的映像檔或命令列,以便程式在該目錄中尋找檔案。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 作為環境變數使用

若要在 Pod 的環境變數中使用 Configmap

  1. 對於 Pod 規範中的每個容器,為您想要使用的每個 Configmap 鍵新增一個環境變數到 env[].valueFrom.configMapKeyRef 欄位。
  2. 修改您的映像檔和/或命令列,以便程式在指定的環境變數中尋找值。

以下範例說明如何將 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 標記為不可變,就無法還原此變更,也無法變更 databinaryData 欄位的內容。您只能刪除並重新建立 ConfigMap。由於現有的 Pod 維護指向已刪除 ConfigMap 的掛載點,因此建議重新建立這些 Pod。

下一步

上次修改時間:2024 年 9 月 11 日下午 6:37 PST:在文件中新增 envFrom 詳細資訊 (#47709) (2ccaf064f8)