繁体   English   中英

如何强制 Kubernetes 重新拉图像?

[英]How do I force Kubernetes to re-pull an image?

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

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

现在,如果我说

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

执行滚动更新,但不重新拉取。 为什么?

Kubernetes 将在以下任一情况下创建 Pod(请参阅更新图像文档):

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

如果你想一直拉,这很好。 但是,如果您想按需执行,该怎么办:例如,如果您想使用some-public-image:latest但只想在您要求时手动拉取更新版本。 您目前可以:

  • imagePullPolicy设置为IfNotPresentNever andpre-pull :在每个集群节点上手动拉取图像,以便缓存最新的图像,然后执行kubectl rolling-update或类似的操作以重新启动kubectl rolling-update (丑陋的容易破坏的黑客!)
  • 临时更改imagePullPolicy ,执行kubectl apply ,重新启动 pod(例如kubectl rolling-update ),恢复imagePullPolicy ,重做kubectl apply (丑陋!)
  • some-public-image:latest拉入并推送到您的私有存储库并执行kubectl rolling-update (重!)

按需拉取没有好的解决方案。 如果有变化,请发表评论; 我会更新这个答案。

必须将imagePullPolicy在容器数据中,而不是在规范数据中。 但是,我对此提出了一个问题,因为我觉得这很奇怪。 此外,没有错误消息。

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

spec:
  containers:
  - name: myapp
    image: myregistry.com/myapp:5c3dda6b
    ports:
    - containerPort: 80
    imagePullPolicy: Always
  imagePullSecrets:
    - name: myregistry.com-registry-key

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

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

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

我在开发过程中的技巧是更改我的部署清单以添加最新的标签并始终像这样拉

image: etoews/my-image:latest
imagePullPolicy: Always

然后我手动删除pod

kubectl delete pod my-app-3498980157-2zxhd

因为是 Deployment,Kubernetes 会自动重新创建 pod 并拉取最新的镜像。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

每次创建新 pod 时,图像拉取策略实际上总是有助于拉取图像(这在任何情况下都可以像缩放副本,或者 pod 死亡并创建新 pod)

但是如果你想更新当前正在运行的 pod 的镜像,部署是最好的方式。 它使您可以毫无问题地进行完美更新(主要是当您将持久卷附加到 pod 时):)

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

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

脚步:

  1. 从 docker hub 获取图像 SHA256(见下图)
  2. kubectl set image deployment/<your-deployment> <your-pod-name>=<some/image>@sha256:<your sha>
  3. kubectl scale deployment <your-deployment>--replicas=0
  4. kubectl scale deployment <your-deployment>--replicas=original replicas count

注意:Rollout 也可能会起作用而不是扩展,但在我的情况下,我们没有足够的硬件资源来创建另一个实例,而 k8s 会卡住。

docker hub sha256 位置

如果要对特定 pod 执行直接图像更新,也可以使用kubectl set image

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

要么您手动删除了所有 pod,以通过再次拉动图像来重新创建它。

或者

运行下面的命令 kubectl rollout restart deployment/deployment_name kubectl rollout restart deployment/nginx

此命令应重新创建所有 pod。

对于这两种情况,imagepullPolicy 都应设置为 Always。

我已经为我的 springboot api 使用了 kubectl rollout restart + yaml,如下所示。 它有效=)

kubectl rollout restart -f pod-staging.yml --namespace test

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: 8097
            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"

以下解决了我的问题:

kubectl rollout restart

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM