Kubernetes配置图中的自动子目录?

Gra*_*ank 10 yaml subdirectory kubernetes

(大约2年前提出了一个非常类似的问题,尽管它专门涉及秘密,但我怀疑这个故事对于configmaps是否有所不同...但是至少,我可以介绍用例以及为什么现有解决方法不存在对我们而言可行)。

给出一个简单的简化方法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
Run Code Online (Sandbox Code Playgroud)

和匹配configmap.yaml

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

    example2.json: |-
        {
            "key2": "value2"
        }
Run Code Online (Sandbox Code Playgroud)

configmap.yaml不管它们中的键是什么,它们都可以简单地创建为文件,而无需deployment.yaml修改或具有mountPath以外的任何其他细节。

问题在于实际结构具有子文件夹来处理特定于区域的值,这些值会覆盖根值:

Configuration \ example1.json
Configuration \ example2.json
Configuration \ us \ example1.json
Configuration \ us \ ca \ example2.json
Run Code Online (Sandbox Code Playgroud)

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

但是,除非有一种我尚未发现的技巧,否则它似乎在多种方面超出了Kubernetes的能力。

首先,没有一种语法可以指定目录的configmap关键字,也不能在关键字中包含子目录路径:

Configuration \ example1.json
Configuration \ example2.json
Configuration \ us \ example1.json
Configuration \ us \ ca \ example2.json
Run Code Online (Sandbox Code Playgroud)

那么我们什么选择来实现这一目标?

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

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

使用任一subPath:(其基本上与使用相同items: -key: -path:volumes: configMap:),

或每个子目录的单独的单独的configmap,并将它们挂载为volumesDeployment.yaml中的不同文件。

所有这些方法都需要对Deployment.yaml进行大量且令人难以置信的冗长更改,从而泄漏出本来没有理由知道的知识,使其变得可变并不断重新生成,而不是静态生成,从而使部署更新更加复杂。豆荚等,等等。这只是不好。所有这些只是映射了一个目录,仅因为它包含子目录...

当然,这不是它的工作方式吗?我想念什么?我应该如何进行?

Par*_*udy 5

{ filename_sha: file_contents }使用 Helm,通过构建的配置映射.Files.Glob,然后挂载每个此类文件,可以非常轻松地解决 OP 的问题。它适用于二进制数据、有趣的文件名和深度嵌套的目录,至少到目前为止是这样。

如果你有很多文件,这效率不高,但如果文件不是太多,这里的简单性可能会证明这种罪恶是合理的。

以下是我的代码摘录,它复制了files/**Helm 图表中的所有内容并将其安装/mnt/**在容器中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-files
data:
# map all files under the files/ to a shasummed key pointing at the contents
{{ range $path, $bytes := .Files.Glob "files/**" }}
{{ sha256sum $path | nindent 2 }}: {{ $.Files.Get $path | quote }}
{{ end }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-container
spec:
  # ... (omitted for brevity)
  template:
    spec:
      containers:
        - name: amp-server
          # ... (omitted for brevity)
          volumeMounts:

            # now mount each such file, trimming the 'files/' prefix here
            {{ range $path, $bytes := .Files.Glob "files/**" }}
            - name: config-files-multipart
              mountPath: {{ printf "/mnt/%s" (trimPrefix "files/" $path) | quote }}
              subPath: {{ sha256sum $path | quote }}
            {{ end }}

      volumes:
        - name: config-files-multipart
          configMap:
            name: my-files
Run Code Online (Sandbox Code Playgroud)


Jon*_*ton 4

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

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

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