我正在学习k8s,并且正在努力编写Helm图表以生成用于我正在逐步建立的生态系统的应用程序的配置文件。我遇到了一个有趣的问题,我需要生成所有节点通用的配置,以及每个节点唯一的配置。知道我会怎么做吗?
从我的values.xml文件中:
# number of nodes / replicas
nodeCount: 5
replicaCount: 3
所有节点上的公共配置称为node_map.xml:
<default>
<node>
<replica>
<host>wild-wallaby-0</host>
<port>8000</port>
</replica>
<replica>
<host>scary-rapids-1</host>
<port>8000</port>
</replica>
</node>
<node>
<replica>
<host>wild-wallaby-1</host>
<port>8000</port>
</replica>
<replica>
<host>scary-rapids-2</host>
<port>8000</port>
</replica>
</node>
<node>
<replica>
<host>wild-wallaby-2</host>
<port>8000</port>
</replica>
<replica>
<host>scary-rapids-0</host>
<port>8000</port>
</replica>
</node>
</default>
上面的代码很容易生成,并且可以在作为单个容器的每个Pod中进行此配置,但是现在每个Pod还需要编写一个附加的配置文件,以使该Pod知道该实例是什么节点和副本,称为instance.xml。请注意,该文件不必称为instance.xml。只要我知道要在启动命令中包含的名称,我就可以灵活地指向并加载任何命名的文件。
例如...
两个实例将在节点wild-wallaby-0,节点0副本1和节点0副本2上运行。每个实例将需要这样生成的配置文件:
初审...
<!-- node 0 replica 1 instance.xml -->
<id>
<node>0</node>
<replica>1</replica>
</id>
还有第二个实例...
<!-- node 0 replica 2 instance.xml -->
<id>
<node>0</node>
<replica>2</replica>
</id>
这当然可以遵循一些约定,这取决于我的值文件中定义的节点和副本的数量。虽然生成所有节点通用的文件很容易,但是我不清楚如何从instance.xml文件的舵图为每个节点生成自定义配置文件。
有什么想法或建议吗?
答案 0 :(得分:1)
您可以将其部署为StatefulSet,并在Pod的主要任务真正启动之前使用initContainers:
创建配置文件。
Kubernetes文档的a fairly detailed of example of this面向复制的MySQL集群,但是具有相同的基本设置:有一个主节点和一些副本,每个副本都需要知道自己的ID,并且配置文件是在主数据库和副本数据库上有所不同。
您可以使用的重要细节似乎是:容器的hostname
(如在shell命令中一样)为statefulsetname-123
,其中数字是连续的,并且可以保证各个容器可以启动为了。 a `statefulset.kubernetes.io/pod-name' label中有相同的详细信息,您可以通过downward API进行检索。
我可能会创建一个ConfigMap,例如:
version: v1
kind: ConfigMap
metadata:
name: config-templates
data:
config.xml.tmpl: >-
<id>
<node>NODE</node>
<replica>REPLICA</replica>
</id>
然后我的StatefulSet规范可能部分如下:
version: apps/v1
kind: StatefulSet
...
spec:
...
template:
spec:
volumes:
- name: config
emptyDir: {}
- name: templates
configMap:
name: config-templates
initContainers:
- name: configfiles
image: ubuntu:16.04
command:
- sh
- -c
- |
POD_NUMBER=$(hostname | sed 's/.*-//')
NODE=$(( $POD_NUMBER / 5 ))
REPLICA=$(( $POD_NUMBER % 5 ))
sed -e "s/NODE/$NODE/g" -e "s/REPLICA/$REPLICA/g" \
/templates/config.xml.tmpl > /config/config.xml
volumeMounts:
- name: templates
mountPath: /templates
- name: config
mountPath: /config
containers:
- name: ...
...
volumeMounts:
- name: config
mountPath: /opt/myapp/etc/config
在该设置中,您要求Kubernetes创建一个在容器之间共享的空临时卷(config
),并使配置映射也可作为卷使用。 init容器提取顺序的pod ID,将其拆分为两个数字,然后将实际的配置文件写入临时卷。然后,主容器将共享的config目录安装到它希望其配置文件位于的任何位置。
答案 1 :(得分:0)
https://github.com/spoditor/spoditor 旨在用 StatefulSet 解决这个问题。它允许您将专用的 configmap
或 secret
挂载到 StatefulSet 中的单个 Pod。
本质上,它在 PodSpec
模板上使用自定义注释,例如:
annotations:
spoditor.io/mount-volume: |
{
"volumes": [
{
"name": "my-volume",
"secret": {
"secretName": "my-secret"
}
}
],
"containers": [
{
"name": "nginx",
"volumeMounts": [
{
"name": "my-volume",
"mountPath": "/etc/secrets/my-volume"
}
]
}
]
}
现在,StatefulSet 的每个 Pod 中的 nginx
容器将尝试以 my-secret-{pod ordinal}
的模式挂载自己的专用密钥。
您只需要确保 my-secret-0
、my-secret-1
等存在于 StatefulSet 的同一命名空间中。
在项目文档中有更高级的注解用法。