#bash #shell #docker #kubernetes #google-kubernetes-engine
#bash #оболочка #docker #kubernetes #google-kubernetes-engine
Вопрос:
Мне любопытно, как ConfigMap и Deployment работают в kubernetes.
Я хотел использовать значения в ConfigMap в качестве аргументов для моих модулей развертывания. Я пробовал это с разными изображениями и обнаружил различное поведение при передаче значения ConfigMap в качестве аргументов команды между контейнерами, которые используют sh
в качестве точки входа, и другими командами в качестве точки входа.
Вот пример конфигурации, который лучше иллюстрирует мой случай:
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-envs
data:
key: "value"
BUCKET_NAME: "gs://bucket-name/"
OUTPUT_PATH: "/data"
deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
spec:
template:
containers:
- name: firstContainer
image: busybox
command: ["sh"]
args:
- c
- |
echo $key
echo ${BUCKET_NAME}
echo $(OUTPUT_PATH)
envFrom:
- configMapRef:
name: app-envs
- name: secondContainer
image: someImage
args: [ "cmd", "${BUCKET_NAME}", "${OUTPUT_DATA}", "${key}" ]
envFrom:
- configMapRef:
name: app-envs
- name: thirdContainer
image: someImage
args: [ "cmd", "$(BUCKET_NAME)", "$(OUTPUT_DATA)", "$(key)" ]
envFrom:
- configMapRef:
name: app-envs
someImage
это образ docker, в качестве точки входа в который используется определенный скрипт bash, выводящий значения среды.
firstContainer
И thirdContainer
могут корректно выводить все значения ConfigMap, то есть все value
, gs://bucket-name/
и /data
принимаются в качестве входных аргументов.
Однако secondContainer
не удается правильно напечатать эти значения. Я попытался повторить полученные аргументы, и оказалось, что он получает:
${BUCKET_NAME}
,${OUTPUT_DATA}
и${key}
буквально в качестве входных аргументов вместо фактических значений из ConfigMaps.
Итак, после наблюдения за описанным выше поведением, вот мои вопросы:
-
Какова связь между deployment и ConfigMap? Существует ли какой-либо порядок, который определяет, как создаются ресурсы в модуле k8s pod / deployment (например, загружается ли ConfigMap первым, затем volumeMounts, а затем контейнер или какие-либо упорядочения)?
-
В чем разница между
${}
и$()
? Почему значения ConfigMap принимаются в виде литеральных строк при использовании${}
в контейнере, точка входа в который отличается отbash
orsh
?
Спасибо. Мы были бы признательны за вашу помощь.
Ответ №1:
Kubernetes напрямую понимает ссылки на переменные среды только в круглых скобках $(VAR)
; смотрите, например, Примечание в Определение команды и аргументов для контейнера.
args: [ "cmd", "$(BUCKET_NAME)", "$(OUTPUT_DATA)", "$(key)" ]
Сам Kubernetes знает, что такое переменные среды, и выполняет замену, поэтому контейнер запускается как cmd gs://bucket-name/ /data key
.
command: ["sh"]
args:
- c
- |
echo $key
echo ${BUCKET_NAME}
echo $(OUTPUT_PATH)
Kubernetes расширяется $(OUTPUT_PATH)
, но не понимает никакой другой формы фигурных скобок, поэтому остальные строки отправляются как есть. Однако, поскольку вы явно запускаете это через оболочку, оба $key
и ${BUCKET_NAME}
являются стандартными расширениями переменных оболочки, поэтому оболочка расширяет эти значения.
args: [ "cmd", "${BUCKET_NAME}", "${OUTPUT_DATA}", "${key}" ]
Kubernetes не расширяет объекты в фигурных скобках, и нет оболочки или чего-либо еще для расширения этих переменных, поэтому строки переменных (а не их содержимое) передаются как есть.