【问题标题】:Automatic subdirectories in Kubernetes configmaps?Kubernetes configmaps 中的自动子目录?
【发布时间】:2018-08-02 21:19:15
【问题描述】:

(大约 2 年前提出了一个非常相似的问题,虽然它专门关于秘密,但我怀疑配置映射的故事有什么不同......但至少,我可以介绍用例以及为什么现有的解决方法对我们来说是不可行的。)

给定一个简单的、精简的deployment.yaml

apiVersion: apps/v1beta1
kind: Deployment
metadata: 
  name: example
spec:
  template: 
    spec:
      containers:
      - name: example
        volumeMounts:
        - name: vol
          mountPath: /app/Configuration
      volumes:
        - name: vol
          configMap:
            name: configs

和匹配的configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: configs
  labels:
    k8s-app: example
data:
    example1.json: |-
        {
            "key1": "value1"
        }

    example2.json: |-
        {
            "key2": "value2"
        }

configmap.yaml 中的键,无论它们是什么,都只是简单地创建为文件,无需修改 deployment.yaml 或具有除 mountPath 之外的任何细节。

问题在于实际结构有子文件夹来处理覆盖根目录的特定于区域的值:

Configuration \ example1.json
Configuration \ example2.json
Configuration \ us \ example1.json
Configuration \ us \ ca \ example2.json

对于可以想象到的许多不同国家和地区以及每个单独配置的模块,它们的数量和性质显然会有所不同。目的是为最终用户提供一个工具,允许他们设置和管理这些配置,这将在幕后自动生成 configmap.yaml 并在 kubernetes 中更新。

但是,除非有我还没有找到的技巧,否则这似乎超出了 kubernetes 的能力范围,在某些方面。

首先,没有语法允许指定作为目录的 configmap 键,也不能在键中包含子目录路径:

data:
    # one possible approach (currently complains that it doesn't validate '[-._a-zA-Z0-9]+')
    /us/example1.json: |-
        {
            "key1": "value1"
        }

    # another idea; this obviously results in 'invalid type for io.k8s.api.core.v1.ConfigMap.data: got "map", expected "string"'
    us:
        example2.json: |-
            {
                "key2": "value2"
            }

那么我们有哪些选择来实现这一目标?

好吧,我们可以使用 deployment.yaml 的 volumes: -configMap: 节点中的 items: -key: path: 方法将键映射到特定位置,

和/或在deployment.yaml的volumeMounts:节点中生成多个节点,

使用subPath:中的任何一个(这与在volumes: configMap:中使用items: -key: -path:基本相同),

或为每个子目录设置单独的配置映射,并将它们全部安装为不同的 volumes 在 deployment.yaml 中。

所有这些方法都需要对 deployment.yaml 进行大量且极其冗长的更改,泄露它不应该有任何理由知道的知识,使其可变并不断重新生成而不是静态的,从而使部署设置复杂化更新已部署的 Pod 等。等等。这只是不好。而这一切只是为了映射一个目录,仅仅因为它包含子目录......

这肯定不是它应该工作的方式吗?我错过了什么?我应该如何进行?

【问题讨论】:

    标签: kubernetes yaml subdirectory


    【解决方案1】:

    从“容器原生”的角度来看,拥有一个由应用程序在启动时处理以达到其规范配置的配置文件的大型文件系统树是一种反模式。最好有一个生成单个文件的工作流,该文件可以存储在 ConfigMap 中并以最终形式轻松检查。例如,参见 nginx 入口。

    但显然不是每个人都在重写他们的应用程序以更好地与 kubernetes 方法保持一致。在部署时将配置文件的完整目录树放入容器中的最简单方法是使用 initContainers 和 emptyDir 挂载。

    将配置文件树打包到一个容器中(有时称为“仅数据”容器),并让容器启动脚本将配置树复制到 emptyDir 挂载中。然后应用程序可以按预期使用树。

    【讨论】:

      【解决方案2】:

      根据您的配置树的规模,另一个可行的选择可能是模拟一个子树,例如,在配置映射内的文件“路径”中使用下划线而不是斜线。这将使您失去一般文件系统性能(如果您只是要读取配置,这永远不会成为问题)并迫使您重写一些应用程序代码(访问配置时文件模式遍历而不是目录遍历),但是应该以相当便宜的价格解决您的用例。

      【讨论】:

        【解决方案3】:

        一些解决方法:

        1. 拥有一个仅包含数据的数据容器...
        FROM scratch
        ... # copy data here
        

        然后将其添加为将卷安装在另一个容器上的 sidecar...

        1. 从配置创建一个 tar 球,将其转换为 configmap,安装在容器中并更改容器命令以在启动前解压缩配置...

        2. 用一些特殊字符而不是/ 重命名文件,例如us@example.json,并像开头一样使用脚本将它们改成mv

        所有这些都非常 hacky... 最好的方案是重构它们以在平面文件夹中使用并使用类似 kustomize 的东西创建它们:

        kustomize edit add configmap my-configmap --from-file='./*.json'
        

        【讨论】:

          猜你喜欢
          • 2019-02-02
          • 2020-05-14
          • 2018-11-21
          • 1970-01-01
          • 2020-11-22
          • 2020-06-02
          • 1970-01-01
          • 2020-03-09
          • 1970-01-01
          相关资源
          最近更新 更多