Kubernetes如何进行部署以更新映像


129

我确实使用单个pod进行了部署,并使用了我的自定义docker映像,例如:

containers:
  - name: mycontainer
    image: myimage:latest

在开发过程中,我想推送新的最新版本并更新Deployment。如果没有明确定义标签/版本并为每个版本增加它,就找不到方法。

kubectl set image deployment/my-deployment mycontainer=myimage:1.9.1

Answers:


151

您可以为Pod配置宽限期(例如30秒或更长时间,具体取决于容器启动时间和图像大小)并进行设置"imagePullPolicy: "Always"。并使用kubectl delete pod pod_name。将创建一个新容器,并自动下载最新的映像,然后终止旧容器。

例:

spec:
  terminationGracePeriodSeconds: 30
  containers:
  - name: my_container
    image: my_image:latest
    imagePullPolicy: "Always"

我目前正在使用Jenkins进行自动构建和图像标记,它看起来像这样:

kubectl --user="kube-user" --server="https://kubemaster.example.com"  --token=$ACCESS_TOKEN set image deployment/my-deployment mycontainer=myimage:"$BUILD_NUMBER-$SHORT_GIT_COMMIT"

另一个技巧是初始运行:

kubectl set image deployment/my-deployment mycontainer=myimage:latest

然后:

kubectl set image deployment/my-deployment mycontainer=myimage

它实际上会触发滚动更新,但请确保您也已imagePullPolicy: "Always"设置。

更新:

我发现的另一个技巧是,无需更改图像名称,而是更改将触发滚动更新的字段的值,例如terminationGracePeriodSeconds。您可以使用kubectl edit deployment your_deploymentkubectl apply -f your_deployment.yaml或使用如下补丁来做到这一点:

kubectl patch deployment your_deployment -p \
  '{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":31}}}}'

只要确保您始终更改数字值即可。


1
实际上,考虑到myimage:lastet和myimage基本上是同一件事,这是您的技巧还不错,谢谢!
abovesun

1
这个技巧似乎更像是一个错误,不确定为什么我们需要指定两次。
speedplane

2
如果您希望kubernetes部署使用相同的映像启动一个新的Pod(并且该技巧仅适用于“最新”标签),则必须指定它而没有标签。下次添加“最新”标签,它将触发更新。顺序可以颠倒,没关系。您永远不会在生产中使用“最新”标签,但是出于开发目的,有时您可以从中受益。
Camil

2
它仅适用于最新版本。默认情况下,至少在docker hub中,通过不标记图像,它将采用“最新”标记。但是没有它也可以工作。这个示例在生产环境中不是您想要的,并且没有很多用例可以在开发中从中受益。有更好的方法,可以使用CI / CD工具自动更新映像。
Camil

11
每次更改标记并运行kubectl set image命令时,kubernetes都会执行滚动更新。例如,假设您部署了“ repo / myimage:latest”。同时,您的图像已更改,并使用“ v0.2”标签推送到存储库。您可以通过运行来执行更新。kubectl set image deployment/my-deployment mycontainer=myimage:v0.2此图像还将具有“最新”标签。
Camil

73

更新2019-06-24

基于@Jodiug注释(如果您有1.15版本),可以使用以下命令:

kubectl rollout restart deployment/demo

阅读有关该问题的更多信息:

https://github.com/kubernetes/kubernetes/issues/13488


好吧,在kubernetes GitHub项目上对此主题进行了有趣的讨论。看到问题:https : //github.com/kubernetes/kubernetes/issues/33664

从那里描述的解决方案中,我建议两个。

第一

1,准备部署

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: registry.example.com/apps/demo:master
        imagePullPolicy: Always
        env:
        - name: FOR_GODS_SAKE_PLEASE_REDEPLOY
          value: 'THIS_STRING_IS_REPLACED_DURING_BUILD'

2.部署

sed -ie "s/THIS_STRING_IS_REPLACED_DURING_BUILD/$(date)/g" deployment.yml
kubectl apply -f deployment.yml

第二(一班轮):

kubectl patch deployment web -p \
  "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"

当然imagePullPolicy: Always,这两种情况都是必需的。


找到了另一个相关的把戏。如果仅执行“ kubectl部署重新启动部署”而不指定任何特定的部署名称,则“全部”将完成。
Lennart Rolland

20
kubectl rollout restart deployment myapp

这是触发滚动更新并将旧副本集留在原处的其他方式,以供kubectl rollout类似回滚提供的其他操作使用。


@Prathameshdhanawade修补程序操作没有undo命令或等效命令。
马丁·彼得

7

我使用Gitlab-CI构建映像,然后将其直接部署到GCK。如果使用整洁的小技巧在不更改容器的任何实际设置的情况下实现滚动更新,则将标签更改为当前的commit-short-sha。

我的命令如下所示:

kubectl patch deployment my-deployment -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"build\":\"$CI_COMMIT_SHORT_SHA\"}}}}}}"

您可以在其中使用标签的任何名称和值,只要标签随每次构建而变化即可。

玩得开心!


6

似乎k8s希望我们为每次部署提供不同的图像标签。我的默认策略是使CI系统生成并推送docker映像,并用内部版本号标记它们xpmatteo/foobar:456

对于本地开发,可以方便地使用脚本或makefile,如下所示:

# create a unique tag    
VERSION:=$(shell date +%Y%m%d%H%M%S)
TAG=xpmatteo/foobar:$(VERSION)

deploy:
    npm run-script build
    docker build -t $(TAG) . 
    docker push $(TAG)
    sed s%IMAGE_TAG_PLACEHOLDER%$(TAG)% foobar-deployment.yaml | kubectl apply -f - --record

sed命令用实际生成的图像标记替换部署文档中的占位符。


kubernetes不需要您使用新标签更新部署即可提取任何映像的最新版本,“最新”是最常见的示例。
戴夫·怀特

1

我正在使用Azure DevOps部署容器化应用程序,我可以通过使用生成ID轻松地解决该问题

每次构建并生成新的Build ID时,我都将此构建ID用作docker image的标签,此处为示例

imagename:buildID

成功建立映像(CI)之后,在部署yml文件的CD管道中,我将映像名称指定为

imagename:env:buildID

此处evn:buildid是天蓝色的devops变量,其值为构建ID。

所以现在每次我对build(CI)和deploy(CD)进行新更改时。

如果您需要CI / CD的构建定义,请发表评论。


清单是回购的一部分。我不知道什么是最佳做法。如果我在管道中构建映像,是否应该推送以掌握更新的清单?还是应该为工件生成更新的清单(因此回购中的清单将只是没有实际标记图像的模板)?
pablete
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.