我是Kubernetes和Helm的新手 . 我来自一个普通的Docker / docker-compose世界 .
我有一些复杂的服务运行多个Docker容器,需要大量的配置参数和逻辑 . docker-ized服务在启动时需要许多不同的配置文件,密钥和命令行参数 . 我还需要一些运行时的配置逻辑(必须生成一些配置元素),它们只能在容器内部执行 .
我最终做的是编写一个shell脚本(用作 CMD
),它需要环境变量,定义默认值,将这些环境变量转换为命令参数和配置文件 .
这是我如何构建它的一个非工作示例,没有考虑Kubernetes和Helm .
Dockerfile
...
CMD [ "./bootstrap.sh" ]
bootstrap.sh (packaged in image)
# Define default values, if no environment variables provided on
# on "docker run"
export CONFIG_VALUE_A=${CONFIG_VALUE_A:="a"}
export CONFIG_VALUE_B=${CONFIG_VALUE_B:="b"}
export CONFIG_VALUE_C=${CONFIG_VALUE_C:="c"}
# write CONFIG_VALUE_A to file
echo ${CONFIG_VALUE_A} > ./some-config-file-a.cfg
ARGS="--config-file-a ./some-config-file-a.cfg --config-value-b ${CONFIG_VALUE_B} --config-value-c ${CONFIG_VALUE_C}"
exec ./my-app ${ARGS}
这样做的好处是使用环境变量,我有一个标准的配置界面,不需要处理配置文件的卷 .
现在,我正走进Helm的Kubernetes . Helm使用 values.yaml
有自己的参数概念 . 为了将它与我上面已有的结合起来,我只想将 values.yaml
中的值与这些环境变量进行映射 .
deployment.yaml
...
spec:
...
template:
...
spec:
containers:
- name: my-app
...
env:
- name: "CONFIG_VALUE_A"
value: {{ .Values.config.value_a }}
- name: "CONFIG_VALUE_B"
value: {{ .Values.config.value_b }}
- name: "CONFIG_VALUE_C"
value: {{ .Values.config.value_c }}
values.yaml
config:
value_a: a
value_b: b
value_c: c
但是,有三个配置层,我来回映射值(helm templates =>容器环境变量=>配置文件/ CLI参数)违反了DRY原则,并增加了很多可能在以后很难找到的拼写错误/错误的可能性 .
理想的情况下,
-
我只想在
deployment.yaml
中定义我的配置结构,在Helm的default.yaml
中定义一次我的默认值 -
我会将这些值直接传递给容器,让某种配置脚本构建命令行参数和配置文件,而不使用环境变量作为中间层
-
使用某种类型安全的配置格式
-
保持总行数尽可能低
-
保持配置文件可读,不要混淆不同的语言(即YAML文件中定义的JSON)
如何使用Kubernetes,Helm和Docker解决复杂的配置管理?
1 回答
在Kubernetes世界中,配置通常由ConfigMap管理,ConfigMap是配置的主要存储 .
在你的情况下,我认为你可以这样做(至少我会这样做,我会这样做):
使用类型ConfigMap在Helm中创建另一个模板,并为应用程序创建一个
.cfg
文件的结构 . Helm使用GoTemplate格式,因此很容易在那里创建任何结构,迭代等 .将所有默认值添加到
values.yaml
文件 .编辑
deployment.yaml
. 将.cfg
文件的挂载添加到容器中的路径,并将应用程序指向它 .使用带有值的附加文件(或几次),并在其中写入默认值的覆盖 .
就是这样了 . 我们有:
ConfigMap采用应用程序格式的静态配置,我们可以随时查看 .
只有一个地方我们可以编辑它 - 在我们的默认和覆盖yamls中 .
可读
key: value
YAML格式 .配置文件的所有逻辑生成和排序容器,因此我们不需要构建新版本只是为了更改选项的顺序 .