如何更新kubernetes部署而不更新映像

时间:2018-05-11 19:03:12

标签: kubernetes

背景。

我们正在使用k8s 1.7。我们使用deployment.yml来维护/更新k8s集群状态。在deployment.yml中,pod的图像设置为${some_image}:latest。创建部署后,只要代码合并到master中,pod的映像就会更新为${some_image}:${build_num}

现在发生的事情是,如果我们需要修改deployment.yml中限制的资源并重新应用它。部署映像也将更新为${some_image} :latest。我们希望将图像保持在集群状态,而不在deployment.yml中维护实际标记。我们知道replcas可以在文件中省略,默认情况下它从集群状态获取值。

问题,

在1.7上,spec.template.spec.containers [0] .image是必需的。

  1. 是否可以应用deployment.yml而不将图像更新为${some_image}:latest--ignore-image-change之类的参数,或deployment.yml中的特定字段)?如果是这样,怎么样?
  2. 另外,我在1.10 documentation中看到图片是可选的。

    1. 这是真的吗?如果是这样,那么哪个版本?
    2. ---更新---

      CI在每次合并到主服务器上构建和部署新映像。在部署时,CI运行命令kubectl set image deployment/app container=${some_image}:${build_num},其中${build_num}是管道的内部版本号。

      要应用deployment.yml,我们运行kubectl apply -f deployment.yml

4 个答案:

答案 0 :(得分:0)

您是否知道repo.example.com/some-tag@sha256:... syntax从docker注册表中提取图片?它几乎完全是为解决您描述的问题而设计的。

从评论更新:

你正在解决错误的问题;该文件仅用于将内容加载到集群中 - 从那一刻开始,元数据的权威副本就在集群中。 kubectl patch命令可以是改变某些内容而不诉诸sed(或更糟)的手术方式,但是不应该尝试在群集外部维护群集状态

答案 1 :(得分:0)

  

但是,在deployment.yml文件中,我们指定了图像的最新标记,因为无法使该字段保持最新

  • 使用“:latest”标记违反了Kubernetes部署中的最佳做法,原因有很多 - 回滚和版本控制是其中的一部分。要正确解决这个问题,您应该重新考虑CI / CD管道方法。例如,我们使用ci-pipeline或ci-job版本来标记图像。
  

是否可以在不将映像更新到指定文件的情况下更新部署。如果是这样,怎么样?

  • 要更新窗格而不更改图像,您有一些选项,每个选项都有一些约束,并且它们都需要一些Ops体操并引入额外的失败点,因为它违反了推荐的方法。
  • k8s可以从您的远程注册表中提取图像(您必须跟踪哈希值,因为您的最新信息不在您的直接控制范围内 - 此处存在潜在问题)。您可以在运行pod的节点的本地docker注册表上检查已使用的哈希值。
  • k8s可以从本地节点注册表中提取图像(您必须确保在“:latest”运行pod的所有潜在节点上都位于本地注册表的同一页面上 - 这样才有可能这里的问题)。在那里,您可以使用容器的imagePullPolicy,这样当CI工具正在部署时 - 它使用yaml的应用(与创建相反)并将图像policu设置为Always,立即应用Never的图像策略(此处也是潜在的问题) ,限制拉动政策已将图像拉到本地存储库(如上所述,此处也存在潜在问题)。
  • 以下是有关此方法的文档的摘录:默认情况下,kubelet将尝试从指定的注册表中提取每个图像。但是,如果容器的imagePullPolicy属性设置为IfNotPresent或Never,则使用本地映像(分别优先或排他)。 如果您希望依赖预先提取的图像作为注册表身份验证的替代,则必须确保群集中的所有节点都具有相同的预拉图像。
  • 更多关于k8s如何处理图片以及为什么最新标记可以回复的原因在这里给出:https://kubernetes.io/docs/concepts/containers/images/

答案 2 :(得分:0)

如果您不想在CI中的deployment.yaml中处理复杂语法,则可以选择使用模板处理器。例如mustache。它会稍微改变CI过程:

  1. 更新模板配置中的图像版本(env1.yaml)
  2. 从模板deployment.mustache和env1.yaml生成deployment.yaml   $ mustache env1.yml deployment.mustache > deployment.yaml
  3. 将配置应用于群集   $ kubectl apply -f deployment.yaml
  4. 主要好处:

    1. env1.yaml始终包含最新的主构建映像,因此您使用正确的映像创建部署对象。
    2. env1.yaml很容易在CI步骤中更新或生成。
    3. deployment.mustache保持不变,并且您确定最终deployment.yaml中可能发生的所有变化都是图像版本。
    4. 还有许多其他模板渲染解决方案,以防胡子不适合你的CI。

答案 3 :(得分:0)

与上面的Const一样,我强烈建议不要在任何docker镜像中使用:latest,而是使用CI / CD来解决版本问题。

我们在Jenkins X项目中遇到了同样的问题,我们有很多git存储库,当我们更改库或基础docker图像之类的东西时,我们需要更改pom.xml, package.json, Dockerfiles, helm charts等许多版本。

我们使用一个名为UpdateBot的简单CLI工具,可以自动在所有下游存储库上生成Pull请求。我们倾向于将此视为库和基本图像的持续交付;)。例如这是current Pull Requests that UpdateBot has generated on the Jenkins X organisation repositories

然后我们将在发布新的基本映像时更新Dockerfiles / helm图表: https://github.com/jenkins-x/builder-base/blob/master/jx/scripts/release.sh#L28-L29