K8s新手系列之Pod中容器的镜像拉取策略

概述

在 Kubernetes(K8s)里,容器镜像拉取策略(ImagePullPolicy)决定了 K8s 在创建或重启 Pod 时,如何处理容器镜像的拉取操作。这一策略能够确保使用的镜像始终是最新的,或者使用本地已有的镜像以提升部署效率。

可以使用kubectl explain pod.spec.containers.imagePullPolicy查看资源的详细文档:

示例:

复制代码
[root@master01 ~]# kubectl explain pod.spec.containers.imagePullPolicy
KIND:     Pod
VERSION:  v1

FIELD:    imagePullPolicy <string>

DESCRIPTION:
     Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always
     if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.
     More info:
     https://kubernetes.io/docs/concepts/containers/images#updating-images

     Possible enum values:
     - `"Always"` means that kubelet always attempts to pull the latest image.
     Container will fail If the pull fails.
     - `"IfNotPresent"` means that kubelet pulls if the image isn't present on
     disk. Container will fail if the image isn't present and the pull fails.
     - `"Never"` means that kubelet never pulls an image, but only uses a local
     image. Container will fail if the image isn't present

通过文档可以发现,镜像拉取策略有三个类型,分别是Always、IfNotPresent、Never

也可以通过官方文档来查看:https://kubernetes.io/docs/concepts/containers/images#updating-images

镜像拉取策略分类详解

Never

Never表示永不拉取镜像,kubelet 不会尝试获取镜像。如果镜像已经以某种方式存在本地, kubelet 会尝试启动容器;否则,会启动失败。

示例:

复制代码
[root@master01 ~/pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat
spec:
  containers:
  - name: container-tomcat
    image: tomcat:8.0
    # 指定镜像拉取策略为Never
    imagePullPolicy: Never
    ports:
    - name: http
      containerPort: 8080
# 创建pod
[root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
pod/pod-tomcat created
# 查看pod
[root@master01 ~/pod]# kubectl get po pod-tomcat
NAME         READY   STATUS              RESTARTS   AGE
pod-tomcat   0/1     ErrImageNeverPull   0          111s

# 查看详情,发现并没有拉取镜像
[root@master01 ~/pod]# kubectl describe po pod-tomcat
Name:             pod-tomcat
...省略万字内容
Events:
  Type     Reason             Age                  From               Message
  ----     ------             ----                 ----               -------
  Normal   Scheduled          2m7s                 default-scheduler  Successfully assigned default/pod-tomcat to node02
  Normal   SandboxChanged     2m5s                 kubelet            Pod sandbox changed, it will be killed and re-created.
  Warning  ErrImageNeverPull  25s (x12 over 2m6s)  kubelet            Container image "tomcat:8.0" is not present with pull policy of Never
  Warning  Failed             25s (x12 over 2m6s)  kubelet            Error: ErrImageNeverPull

IfNotPresent

如果本地有镜像就使用本地的,如果没有就去远程仓库拉取

示例:

复制代码
[root@master01 ~/pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat
spec:
  containers:
  - name: container-tomcat
    image: tomcat:8.0
    # 指定镜像拉取策略为IfNotPresent
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 8080

# 创建pod
[root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
pod/pod-tomcat created

# 查看pod
[root@master01 ~/pod]# kubectl get pod pod-tomcat
NAME         READY   STATUS    RESTARTS   AGE
pod-tomcat   1/1     Running   0          43s

#查看pod详情
[root@master01 ~/pod]# kubectl describe pod pod-tomcat
Name:             pod-tomcat
Namespace:        default
##...省略万字内容
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  64s   default-scheduler  Successfully assigned default/pod-tomcat to node02
  Normal  Pulling    63s   kubelet            Pulling image "tomcat:8.0"
  Normal  Pulled     23s   kubelet            Successfully pulled image "tomcat:8.0" in 40.129798231s (40.129811976s including waiting)
  Normal  Created    23s   kubelet            Created container container-tomcat
  Normal  Started    23s   kubelet            Started container container-tomcat

Always

如果本地有镜像,则对比本地镜像和远程仓库的摘要信息,若相同则使用本地缓存,若不同则重新拉取镜像。

如果本地没有镜像,则无需对比摘要信息,直接拉取镜像。

示例:

复制代码
[root@master01 ~/pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat
spec:
  containers:
  - name: container-tomcat
    # 镜像更改为latest
    image: tomcat:latest
    # 指定镜像拉取策略为Always
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 8080

# 创建pod
[root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
pod/pod-tomcat created

#查看pod
[root@master01 ~/pod]# kubectl get pod pod-tomcat
NAME         READY   STATUS    RESTARTS   AGE
pod-tomcat   1/1     Running   0          4m53s

# 查看pod详情
[root@master01 ~/pod]# kubectl describe pod pod-tomcat
Name:             pod-tomcat
Namespace:        default
## ...省略万字内容
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  5m39s  default-scheduler  Successfully assigned default/pod-tomcat to node02
  Normal  Pulling    5m38s  kubelet            Pulling image "tomcat:latest"
  Normal  Pulled     4m55s  kubelet            Successfully pulled image "tomcat:latest" in 43.43020764s (43.430224485s including waiting)
  Normal  Created    4m55s  kubelet            Created container container-tomcat
  Normal  Started    4m55s  kubelet            Started container container-tomcat

镜像默认的拉取策略

官网的描述是这样的:

  • 如果你省略了 imagePullPolicy 字段,并且你为容器镜像指定了摘要, 那么 imagePullPolicy 会自动设置为 IfNotPresent
  • 如果你省略了 imagePullPolicy 字段,并且容器镜像的标签是 :latestimagePullPolicy 会自动设置为 Always
  • 如果你省略了 imagePullPolicy 字段,并且没有指定容器镜像的标签, imagePullPolicy 会自动设置为 Always
  • 如果你省略了 imagePullPolicy 字段,并且为容器镜像指定了非 :latest 的标签, imagePullPolicy 就会自动设置为 IfNotPresent

简单点来说就是如果没有指定镜像的版本,或者指定镜像的版本为 :latest,那么镜像拉取策略就是 Always。否则就是 IfNotPresent