Kubernetes configmaps中的自动子目录?

时间:2018-02-22 21:17:23

标签: kubernetes yaml subdirectory

(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"
            }

那么 我们的选择是什么?

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

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

使用subPath:(与items: -key: -path:中使用volumes: configMap:基本相同),

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

所有这些方法都需要对deployment.yaml进行大规模且令人难以置信的冗长更改,泄露出不应该有任何理由知道的知识,使其变得可变且不断重新生成而不是静态,使滚动复杂化对部署的pod等的设置更新等等。它只是不好。所有这些只是为了映射一个目录,只是因为它包含子目录......

当然,这可以成为它支持的工作方式吗?我错过了什么?我该怎么办?

3 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

一些解决方法:

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

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

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

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

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

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