Kubernetes 在现有目录上挂载卷,其中包含容器内的文件

Posted

技术标签:

【中文标题】Kubernetes 在现有目录上挂载卷,其中包含容器内的文件【英文标题】:Kubernetes mount volume on existing directory with files inside the container 【发布时间】:2020-01-27 10:17:02 【问题描述】:

我使用 1.11 版的 k8s 和 CephFS 作为存储。

我正在尝试将在 CephFS 上创建的目录挂载到 pod 中。为了达到同样的效果,我编写了以下卷和卷安装配置 在部署配置中

音量


  "name": "cephfs-0",
  "cephfs": 
    "monitors": [
      "10.0.1.165:6789",
      "10.0.1.103:6789",
      "10.0.1.222:6789"
    ],
    "user": "cfs",
    "secretRef": 
      "name": "ceph-secret"
    ,
    "readOnly": false,
    "path": "/cfs/data/conf"
  

体积安装


  "mountPath": "/opt/myapplication/conf",
  "name": "cephfs-0",
  "readOnly": false
 

Mount 工作正常。我可以看到 ceph 目录,即 /cfs/data/conf 已安装在 /opt/myapplication/conf 上,但以下是我的问题。

我的配置文件已经作为 docker 映像的一部分存在于 /opt/myapplication/conf 位置。当部署尝试挂载 ceph 卷时,/opt/myapplication/conf 位置的所有文件都会消失。我知道这是挂载操作的行为,但是有什么方法可以将容器中已经存在的文件保存在我正在挂载的卷上,以便其他挂载相同卷的 Pod 可以访问配置文件。即,已经存在于 /opt/myapplication/conf 位置的 pod 内的文件应该可以在 CephFS 上的 /cfs/data/conf 位置访问。

有可能吗?

我浏览了 docker 文档,它提到了

使用容器填充卷 如果你启动一个容器来创建一个新的卷,如上,并且容器在要挂载的目录中有文件或目录(如上面的 /app/),则目录的内容将被复制到卷中。然后容器挂载并使用该卷,其他使用该卷的容器也可以访问预填充的内容。

这符合我的要求,但是如何用 k8s 卷来实现呢?

【问题讨论】:

kubernetes.io/docs/concepts/configuration/configmap 会更适合这样的配置吗? 【参考方案1】:

不幸的是,Kubernetes 的卷系统与 Docker 的非常不同,所以这是不可能直接实现的。如果只有一个文件(或少量),您可以像这样使用 subPath 投影:

volumeMounts:
- name: cephfs-0
  mountPath: /opt/myapplication/conf/foo.conf
  subPath: foo.conf

对每个文件重复此操作。但是如果你有很多文件,或者它们可以变化,那么你必须在运行时处理这个或者使用模板工具。通常这意味着将它安装在其他地方并在您的主进程开始之前设置符号链接。

【讨论】:

有一种方法可以将主机文件共享到 pod kubernetes share a directory from your local system to kubernetes container @sngjuk 是的,这不是问题。这里的难点在于 Docker 具有使用容器映像中的内容初始化持久卷的功能。 Kubernetes 没有这个功能。 请注意,此选项至少使 Ruby 无法更新文件被视为目录:/application/config/initializers/clamby.rb:11:in `initialize': Is a directory @ rb_sysopen - /application/config/clamby.conf (Errno::EISDIR)【参考方案2】:

我还遇到了这个非常小众的问题,无法将文件夹安装到包含我构建图像中的内容的特定路径。这最终是空的。

但是我的解决方法是在 de dockerfile 中使用 ENTRYPOINT 来引用 shellscript,该脚本运行命令以初始化 DB 或对影响已挂载目标文件夹的文件执行某些操作。

所以似乎入口点在 kubernetes 挂载卷之后运行。

我确实尝试在入口点脚本中对路径进行符号链接,但没有成功。

【讨论】:

【参考方案3】:

我能够通过让我的ENTRYPOINT 成为一个 bash 脚本来解决这个问题,mv 我想要将我的配置文件安装到它们的正确位置。似乎发生了this device or resource is busy 错误,因为文件尚未挂载。

【讨论】:

以上是关于Kubernetes 在现有目录上挂载卷,其中包含容器内的文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kubernetes 中使用 Aws EBS 挂载 postgresql 卷

Kubernetes笔记

如何使用 Spring Boot 从 Kubernetes 卷挂载中读取密钥和值

如何在 kubernetes 中使用 windows 容器挂载卷?

Kubernetes-subPath的使用

使用 Jenkins 中的 Kubernetes 插件未进行卷挂载