我如何强迫Kubernetes重新拉一张图片?

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

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

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

296960 次浏览

滚动更新命令,当给定一个映像参数时,假设图像是不同的比当前存在于复制控制器中的值。

必须将imagePullPolicy分组在容器数据中,而不是在规范数据中。然而,我对此提交了问题,因为我发现它很奇怪。此外,没有错误消息。

因此,这个规范代码片段是有效的:

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

Kubernetes将在Pod创建时拉(参见updating-images医生):

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

如果你想一直拉,这很好。但如果你想这样做对需求:例如,如果你想使用some-public-image:latest,但只想在你要求它时手动拉出一个更新的版本。您目前可以:

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

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

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

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

我在开发期间的黑客是改变我的部署清单,以添加最新的标签,总是这样拉

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

然后我手动删除pod

kubectl delete pod my-app-3498980157-2zxhd

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

受欢迎的解决方案是用一个虚拟注释(或标签)修补部署:

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

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

有一个命令可以直接这样做:

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

把请求被合并。它是版本1.15 (更新日志)或更高版本的一部分。

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

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

# 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 pull策略将总是在每次创建新pod时帮助拉出图像(这可以在任何情况下,如缩放副本,或pod死亡,并创建新pod)

但是如果你想要更新当前运行的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. 指定图像提取策略- Always
      containers:
- name: \{\{ .Chart.Name }}
image: "\{\{ .Values.image.repository }}:\{\{ .Values.image.tag }}"
imagePullPolicy: Always

这个答案的目的是在节点已经下载了同名图像的情况下强制拉取图像,因此即使您将新图像推送到容器注册表中,当您启动一些pod时,您的pod会显示“image already present&;”。

对于Azure容器注册表中的一个案例(可能AWS和GCP也提供了这个):

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

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

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

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

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

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

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

它不需要使用最新的标记或imagePullPolicy:总是。如果您通过指定image sha256文摘将新图像推到相同的标记,它也可以工作。

步骤:

  1. 从docker hub获取SHA256图像(见下图)
  2. kubectl set image deployment/<your-deployment> <your_container_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也可以代替scale工作,但在我的情况下,我们没有足够的硬件资源来创建另一个实例,k8s卡住了。

docker hub sha256 location

如果你想在特定的pod上执行直接的图像更新,你也可以使用kubectl set image

< a href = " https://kubernetes。Io /docs/concepts/workload /controllers/deployment/" rel="nofollow noreferrer">https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ .

要么你已经手动删除了所有的豆荚,以再次拉出图像来重新创建。

执行以下命令 Kubectl rollout重启deploy /deployment_name Kubectl rollout restart部署/nginx

这个命令应该重新创建所有的pod。

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

我已经使用kubectl rollout restart我的springboot api和它的工作。

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

部署的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"

下面的方法解决了我的问题:

kubectl rollout restart