如何让 kubernetes “kubectl apply”不更新现有部署

Posted

技术标签:

【中文标题】如何让 kubernetes “kubectl apply”不更新现有部署【英文标题】:How to kubernetes "kubectl apply" does not update existing deployments 【发布时间】:2020-02-07 22:16:13 【问题描述】:

我有一个 .NET-core Web 应用程序。这将部署到 Azure 容器注册表。我使用

将它部署到我的 Azure Kubernetes 服务

kubectl apply -f testdeployment.yaml

下面的 yaml 文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: mycontainerregistry.azurecr.io/myweb:latest
        ports:
        - containerPort: 80
      imagePullSecrets:
        - name: my-registry-key

这很好用,但是当我更改一些代码时,将新代码推送到容器并运行

kubectl apply -f testdeployment

再一次,AKS/网站不会更新,直到我删除部署

kubectl 删除部署 myweb

我应该怎么做才能让它覆盖部署的任何内容?我想在我的 yaml 文件中添加一些内容。 (我试图在 Azure DevOps 中使用它进行持续交付)。

【问题讨论】:

您是否尝试使用图片中的版本而不是最新版本? 【参考方案1】:

这里的问题是在 kubernetes 中运行的用于此部署的 pod 是旧的。这就是您在应用程序中看不到更改的原因。

每当您部署或推送新代码时,您都必须删除正在运行的 pod。然后,它会从容器注册表中拉取镜像,您将可以看到新的更改。

我建议您在应用部署文件后将其作为 CI/CD 管道中的一个步骤。如果您要手动应用 deployment.yml 文件,则必须使用以下命令手动删除 pod:kubectl delete pod

【讨论】:

你介意解释一下“这里的问题是在 kubernetes 中运行的用于此部署的 pod 是旧的。”当然 pod 是旧的,因此人们希望通过应用新部署来更新它 是 -> 假设您有一个部署 1 与一些 pod-1 一起运行。当您重新应用 deployment-1.yml(yml 文件中没有任何更改,仅更改代码)时,deployment-1 保持不变,并且 pod-1 不会被删除或更新。因此,您要么需要进行滚动更新,要么只是删除 pod,然后从注册表中提取最新的图像。但如果我错了,请纠正我。【参考方案2】:

kubectl 在您的部署 yaml 文件中看不到任何更改,因此它不会进行任何更改。这是使用latest 标签的问题之一。

将您的映像标记为某个增量版本或内部版本号,并在 CI 管道中将 latest 替换为该标签(例如,使用 envsubst 或类似标签)。这样kubectl 就知道图像已更改。而且您还知道正在运行哪个版本的映像。 latest 标签可以是任何图像版本。

Azure DevOps 的简化示例:

# <snippet>
        image: mycontainerregistry.azurecr.io/myweb:$TAG
# </snippet>

管道 YAML:

stages:
- stage: Build
  jobs:
  - job: Build
    variables:
    - name: TAG
      value: $(Build.BuildId)
    steps:
    - script: |
        envsubst '$TAG' < deployment-template.yaml > deployment.yaml
      displayName: Replace Environment Variables

或者,您也可以使用其他工具,例如 Replace Tokens(不同的语法:#TAG#)。

【讨论】:

我为 Azure DevOps 管道添加了一个示例。 我想这是一个更好的解决方案,但如果我必须为我的问题选择正确的答案,我必须是 Daniel Lee。我希望我不会引起太多混乱 问题是,这是错误的。当您使用latest 标签时,imagePullPolicy 默认为Always 是的,我同意,通过查看文档。但是,当我最初写问题时,我确实使用了 :latest-tag。 对,省略标签的行为完全相同。最新的、无标签的、imagePullPolicy:总是 = 都是一样的东西。重新运行您的示例,您会发现如果您的 yaml 没有更改,则没有任何更改。 kubernetes.io/docs/concepts/configuration/overview/…【参考方案3】:

我相信您正在寻找的是 imagePullPolicy。默认为 ifNotPresent,表示不会拉取最新版本。

https://kubernetes.io/docs/concepts/containers/images/

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: mycontainerregistry.azurecr.io/myweb
        imagePullPolicy: Always
        ports:
        - containerPort: 80
      imagePullSecrets:
        - name: my-registry-key

要确保重新创建 pod,请运行:

kubectl delete -f testdeployment && kubectl apply -f testdeployment

【讨论】:

更好! ...是的,这就是我要找的东西 :o) ..Ehr.. .too仓促...没用...根据kubernetes.io/docs/concepts/configuration/overview/…,如果您引用容器:最新并省略imagePullPolicy .. .所以它应该已经是“始终”...我还需要删除 :latest 以使其按预期工作...(尽管您在理论上/规范上是正确的)。您能否在没有 :latest 的情况下更新您的示例,然后我可以将其设置为正确,以帮助其他人 (使用或不使用 imagePullPolicy,它更多地取决于:最新与否) 根据上面的评论更新 如果部署定义没有改变,它仍然不会应用任何东西。如果它必须重新创建 pod,它会再次拉出“最新”版本,但不是在 kubectl apply

以上是关于如何让 kubernetes “kubectl apply”不更新现有部署的主要内容,如果未能解决你的问题,请参考以下文章

如何让容器在 Kubernetes 上运行?

如何让在kubernetes master 也作为节点

如何让快速网关在 Kubernetes 中工作?

如何让 kubernetes “kubectl apply”不更新现有部署

如何让 bash 脚本等到 kubernetes pod 重新启动?

用 Django 和 Kubernetes 部署 prometheus,如何让它抓取 Django 应用程序?