如何强制Kubernetes重新拉出图像?

Tor*_*ger 112 pull image kubernetes

我在GKE上的Kubernetes中有以下复制控制器:

apiVersion: v1
kind: ReplicationController
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 2
  selector:
    app: myapp
    deployment: initial
  template:
    metadata:
      labels:
        app: myapp
        deployment: initial
    spec:
      containers:
      - name: myapp
        image: myregistry.com/myapp:5c3dda6b
        ports:
        - containerPort: 80
      imagePullPolicy: Always
      imagePullSecrets:
        - name: myregistry.com-registry-key
Run Code Online (Sandbox Code Playgroud)

现在,如果我说

kubectl rolling-update myapp --image=us.gcr.io/project-107012/myapp:5c3dda6b
Run Code Online (Sandbox Code Playgroud)

执行滚动更新,但没有重新拉动.为什么?

Wer*_*ght 95

如果有的话,Kubernetes将会使用Pod创建(请参阅更新图像文档):

  • 使用标记的图像 :latest
  • imagePullPolicy: Always 已指定

如果你想总是拉,这很好.但是,如果您想按需执行该操作:例如,如果您想使用some-public-image:latest但只想在您要求时手动提取新版本.你现在可以:

  • 设置imagePullPolicyIfNotPresentNever前拉:每个群集节点,因此最新的缓存上拉手动图像,然后做一个kubectl rolling-update或类似的重新启动吊舱(丑容易坏劈!)
  • 暂时改变imagePullPolicy,做一个kubectl apply,重启pod(例如kubectl rolling-update),还原imagePullPolicy,重做kubectl apply(丑陋!)
  • 拉动并推 some-public-image:latest送到您的私人存储库并执行kubectl rolling-update(重!)

对于on-demande pull来说没有好的解决方案.如果有变化,请评论; 我会更新这个anwser.

  • 你说 kubernetes 在使用 `:latest` 时会拉动 Pod 创建 - 那么 `patch` 怎么样?它是否也总是提取最新/最新的图像?似乎不适合我:( (4认同)
  • 这是对另一个问题的回答。我要求“强制”重新拉动。 (4认同)
  • 谢谢。采用拉推方法。使用 bash 脚本尽可能地自动化,但同意,它很重:) (2认同)
  • 为每个环境设置一个“prod”、“stage”、“test”等标签,将 imagePullPolicy 保留为“always”,并在您想要部署时将标签推送到要部署的映像怎么样? (2认同)

S.S*_*ker 66

有一个命令可以直接执行此操作:

创建一个kubectl rollout restart执行部署滚动重启的新命令。

拉请求GOT合并。它是版本1.15( changelog ) 或更高版本的一部分。

  • @spinkus 与 `kubectl rollout restart deploy <name>` 一起使用 (10认同)
  • 不,没有命令可以直接执行此操作。这只适用于“imagePullPolicy: Always”设置。 (9认同)
  • 是的,这是在新的 kubernetes 版本 1.15 中触发更新的最佳方式。 (4认同)

Tor*_*ger 50

必须imagePullPolicy在容器数据内部而不是在规范数据内部进行分组.但是,我提出了一个问题,因为我发现它很奇怪.此外,没有错误信息.

所以,这个规范片段有效:

spec:
  containers:
  - name: myapp
    image: myregistry.com/myapp:5c3dda6b
    ports:
    - containerPort: 80
    imagePullPolicy: Always
  imagePullSecrets:
    - name: myregistry.com-registry-key
Run Code Online (Sandbox Code Playgroud)

  • 在容器定义中使用“imagePullPolicy:Always”将使“kubernetes”在将更新版本的图像推送到注册表时获取标有“:latest”的图像? (3认同)
  • @pkaramol 否。 `imagePullPolicy: Always` 只是告诉 Kubernetes 始终从注册表中提取镜像。它将使用什么图像由“image”属性配置。如果您将其配置为“image:your-image:latest”,那么它将始终拉取带有“latest”标签的“your-image”图像。 (3认同)
  • 如果你想一直拉,`imagePullPolicy`(或标记`:latest`)很好,但是不能解决按需拉的问题。 (2认同)
  • 是的,我想*总是*拉,如问题中所述。 (2认同)

Eve*_*ews 22

我在开发过程中的黑客攻击是更改我的部署清单以添加最新标记,并始终如此拉动

image: etoews/my-image:latest
imagePullPolicy: Always
Run Code Online (Sandbox Code Playgroud)

然后我手动删除pod

kubectl delete pod my-app-3498980157-2zxhd
Run Code Online (Sandbox Code Playgroud)

因为它是一个部署,Kubernetes将自动重新创建pod并提取最新图像.

  • 值得注意的是,该策略仅在服务故障和停机时间可以容忍的情况下才可行。对于开发来说,这似乎是合理的,但我绝不会将这一策略用于生产部署。 (2认同)

Tam*_*lyn 13

一个流行的解决方法是使用虚拟注释(或标签)修补部署:

kubectl patch deployment <name> -p \
  "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"
Run Code Online (Sandbox Code Playgroud)

假设您的部署满足这些要求,这将导致K8拉动任何新映像并重新部署。

  • 是的,为此使用注释。 (2认同)
  • 另一个复杂的解决方案是两者的结合,即。添加注释并将`ImagePullPolicy` 设置为*Always*。诸如 `deployment.kubernetes.io/revision: "v-someversion"` 和 `kubernetes.io/change-cause: the reason` 之类的注释非常有用,并且会朝着不可变部署方向发展。 (2认同)

Ora*_*bîg 12

现在,kubectl rollout restart deploy YOUR-DEPLOYMENT结合imagePullPolicy: Always策略的命令将允许您使用最新版本的映像重新启动所有 pod。


Gin*_*nts 10

  1. 将策略指定为:
  strategy: 
    type: Recreate
    rollingUpdate: null
Run Code Online (Sandbox Code Playgroud)
  1. 确保每个部署都有不同的注释。Helm 是这样的:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: AppName
        app.kubernetes.io/instance: ReleaseName
      annotations:
        rollme: {{ randAlphaNum 5 | quote }}
Run Code Online (Sandbox Code Playgroud)
  1. 指定映像拉取策略 - 始终
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: Always
Run Code Online (Sandbox Code Playgroud)


iou*_*das 10

在浏览了所有其他答案但不满意之后,我在这里找到了更好的解决方案: https: //cloud.google.com/kubernetes-engine/docs/how-to/updating-apps

它无需使用最新标签或imagePullPolicy: Always 即可工作。如果您通过指定图像 sha256 摘要将新图像推送到同一标签,它也可以工作。

脚步:

  1. 从 docker hub 获取镜像 SHA256(见下图)
  2. 使用以下命令找到您的部署kubectl get deployments
  3. kubectl set image deployment/<your-deployment> <your_container_name>=<some/image>@sha256:<your sha>
  4. kubectl scale deployment <your-deployment>--replicas=0
  5. kubectl scale deployment <your-deployment>--replicas=original replicas count

注意:推出也可能比扩展更有效,但就我而言,我们没有足够的硬件资源来创建另一个实例,k8s 就会陷入困境。

docker hub sha256 位置

  • 小修正。第二点,应该是 &lt;your_container_name&gt; 而不是 &lt;your-pod-name&gt; (2认同)

Bar*_*uri 9

# Linux

kubectl patch deployment <name> -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"

# windows

kubectl patch deployment <name> -p (-join("{\""spec\"":{\""template\"":{\""metadata\"":{\""annotations\"":{\""date\"":\""" , $(Get-Date -Format o).replace(':','-').replace('+','_') , "\""}}}}}"))
Run Code Online (Sandbox Code Playgroud)


Cen*_*cio 8

此答案旨在在您的节点已下载同名镜像的情况下强制拉取镜像,因此即使您将新镜像推送到容器注册表,当您启动一些 pod 时,您的 pod 也会显示“镜像已经存在”。

对于 Azure Container Registry 中的一个案例(可能 AWS 和 GCP 也提供了这个):

  1. 您可以查看您的 Azure 容器注册表,并通过检查清单创建日期来确定哪个映像是最新的。

  2. 然后,复制其摘要哈希(格式为sha256:xxx...xxx)。

  3. 您可以通过运行以下命令缩小当前副本。请注意,这显然会停止您的容器并导致停机。

kubectl scale --replicas=0 deployment <deployment-name> -n <namespace-name>
Run Code Online (Sandbox Code Playgroud)
  1. 然后你可以通过运行来获取 deployment.yaml 的副本:
kubectl get deployments.apps <deployment-name> -o yaml > deployment.yaml
Run Code Online (Sandbox Code Playgroud)
  1. 然后将带有图像字段的行从 更改<image-name>:<tag><image-name>@sha256:xxx...xxx,保存文件。

  2. 现在您可以再次扩展您的副本。新图像将以其独特的摘要被拉出。

注意:假设容器中存在 imagePullPolicy: Always 字段。


Rob*_*ley 7

当给定映像参数时,滚动更新命令假定该映像与复制控制器中当前存在的映像不同。

  • 正如我自己的答案所说,如果图像名称相同,它也有效。很简单,imagePullPolicy 放错了地方。为我辩护,k8s 1.0 文档在这方面是错误的。 (2认同)
  • 该网址也已过时。 (2认同)

Sac*_*ote 6

您可以imagePullPolicy: Always在部署文件中定义。


sjk*_*ing 5

显然,现在当您使用与--image现有容器图像相同的参数运行滚动更新时,您还必须指定一个--image-pull-policy.当以下命令与容器图像相同时,应强制拉动图像:

kubectl rolling-update myapp --image=us.gcr.io/project-107012/myapp:5c3dda6b --image-pull-policy Always

  • 自 Kubernetes 1.18 起,此功能已被删除,如下所述:https://v1-18.docs.kubernetes.io/docs/setup/release/notes/#kubectl (2认同)

Wag*_*ues 5

我已经为我的 springboot api 使用了 kubectl rollout restart 并且它有效。

kubectl rollout restart -f pod-staging.yml --namespace test
Run Code Online (Sandbox Code Playgroud)

用于部署的 Yaml:

apiVersion: "apps/v1"
kind: "Deployment"
metadata:
    name: "my-api"
    labels:
      app: "my-api"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "my-api"
  template:
    metadata:
      labels:
        app: "my-api"
    spec:
      containers:
        - name: my-api
          image: harbor.url.com/mycompany/my-api:staging
          ports:
            - containerPort: 8099
              protocol: TCP
          imagePullPolicy: Always
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8099
            initialDelaySeconds: 90
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8099
            initialDelaySeconds: 90
            periodSeconds: 5
          envFrom:
            - configMapRef:
                name: "my-api-configmap"
          env:
            - name: "TOKEN_VALUE"
              valueFrom:
                secretKeyRef:
                  name: "my-api-secret"
                  key: "TOKEN_VALUE"
          resources:
            requests:
              memory: "512Mi"
              cpu: "500m"
            limits:
              memory: "2048Mi"
              cpu: "1000m"
      imagePullSecrets:
        - name: "my-ci-user"
Run Code Online (Sandbox Code Playgroud)