Ответ 1
Я не думаю, что это возможно, чтобы установить изображение через переменную или карту конфигурации в Kubernetes. Но вы можете использовать, например, Helm, чтобы сделать развертывание более гибким и настраиваемым.
Например, файл 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. Есть ли способ установить ключ для переменных среды?
Я не думаю, что это возможно, чтобы установить изображение через переменную или карту конфигурации в Kubernetes. Но вы можете использовать, например, Helm, чтобы сделать развертывание более гибким и настраиваемым.
Вы не можете сделать это автоматически, вам нужно использовать внешний скрипт для "компиляции" вашего шаблона или использовать 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 -
Одна линия:
cat app-deployment.yaml | sed "s/{{BITBUCKET_COMMIT}}/$BITBUCKET_COMMIT/g" | kubectl apply -f -
В ямле:
...
containers:
- name: ulisses
image: niceuser/niceimage:{{BITBUCKET_COMMIT}}
...
Мой подход:
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
Вы также можете использовать envsubst
при развертывании.
например
cat $app/deployment.yaml | envsubst | kubectl apply ...
Он заменит все переменные в файле их значениями. Мы успешно используем этот подход в нашем CI при развертывании в нескольких средах, а также для внедрения CI_TAG и т.д. В развертывания.
Я создаю скрипт с именем 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.
Я использую kubetpl
Он имеет три различных шаблона и поддерживает заморозку ConfigMap/Secret.
Я создаю скрипт с именем kubectl_apply. Он загружает переменные из .env, заменяет $ {CUSTOMVAR} в yml и передает его команде kubectl
#!/bin/bash
set -a
source .env
set +a
eval "cat <<EOF
$(<$1)
EOF
" | kubectl apply -f -
Шлем предназначен именно для таких вещей и многого другого. Он обрабатывает сложный набор ресурсов развертывания в виде группы и т.д.
Но если мы все еще ищем простую альтернативу, тогда как насчет использования муравья?
Если вы хотите изменить файл как часть процесса сборки или процесса тестирования, то вы можете использовать и задачу 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.
свойство загружается из переменных окружения, а другое из файла свойств
Надеюсь, это помогло :)