Передать уникальную конфигурацию в контейнер без дистрибутива
Я запускаю StatefulSet, где каждая реплика требует своей уникальной конфигурации. Для этого я сейчас использую конфигурацию с двумя контейнерами на под:
- Ан
initContainer
подготавливает конфигурацию и сохраняет ее на общий том - Основной контейнер использует конфигурацию, выводя содержимое общего тома и передавая его программе в виде флагов CLI.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: my-app
serviceName: my-app
template:
metadata:
labels:
app.kubernetes.io/name: my-app
spec:
initContainers:
- name: generate-config
image: myjqimage:latest
command: [ "/bin/sh" ]
args:
- -c
- |
set -eu -o pipefail
POD_INDEX="${HOSTNAME##*-}"
# A configuration is stored as a JSON array in a Secret
# E.g., [{"param1":"string1","param2":"string2"}]
echo "$MY_APP_CONFIG" | jq -rc --arg i "$POD_INDEX" '.[$i|tonumber-1].param1' > /config/param1
echo "$MY_APP_CONFIG" | jq -rc --arg i "$POD_INDEX" '.[$i|tonumber-1].param2' > /config/param2
env:
- name: MY_APP_CONFIG
valueFrom:
secretKeyRef:
name: my-app
key: config
volumeMounts:
- name: configs
mountPath: "/config"
containers:
- name: my-app
image: myapp:latest
command:
- /bin/sh
args:
- -c
- |
/myapp --param1 $(cat /config/param1) --param2 $(cat /config/param2)
volumeMounts:
- name: configs
mountPath: "/config"
volumes:
- name: configs
emptyDir:
medium: "Memory"
---
apiVersion: v1
kind: Secret
metadata:
name: my-app
namespace: default
labels:
app.kubernetes.io/name: my-app
type: Opaque
data:
config: W3sicGFyYW0xIjoic3RyaW5nMSIsInBhcmFtMiI6InN0cmluZzIifV0=
Теперь я хочу переключиться на distroless для своего основного контейнера. Образы Distroless содержат только необходимые зависимости для запуска программы (в моем случае это glibc). И отсутствует оболочка. Итак, если раньше я мог выполнитьcat
и вывести содержимое файла. Теперь я немного застрял.
Теперь вместо того, чтобы читать содержимое из файла, я должен передать флаги CLI, определенные как переменные среды. Что-то вроде этого:
containers:
- name: my-app
image: myapp:latest
command: ["/myapp", "--param1", "$(PARAM1)", "--param2", "$(PARAM2)"]
env:
- name: PARAM1
value: somevalue1
- name: PARAM2
value: somevalue2
Опять же, каждый Pod в StatefulSet должен иметь уникальную конфигурацию. то есть,PARAM1
иPARAM2
должен быть уникальным для всех подов в StatefulSet. Как мне этого добиться?
Варианты, которые я рассматривал:
- Использование контейнеров отладки -- новая функция K8s. Каким-то образом используйте его для редактирования конфигурации работающего контейнера во время выполнения и внедрения необходимых переменных. Но эта функция только что стала бета-версией версии 1.23. И я не хочу изменять свой StatefulSet во время выполнения, поскольку я использую подход GitOps для хранения конфигурации в Git. Это, вероятно, вызовет непрерывный дрейф конфигурации
- Использование задания для изменения конфигурации во время выполнения. Опять же, выглядит очень некрасиво и нарушает принцип GitOps
- С использованием
shareProcessNamespace
. Не уверен, что это может помочь, но, возможно, я смогу каким-то образом ввести переменные среды из initContainer.
Ограничения:
- Приложение поддерживает только конфигурацию, предоставленную с помощью флагов CLI. Нет переменных окружения, нет загрузки конфига из файла