Как установить динамические значения с помощью файла Kubernetes yaml?

Например, файл yaml для развертывания:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
      spec:
        container:
          - name: guestbook
            image: {{Here want to read value from config file outside}}

Существует функция ConfigMap с Kubernetes, но они также записывают ключ/значение в файл yaml. Есть ли способ установить ключ для переменных среды?

Ответ 1

Я не думаю, что это возможно, чтобы установить изображение через переменную или карту конфигурации в Kubernetes. Но вы можете использовать, например, Helm, чтобы сделать развертывание более гибким и настраиваемым.

Ответ 2

Вы не можете сделать это автоматически, вам нужно использовать внешний скрипт для "компиляции" вашего шаблона или использовать helm, как предложено @Jakub.

Возможно, вы захотите использовать собственный скрипт bash, возможно, интегрированный с вашим конвейером CI.

Имея шаблонный файл deploy.yml.template именем deploy.yml.template очень похожий на тот, который вы предоставили, вы можете использовать что-то вроде этого:

#!/bin/bash

# sample value for your variables
MYVARVALUE="nginx:latest"

# read the yml template from a file and substitute the string 
# {{MYVARNAME}} with the value of the MYVARVALUE variable
template='cat "deploy.yml.template" | sed "s/{{MYVARNAME}}/$MYVARVALUE/g"'

# apply the yml with the substituted value
echo "$template" | kubectl apply -f -

Ответ 3

Одна линия:

cat app-deployment.yaml | sed "s/{{BITBUCKET_COMMIT}}/$BITBUCKET_COMMIT/g" | kubectl apply -f -

В ямле:

  ...
  containers:
  - name: ulisses
    image: niceuser/niceimage:{{BITBUCKET_COMMIT}}
  ...

Ответ 4

Мой подход:

tools/jinja2-cli.py:

#!/usr/bin/env python3
import os
import sys
from jinja2 import Environment, FileSystemLoader

sys.stdout.write(Environment(loader=FileSystemLoader('templates/')).from_string(sys.stdin.read()).render(env=os.environ) + "\n")

Сделать правило:

_GENFILES = $(basename $(TEMPLATES))
GENFILES = $(_GENFILES:templates/%=%)

$(GENFILES): %: templates/%.j2 $(MKFILES) tools/jinja2-cli.py .env
        env $$(cat .env | xargs) tools/jinja2-cli.py < $< > [email protected] || (rm -f [email protected]; false)

Внутри .j2 файла шаблона вы можете использовать любой дзиндзя синтаксис конструкции, например, {{env.GUEST}} будет заменено значением GUEST, определенной в .env

Так что ваши templates/deploy.yaml.j2 будут выглядеть так:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
      spec:
        container:
          - name: guestbook
            image: {{env.GUEST}}

Другой подход (используя только встроенные xargs bash и xargs) может быть

env $(cat .env | xargs) cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
      spec:
        container:
          - name: guestbook
            image: ${GUEST}
EOF

Ответ 5

Вы также можете использовать envsubst при развертывании.

например

cat $app/deployment.yaml | envsubst | kubectl apply ...

Он заменит все переменные в файле их значениями. Мы успешно используем этот подход в нашем CI при развертывании в нескольких средах, а также для внедрения CI_TAG и т.д. В развертывания.

Ответ 6

Я создаю скрипт с именем kubectl_create и использую его для запуска команды create. Он заменит любое значение в шаблоне, на которое ссылается переменная среды.

#!/bin/bash
set -e
eval "cat <<EOF
$(<$1)
EOF
" | kubectl create -f -

Например, если файл шаблона имеет:

apiVersion: v1
kind: Service

metadata:
  name: nginx-external
  labels:
    app: nginx

spec:
  loadBalancerIP: ${PUBLIC_IP}
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 443

  selector:
    app: nginx

Запустите kubectl_create nginx-service.yaml а затем переменная среды PUBLIC_IP будет подставлена перед выполнением фактической команды kubectl create.

Ответ 7

Я использую kubetpl

Он имеет три различных шаблона и поддерживает заморозку ConfigMap/Secret.

Ответ 8

Я создаю скрипт с именем kubectl_apply. Он загружает переменные из .env, заменяет $ {CUSTOMVAR} в yml и передает его команде kubectl

  #!/bin/bash
  set -a
  source .env
  set +a
  eval "cat <<EOF
  $(<$1)
  EOF
  " | kubectl apply -f -

Ответ 9

Шлем предназначен именно для таких вещей и многого другого. Он обрабатывает сложный набор ресурсов развертывания в виде группы и т.д.

Но если мы все еще ищем простую альтернативу, тогда как насчет использования муравья?

Если вы хотите изменить файл как часть процесса сборки или процесса тестирования, то вы можете использовать и задачу ant.

Используя ant, вы можете загрузить все значения среды как свойство или просто загрузить файл свойств, например:

<property environment="env" />
<property file="build.properties" />

Тогда у вас может быть цель, которая преобразует файлы шаблонов в нужный вам файл yaml.

<target name="generate_from_template">

    <!-- Copy task to replaces values and create new file -->
    <copy todir="${dest.dir}" verbose="true" overwrite="true" failonerror="true">

        <!-- List of files to be processed -->
        <fileset file="${source.dir}/xyz.template.yml" />

        <!-- Mapper to transform filename. Removes '.template' from the file
            name when copying the file to output directory -->
        <mapper type="regexp" from="(.*).template(.*)" to="\1\2" />

        <!-- Filter chain that replaces the template values with actual values 
            fetched from properties file -->
        <filterchain>
            <expandproperties />
        </filterchain>
    </copy>
</target>

Конечно, вы можете использовать набор fileset вместо file если вы хотите динамически изменять значения для нескольких файлов (вложенных или любых других)

Ваш файл шаблона xyz.template.yml должен выглядеть так:

apiVersion: v1
kind: Service
metadata:
  name: ${XYZ_RES_NAME}-ser
  labels:
    app: ${XYZ_RES_NAME}
    version: v1
spec:
  type: NodePort
  ports:
    - port: ${env.XYZ_RES_PORT}
      protocol: TCP
  selector:
    app: ${XYZ_RES_NAME}
    version: v1

env. свойство загружается из переменных окружения, а другое из файла свойств

Надеюсь, это помогло :)