Какова связь между deployment и ConfigMap?

#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.

Итак, после наблюдения за описанным выше поведением, вот мои вопросы:

  1. Какова связь между deployment и ConfigMap? Существует ли какой-либо порядок, который определяет, как создаются ресурсы в модуле k8s pod / deployment (например, загружается ли ConfigMap первым, затем volumeMounts, а затем контейнер или какие-либо упорядочения)?

  2. В чем разница между ${} и $() ? Почему значения ConfigMap принимаются в виде литеральных строк при использовании ${} в контейнере, точка входа в который отличается от bash or sh ?

Спасибо. Мы были бы признательны за вашу помощь.

Ответ №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 не расширяет объекты в фигурных скобках, и нет оболочки или чего-либо еще для расширения этих переменных, поэтому строки переменных (а не их содержимое) передаются как есть.