首页 > 解决方案 > 如何保存容器的任何更改?

问题描述

如果我有一个 ubuntu 容器,并且我 ssh 到它并在容器被销毁后创建一个文件,或者我重新启动容器,则新文件被销毁,因为 kubernetes 加载了不包含我的更改的 ubuntu 映像。我的问题是我应该怎么做才能保存任何更改?我知道这是可以做到的,因为一些云提供商会这样做。

例如:

ssh ubuntu@POD_IP
mkdir new_file
ls 
  new_file
reboot

重启后我有

ssh ubuntu@POD_IP
ls 

ls什么都不显示

但我想保存我当前的状态。我想自动完成。

如果我使用 docker commit 我无法控制我的图像,因为它会生成数百个图像。因为我应该通过每次更改来制作图像。

如果我想使用存储,我应该挂载 /。但是 kubernetes 不允许我挂载 /. 它给了我这个错误

错误:来自守护程序的错误响应:无效的卷规范:'/var/lib/kubelet/pods/26c39eeb-85d7-11e9-933c-7c8bca006fec/volumes/kubernetes.io~rbd/pvc-d66d9039-853d-11e9-8aa3-7c8bca006fec :/':类型“绑定”的无效装载配置:无效规范:目标不能是“/”

标签: dockerkubernetescloud

解决方案


Docker 和 Kubernetes 不是这样工作的。永远不要跑docker commit。通常你在容器/pod 中几乎不需要 ssh 守护进程,你需要做一些特殊的工作来让 sshd 和主进程都运行(以及额外的工作来让 sshd 实际上是安全的);如果您删除这些容器,您的容器会更简单、更安全。

通常的过程涉及一种称为不可变基础设施的技术。您永远不会更改现有容器中的代码;相反,您更改配方以构建容器,并告诉集群管理器您想要更新,它会从头开始拆除并重建所有内容。要更改在 Kubernetes pod 中运行的应用程序,您通常:

  1. 在本地进行和测试您的代码更改,完全不涉及 Docker 或 Kubernetes。
  2. docker build包含您的代码更改的新图像。它应该有一个唯一的标签,通常是日期戳或源代码控制提交 ID。
  3. (可选但推荐)docker run本地映像并运行集成测试。
  4. docker push图像到注册表。
  5. 更改 Kubernetes 部署规范中的镜像标签和kubectl apply(或helm upgrade)它。

通常你会有一个自动化的持续集成系统执行步骤 2-4,而持续部署系统执行最后一步;您只需要提交并推送您测试过的更改。

请注意,当您docker run在步骤 3 中本地镜像时,您运行的镜像与生产 Kubernetes 系统将运行的镜像完全相同。抵制将本地源代码树挂载到其中并尝试在那里进行开发的诱惑!如果此时测试失败,请将其简化为最简单的失败案例,为其编写单元测试,并在本地树中修复它。重建图像不应该特别昂贵。

您的问题暗示了未修改的ubuntu图像。FROM除了一些非常早期的“hello world”类型实验之外,除了Dockerfile 行之外,几乎没有理由在任何地方使用它。如果您还没有,您应该阅读官方 Docker 教程,了解构建和运行自定义镜像,该教程适用于任何集群系统。(如果您已经将 Kubernetes 作为编排器,请跳过后面所有涵盖 Docker Swarm 的教程。)


推荐阅读