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

Kubernetes how to make Deployment to update image

提问人:Andriy Kopachevskyy 提问时间:11/2/2016 更新时间:4/29/2021 访问量:331008

问:

我确实部署了单个 pod,我的自定义 docker 映像如下:

containers:
  - name: mycontainer
    image: myimage:latest

在开发过程中,我想推送新的最新版本并更新部署。 找不到如何做到这一点,而没有明确定义标签/版本并为每个构建递增它,然后执行

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

评论


答:

264赞 Camil 11/2/2016 #1

您可以为 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"

更新:

我发现的另一个技巧是,您不必更改图像名称,而是更改将触发滚动更新的字段的值,例如 .您可以使用或使用如下补丁来执行此操作:terminationGracePeriodSecondskubectl edit deployment your_deploymentkubectl apply -f your_deployment.yaml

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

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

评论

1赞 Andriy Kopachevskyy 11/2/2016
其实你的伎俩还不错,考虑到myimage:lastet和myimage基本上是一样的,谢谢!
3赞 speedplane 6/30/2017
这个技巧似乎更像是一个错误,不知道为什么我们需要指定它两次。
2赞 Camil 6/30/2017
如果您希望 kubernetes 部署使用相同的映像启动一个新 pod(并且此技巧仅适用于“latest”标签),则必须在不带标签的情况下指定它。下次添加“latest”标签,它将触发更新。顺序可以颠倒,没关系。您从不在生产中使用“最新”标签,但出于开发目的,您有时可以从中受益。
2赞 Camil 8/10/2017
它仅适用于最新版本。默认情况下,至少在 docker hub 中,通过不标记映像,它将采用“latest”标记。但也可以在没有它的情况下工作。这个例子不是你在生产环境中想要的,而且在开发中也可以从中受益的用例并不多。有更好的方法可以使用 CI/CD 工具自动更新映像。
15赞 Camil 8/10/2017
每次更改 tag 和 run 命令时,kubernetes 都会执行滚动更新。例如,假设您部署了“repo/myimage:latest”。同时,您的映像已更改并推送到带有“v0.2”标记的存储库。可以通过运行此映像还将具有“最新”标记来执行更新。kubectl set imagekubectl set image deployment/my-deployment mycontainer=myimage:v0.2
178赞 Przemek Nowak 8/14/2018 #2

更新 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

评论

4赞 Mr. Developerdude 12/22/2019
发现了另一个相关的技巧。如果你只做 “kubectl rollout restart deployment” 而不指定任何特定的部署名称,ity 将做“所有”的事情。
1赞 axell-brendow 1/11/2021
就我而言,我发现问题出在我的映像的缓存构建步骤上。所以我需要运行来重新创建图像。docker build --no-cache
0赞 Wyck 1/17/2021
所有逃避的报价都使它看起来很丑陋。\"
0赞 Niko S P 4/3/2021
对我们来说更直接,根据 Przemek 的回答,在部署中添加一个环境变量,引用一个保存 git commit SHA 的变量,使用 imagePullPolicy 这会导致在每次部署中重新拉取映像。
0赞 Paolo Falomo 10/15/2022
就我而言(在 GitLab CI 上),添加提交 sha 对我来说是最好的解决方案:“sed -ie ”s/CI_COMMIT_SHA/$CI_COMMIT_SHA)/g“ deployment.yml See: github.com/kubernetes/kubernetes/issues/...
8赞 xpmatteo 1/17/2019 #3

似乎 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

评论

2赞 Dave White 5/30/2020
Kubernetes 不需要您使用新标签更新部署即可拉取任何映像的最新版本,“latest”是最常见的示例。
19赞 David Faber 5/16/2019 #4

我使用 Gitlab-CI 构建映像,然后将其直接部署到 GCK。如果使用一个巧妙的小技巧来实现滚动更新,而无需更改容器的任何实际设置,即将标签更改为当前的 commit-short-sha。

我的命令如下所示:

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

您可以在其中使用任何名称和任何值作为标签,只要它随每次生成而更改即可。

玩得愉快!

52赞 Martin Peter 10/21/2019 #5
kubectl rollout restart deployment myapp

这是触发滚动更新的当前方法,并将旧副本集保留在原位,以便进行类似回滚提供的其他操作。kubectl rollout

评论

0赞 Martin Peter 11/20/2019
@Prathameshdhanawade修补操作没有命令或等效命令。undo
1赞 Noman Sadiq 1/25/2020 #6

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

每次构建并生成新的构建 ID 时,我都会使用此构建 ID 作为 docker 映像的标签,这里是示例

imagename:buildID

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

imagename:env:buildID

此处 evn:buildid 是 Azure DevOps 变量,其值为 build ID。

所以现在每次我对 build(CI) 和 deploy(CD) 都有新的更改。

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

评论

1赞 pablete 2/17/2020
清单是存储库的一部分。我不明白什么是最佳实践。如果我在管道中生成映像,我是否应该推送以掌握更新的清单?或者我应该为工件生成更新的清单(因此存储库中的清单只是一个没有实际标记图像的模板)?
5赞 Rotem jackoby 10/20/2020 #7

另一个更适合调试但值得一提的选项是检查推出的修订历史记录:

$ kubectl rollout history deployment my-dep
deployment.apps/my-dep
 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

若要查看每个修订的详细信息,请运行:

 kubectl rollout history deployment my-dep --revision=2

然后通过运行以下命令返回到上一个修订版本:

 $kubectl rollout undo deployment my-dep --to-revision=2

然后回到新的。
就像跑步一样(:
ctrl+z -> ctrl+y

(*)CHANGE-CAUSE 是因为您应该使用以下标志运行更新 - 如下所述<none>--record

kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record

(**)有一个关于弃用此标志的讨论

11赞 vagdevi k 4/29/2021 #8

我们可以使用以下命令更新它:

kubectl set image deployment/<<deployment-name>> -n=<<namespace>> <<container_name>>=<<your_dockerhub_username>>/<<image_name you want to set now>>:<<tag_of_the_image_you_want>>

例如

kubectl set image deployment/my-deployment -n=sample-namespace my-container=alex/my-sample-image-from-dockerhub:1.1

哪里:

  • kubectl set image deployment/my-deployment- 我们想将名为my-deployment
  • -n=sample-namespace- 此部署属于名为 的命名空间。如果您的部署属于默认命名空间,则无需在命令中提及此部分。sample-namespace
  • my-container是之前在部署配置的 YAML 文件中提到的容器名称。
  • alex/my-sample-image-from-dockerhub:1.1是要为部署设置并运行容器的新映像。这里是 dockerhub 镜像的用户名(如果适用)、要使用的镜像和标签。alexmy-sample-image-from-dockerhub:1.1