【问题标题】:How to generate unique config files for multiple hosts?如何为多个主机生成唯一的配置文件?
【发布时间】:2018-10-31 23:05:23
【问题描述】:

我正在学习 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 文件的 helm 图表为每个节点生成自定义配置文件。

有什么想法或建议吗?

【问题讨论】:

    标签: kubernetes kubernetes-helm go-templates


    【解决方案1】:

    您可以将其部署为 StatefulSet,并使用 initContainers: 在 pod 的主要任务真正启动之前创建配置文件。

    Kubernetes 文档中有 a fairly detailed of example of this 围绕一个复制的 MySQL 集群,但基本设置相同:有一个主节点和一些副本,每个都需要知道自己的 ID,配置文件在主和副本。

    看起来您可以使用的重要细节是 pod 的 hostname(如在 shell 命令中)是 statefulsetname-123,其中数字是连续的,并且各个 pod 保证按顺序启动。 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,将其拆分为两个数字,并将实际的配置文件写入临时卷。然后主容器将共享配置目录挂载到它期望其配置文件所在的任何位置。

    【讨论】:

      【解决方案2】:

      https://github.com/spoditor/spoditor 旨在通过 StatefulSet 解决这个问题。它允许您将专用的 configmapsecret 挂载到 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-0my-secret-1 等存在于 StatefulSet 的同一命名空间中。

      项目文档中有更高级的注解用法。

      【讨论】:

        猜你喜欢
        • 2018-02-11
        • 1970-01-01
        • 2016-12-03
        • 2023-03-16
        • 2020-06-17
        • 2012-01-27
        • 1970-01-01
        • 1970-01-01
        • 2020-09-09
        相关资源
        最近更新 更多