ConfigMap — це обʼєкт API, призначений для зберігання неконфіденційних даних у вигляді пар ключ-значення. Podʼи можуть використовувати ConfigMap як змінні середовища, аргументи командного рядка чи файли конфігурації у томі.
ConfigMap дозволяє відділити конфігурацію, специфічну для середовища, від образів контейнерів, щоб ваші застосунки були легко переносимими.
Використовуйте ConfigMap для визначення конфігураційних даних окремо від коду застосунку.
Наприклад, уявіть, що ви розробляєте застосунок, який ви можете запускати на власному компʼютері (для розробки) і в хмарі (для обробки реального трафіку). Ви пишете код, який читає змінну середовища з назвою DATABASE_HOST. Локально ви встановлюєте цю змінну в значення localhost. У хмарі ви встановлюєте її так, щоб вона посилалася на Service, який надає доступ до компонента бази даних вашому кластеру. Це дозволяє вам отримати образ контейнера, який працює в хмарі, і у разі потреби налагоджувати той самий код локально.
ConfigMap — це обʼєкт API, який дозволяє зберігати конфігураційні дані для використання іншими обʼєктами. На відміну від більшості обʼєктів Kubernetes, у яких є spec, ConfigMap має поля data та binaryData. Ці поля приймають пари ключ-значення як свої значення. Обидва поля data і binaryData є необовʼязковими. Поле data призначене для зберігання рядків UTF-8, тоді як поле binaryData призначене для зберігання бінарних даних у вигляді рядків, закодованих у base64.
Назва ConfigMap повинна бути дійсним піддоменом DNS.
Кожний ключ у полі data або binaryData повинен складатися з буквено-цифрових символів, -, _ або .. Ключі, збережені в data, не повинні перетинатися з ключами у полі binaryData.
Починаючи з версії v1.19, ви можете додати поле immutable до визначення ConfigMap, щоб створити незмінний ConfigMap.
Ви можете написати spec Podʼа, який посилається на ConfigMap і конфігурує контейнер(и) в цьому Podʼі на основі даних з ConfigMap. Pod і ConfigMap повинні бути в тому самому просторі імен.
Ось приклад ConfigMap, який має деякі ключі з окремими значеннями, а також інші ключі, де значення виглядає як фрагмент формату конфігурації.
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# ключі у вигляді властивостей; кожен ключ зіставляється з простим значенням
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# ключі у формі файлів
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
Є чотири різних способи використання ConfigMap для конфігурації контейнера всередині Podʼа:
Ці різні методи підходять для різних способів моделювання даних, які використовуються. Для перших трьох методів kubelet використовує дані з ConfigMap під час запуску контейнера(ів) для Podʼа.
Четвертий метод означає, що вам потрібно написати код для читання ConfigMap та його даних. Однак, оскільки ви використовуєте прямий доступ до API Kubernetes, ваш застосунок може підписатися на отримання оновлень, коли змінюється ConfigMap, і реагувати на це. Завдяки прямому доступу до API Kubernetes цей підхід також дозволяє вам отримувати доступ до 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ʼа містить масив items в розділі volumes. Якщо ви взагалі опустите масив items, кожен ключ у ConfigMap стане файлом із такою самою назвою, що й ключ, і ви отримаєте 4 файли.
ConfigMap можуть бути змонтовані як томи даних. ConfigMap також можуть бути використані іншими частинами системи без безпосереднього надання Podʼу. Наприклад, ConfigMap можуть містити дані, які повинні використовуватися іншими частинами системи для конфігурації.
Найпоширеніший спосіб використання ConfigMap — це налаштування контейнерів, які працюють у Podʼі в тому самому просторі імен. Ви також можете використовувати ConfigMap окремо.
Наприклад, ви можете зустріти надбудови або оператори, які налаштовують свою поведінку на основі ConfigMap.
Щоб використовувати ConfigMap в томі в Podʼі:
.spec.volumes[]. Дайте тому будь-яку назву та встановіть поле .spec.volumes[].configMap.name для посилання на ваш обʼєкт ConfigMap..spec.containers[].volumeMounts[] до кожного контейнера, який потребує ConfigMap. Вкажіть .spec.containers[].volumeMounts[].readOnly = true та задайте в .spec.containers[].volumeMounts[].mountPath назву невикористаної теки, де ви хочете, щоб зʼявився ConfigMap.data ConfigMap стає імʼям файлу в mountPath.Ось приклад Podʼа, який монтує ConfigMap в том:
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, але потрібно лише одне поле .spec.volumes на ConfigMap.
Коли ConfigMap, що наразі використовується в томі, оновлюється, спроєцьовані ключі згодом також оновлюються. Kubelet перевіряє, чи змонтований ConfigMap є актуальним під час кожної періодичної синхронізації. Однак kubelet використовує свій локальний кеш для отримання поточного значення ConfigMap. Тип кешу налаштовується за допомогою поля configMapAndSecretChangeDetectionStrategy в структурі KubeletConfiguration. ConfigMap можна поширити за допомогою watch (типово), на основі ttl або шляхом перенаправлення всіх запитів безпосередньо до API-сервера. Отже, загальна затримка від моменту оновлення ConfigMap до моменту, коли нові ключі буде спроєцьовано в Pod, може дорівнювати періоду синхронізації kubelet + затримці поширення кешу, де затримка поширення кешу залежить від обраного типу кешу (вона дорівнює затримці поширення watch, ttl кешу або нулю відповідно).
ConfigMap, що використовуються як змінні середовища, не оновлюються автоматично і потребують перезапуску Podʼа.
Щоб використовувати ConfigMap у змінних середовища в Podʼі:
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, який використовує тільки значення username з ConfigMap. Для цього випадку можна використовувати синтаксис 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 встановлена на значення username з ConfigMap. Інші ключі з даних ConfigMap не будуть скопійовані у середовище.
Важливо зауважити, що набір символів, дозволених для назв змінних середовища в Podʼах, обмежений. Якщо будь-які ключі не відповідають правилам, ці ключі не будуть доступні вашому контейнеру, хоча Pod може бути запущений.
Функція Kubernetes Immutable Secrets та ConfigMaps надає можливість зробити окремі Secrets та ConfigMaps незмінними. Для кластерів, що інтенсивно використовують ConfigMap (принаймні десятки тисяч унікальних монтувань ConfigMap до Podʼів), запобігання змінам їх даних має такі переваги:
Ви можете створити незмінний ConfigMap, встановивши поле immutable в true. Наприклад:
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
Після того, як ConfigMap позначено як незмінний, відмінити цю зміну або змінити вміст поля data або binaryData неможливо. Ви можете лише видалити та створити ConfigMap знову. Оскільки поточні Podʼи підтримують точку монтування для видаленого ConfigMap, рекомендується створити заново ці Podʼи.