目录

引言

一、Pod基础概念

(一)Pod简介

(二)Pod的分类

1.自主式Pod

2.控制器管理的Pod

(三)Pod使用方式

1.单容器pod

2.多容器Pod

3. 注意事项

二、Pod容器的分类

(一)基础容器

1.Pause容器的主要作用

2.基础容器的创建

3. pod中容器通信

(二)初始化容器

1.主要特点

2.用途

3.官网示例

3.1 编写yaml文件

3.2 创建service

4.具体行为

(三)应用容器

三、镜像拉取策略

(一)Always

1.基本含义

2.示例

2.1 编写文件

2.2 查看策略结果

(二)IfNotPresent

1.基本含义

2.示例

(三)Never

1.基本含义

2.示例

四、容器重启策略

(一)Always

1.编写文件

2.查看结果

(二)OnFailure

1.编写文件

2.查看结果

(三)Never

1.编写文件

2.查看结果


引言

在Kubernetes(简称K8s)这一强大的容器编排系统中,Pod是最基本的部署单元。Pod封装了一个或多个容器,共享存储、网络和进程空间,允许它们协同工作以完成特定任务。本文将深入探讨Pod的概念、特性以及如何在K8s中对其进行管理

一、Pod基础概念

(一)Pod简介

Pod是Kubernetes中的最小部署单元,它是一组(一个或多个)紧密关联的容器集合,它们共享存储、网络、以及对于如何运行容器的声明(比如启动命令、环境变量等)。Pod中的容器共享一个IP地址和端口空间,它们可以直接通过localhost互相通信。

Pod是Kubernetes进行管理的最小单位,而不是仅仅运行的单个容器。Pod的设计初衷是支持多个容器在一个Pod中协同工作,完成一个复杂的任务。这些容器共享Pod级别的存储卷、网络和生命周期。Pod中可能包含一个或多个紧密相关的应用容器,这些容器可以共享数据卷、网络栈和生命周期管理

(二)Pod的分类

1.自主式Pod

自主式Pod(Ad-Hoc Pod或Non-Controller Managed Pod)是指那些由用户直接创建但不受任何控制器管理的Pod。它们通常通过kubectl run命令或直接向API Server提交YAML/JSON配置文件的方式来创建。自主式Pod一旦创建,除非手动删除,否则不会自动消失或者被重建。这类Pod没有与之关联的控制器,所以如果Pod出现故障,不会像受控制器管理的Pod那样自动恢复到期望状态

2.控制器管理的Pod

Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。

(三)Pod使用方式

在Kubernetes中,Pod可以包含一个或多个容器,这些容器共享相同的网络命名空间、存储卷和生命周期。根据Pod中容器数量的不同,可以将Pod分为单容器Pod和多容器Pod。

1.单容器pod

单容器Pod是最简单和最常见的Pod类型,它只包含一个容器。在这种情况下,Pod的整个生命周期和容器的生命周期是一致的。当容器启动时,Pod开始运行;当容器停止时,Pod也会终止。单容器Pod通常用于运行单个应用或服务,该应用或服务在单个容器中就能完成所有功能。

2.多容器Pod

多容器Pod则包含两个或更多容器,这些容器共享相同的网络和存储资源,并且可以相互通信。多容器Pod通常用于以下场景

2.1 边车(Sidecar)模式

边车模式是一种常用的多容器Pod设计模式。在这种模式下,一个主容器负责处理主要的业务逻辑,而一个或多个边车容器则提供辅助功能,如日志收集、监控、配置管理等。边车容器与主容器共享相同的网络和存储资源,因此可以轻松地访问主容器的日志、配置文件等。

2.2 容器间通信

多容器Pod允许容器之间通过localhost进行通信,这使得容器间协作变得更加容易。例如,一个Web应用可能需要一个数据库容器来存储数据,这两个容器可以部署在同一个Pod中,并通过localhost进行通信。

2.3 资源共享

多容器Pod中的所有容器共享相同的网络和存储资源,这可以简化资源的配置和管理。例如,多个容器可以共享同一个存储卷,以便在容器之间共享数据

3. 注意事项

  • 虽然多容器Pod在某些场景下很有用,但过度使用多容器Pod也可能导致一些问题。例如,如果Pod中的容器过多,可能会导致资源竞争和管理复杂性增加。
  • 在设计多容器Pod时,需要仔细考虑容器之间的依赖关系和通信方式,以确保Pod的稳定性和可维护性。
  • 通常情况下,建议将独立的服务或组件部署在单独的Pod中,以便更好地进行资源隔离和扩展。只有在确实需要容器间紧密协作或共享资源的情况下,才考虑使用多容器Pod。

二、Pod容器的分类

Pod容器在Kubernetes中可以根据其功能和使用场景进行分类。常见的Pod容器分类包括

(一)基础容器

基础容器,又叫Pause容器(全称Infrastructure Container或Infra容器)是Kubernetes中的一个特殊容器,主要用于支持Pod级别的网络命名空间和共享存储卷。它是由Kubernetes自动生成并注入到每个Pod中的,不是用户定义的容器。

1.Pause容器的主要作用

创建共享网络命名空间:Pause容器首先启动,并创建一个网络命名空间,所有该Pod内的其他业务容器都加入到这个共享的网络命名空间中,并分配不同的IP地址。这意味着这些容器可以相互通信就如同它们在同一台主机上的进程一样,共享相同的网络栈和IP地址。

PID命名空间共享:Pod中的不同容器通过共享Pause容器的PID命名空间,使得容器间能够看到彼此的进程ID。

IPC命名空间共享:在同一Pod内的容器也可以通过Pause容器共享IPC命名空间,从而允许它们使用SystemV IPC或POSIX消息队列进行跨容器通信。

资源隔离与管理:虽然Pause容器本身通常是一个非常小且不执行任何实际业务逻辑的镜像(仅包含一个无限循环或暂停进程),但它作为Pod内所有容器的父进程,有助于系统管理和跟踪容器生命周期。同时,Pause容器的存在简化了对Pod整体行为的管理和控制

存储:Pod可以指定多个共享的Volume。Pod中的所有容器都可以访问共享的Volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。

2.基础容器的创建

在创建一个pod时,节点服务器上会事先创建一个pause容器做为基础,而后去生成应用容器,pause容器负责管理此应用容器

创建一个自主式pod,而后在对应的node节点上进行查看

[root@master01 ~]#kubectl run nginx --image=nginx:1.18.0
pod/nginx created
[root@master01 ~]#kubectl get pod nginx -owide
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          8s    10.244.1.101   node01   <none>           <none>
[root@master01 ~]#

在node01节点上查看

[root@node01 ~]#docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS     NAMES
9a7620aa067b   c2c45d506085           "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes             k8s_nginx_nginx_default_82cb8607-3afd-4f8b-a021-fd7bc26320a0_0
3faadfeb233f   k8s.gcr.io/pause:3.2   "/pause"                 2 minutes ago   Up 2 minutes             k8s_POD_nginx_default_82cb8607-3afd-4f8b-a021-fd7bc26320a0_0
#在开启pod之前,会建立k8s.gcr.io/pause:3.2基础容器,而后管理pod

3. pod中容器通信

在同一个pod中的多个容器之间,需要通过pause创建的共享网络空间进行通信

当Kubernetes创建一个Pod时,会首先启动一个Pause容器。这个Pause容器会创建一个新的网络命名空间,并且初始化该命名空间的网络接口。随后,当Pod中的其他容器启动时,它们会被加入到这个已经由Pause容器创建的网络命名空间中。

由于所有容器都共享同一个网络命名空间,它们可以直接通过localhost或者Pod的IP地址进行通信,无需经过Pause容器。

同样的,如果需要进行数据共享,pause容器同样会创建一个共享存储空间进行数据之间的共享

(二)初始化容器

初始化容器在主应用程序容器启动之前运行,用于执行一些初始化任务,如设置配置文件、初始化数据库或等待外部服务准备就绪等。

在Kubernetes中,初始化容器(Init Containers)是一种特殊类型的容器,它们在应用程序容器启动之前运行。

1.主要特点

初始化顺序:初始化容器总是在Pod的主容器(即应用容器)启动之前运行。如果有多个初始化容器,它们会按照在Pod定义中的顺序一个接一个地运行。只有当所有的初始化容器都成功执行完毕后,主容器才会启动。

独立性和隔离性:每个初始化容器都独立运行并单独完成其任务。初始化容器之间以及初始化容器和主容器之间都是隔离的。

运行时长:初始化容器必须运行成功到完成(即退出码为0),如果初始化容器运行失败(即退出码非0),Kubernetes会不断重启Pod,直到初始化容器成功为止(除非Pod的重启策略设置为Never)。

资源限制:初始化容器可以使用与主容器相同的资源限制和配额。

2.用途

资源准备:某些应用程序可能需要一些额外的资源或文件,例如配置文件、SSL证书、密钥等。初始化容器可以负责从配置存储或其他位置获取这些资源,并将它们复制到应用容器可以访问的位置。

同步/等待:有时,应用程序可能需要等待其他外部依赖项就绪,例如数据库服务或消息队列。初始化容器可以负责检查这些依赖项的可用性,并在其就绪后再启动应用容器。

数据预处理:某些应用程序可能需要在启动之前对数据进行预处理,例如解压缩文件、验证数据完整性等。初始化容器可以在应用容器之前执行这些任务,确保应用容器运行时所需的数据已准备就绪。

提供工具程序或自定义代码:初始化容器还可以提供主容器镜像中不具备的工具程序或自定义代码,以满足特定的初始化需求。

修改目录权限:初始化容器还可以用于修改应用容器所需的目录权限,确保应用容器能够正常访问和写入所需的文件或目录。

3.官网示例

在官网网站中有如何使用init容器的示例文件

官方网站:Init 容器 _ Kubernetes(K8S)中文文档_Kubernetes中文社区

3.1 编写yaml文件
[root@master01 data]#vim init.yaml 
[root@master01 data]#cat init.yaml 
apiVersion: v1             #指定了 Kubernetes API 的版本
kind: Pod                  #指定创建资源的类型为pod
metadata:                  #开始定义Pod的元数据
  name: myapp-pod          #Pod 的名称
  labels:                  #定义标签名称
    app: myapp
spec:                      #定义Pod的期望状态的所有信息
  containers:              #定义Pod中要运行的容器
  - name: myapp-container  #容器的名称
    image: busybox         #容器要使用的镜像
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
#command指令,表示在容器中运行的命令及其参数。
#[...]:表示运行一个 shell 命令,该命令输出一条消息并休眠3600秒(1 小时)。
  initContainers:          #开始定义初始化容器
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
#初始化容器要运行的命令及其参数。
#在这个例子中,两个初始化容器都运行了一个shell命令,until表示死循环。
#与while的区别在于,while条件判断为真时,则会进行循环,而until表示条件为假时,进行死循环
#该命令使用 nslookup 来检查 myservice 和 mydb 是否可解析。
#如果它们不可解析,则命令会输出一条消息并休眠 2 秒,然后再次尝试

#initContainers是一个特殊的容器列表,它们在Pod的主容器启动之前运行。
#这些容器可以包含用于设置 Pod 运行环境的初始化任务,如等待其他服务变得可用

此时还需要创建两个用于解析的service,(myservice、mydb)

如果不创建service资源,当使用nslookup进行解析时,因为没有myservice与mydb这个域名,导致nslookup解析失败,until判断条件为假,则会陷入循环

不创建service时,执行该文件,STATUS会一直处于Init:0/2的状态

[root@master01 data]#kubectl apply -f init.yaml 
pod/myapp-pod created
[root@master01 data]#kubectl get pod -o wide
NAME            READY   STATUS     RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
pod/myapp-pod   0/1     Init:0/2   0          19s   10.244.1.116   node01   <none>           <none>

可以通过kubectl get events指令通过查看事件信息,查看调度信息与创建情况

[root@master01 data]#kubectl get events 
LAST SEEN   TYPE     REASON      OBJECT          MESSAGE
2m43s       Normal   Pulling     pod/myapp-pod   Pulling image "busybox"
2m42s       Normal   Scheduled   pod/myapp-pod   Successfully assigned default/myapp-pod to node01
2m27s       Normal   Pulled      pod/myapp-pod   Successfully pulled image "busybox" in 15.925716511s
2m27s       Normal   Created     pod/myapp-pod   Created container init-myservice
2m26s       Normal   Started     pod/myapp-pod   Started container init-myservice

当状态一直处于Init:0/2时,可以通过日志查看pod中init容器的启动失败的原因

按照定义init容器的顺序进行查看,首先查看init-myservice初始化容器

[root@master01 data]#kubectl logs myapp-pod -c init-myservice
Server:		10.96.0.10
Address:	10.96.0.10:53

** server can't find myservice.default.svc.cluster.local: NXDOMAIN

*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer

waiting for myservice      #进入死循环时echo输出的信息
Server:		10.96.0.10
Address:	10.96.0.10:53

** server can't find myservice.default.svc.cluster.local: NXDOMAIN

*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
......

#错误信息表示在解析myservice并没有找到这个名称,并且返回了NXDOMAIN(非存在域)错误。导致一直处在死循环当中

由于init-myservice初始化容器并没有成功运行,pod会不断重启这个容器,导致init-mydb无法运行,同样的也不会运行myapp-pod这个pod实例

相似的,init-mydb的初始化容器,同样如此,所以需要创建这两个service,是nslookup能够正常解析

3.2 创建service

使用yaml文件,同时创建两个service

[root@master01 data]#vim svc.yaml
[root@master01 data]#cat svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

创建service

[root@master01 data]#kubectl apply -f svc.yaml 
service/myservice created
service/mydb created
[root@master01 data]#kubectl get pod,svc
NAME            READY   STATUS     RESTARTS   AGE
pod/myapp-pod   0/1     Init:1/2   0          22m    #先启动定义的第一个初始化容器

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   8d
service/mydb         ClusterIP   10.96.50.193   <none>        80/TCP    86s
service/myservice    ClusterIP   10.96.33.11    <none>        80/TCP    86s
[root@master01 data]#kubectl get pod,svc
NAME            READY   STATUS    RESTARTS   AGE
pod/myapp-pod   1/1     Running   0          23m     

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   8d
service/mydb         ClusterIP   10.96.50.193   <none>        80/TCP    2m10s
service/myservice    ClusterIP   10.96.33.11    <none>        80/TCP    2m10s

#当两个初始化容器都启动成功后,则会正常启动应用容器,即myapp-pod

4.具体行为

在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。 每个容器必须在下一个容器启动之前成功退出。 如果由于运行时或失败退出,导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试。 然而,如果 Pod 的 restartPolicy 设置为 Always,Init 容器失败时会使用 RestartPolicy策略。

在所有的 Init 容器没有成功之前,Pod 将不会变成 Ready 状态。 Init 容器的端口将不会在 Service 中进行聚集。 正在初始化中的 Pod 处于 Pending 状态,但应该会将条件 Initializing 设置为 true。

如果 Pod 重启,所有 Init 容器必须重新执行。

对 Init 容器 spec 的修改,被限制在容器 image 字段中。 更改 Init 容器的 image 字段,等价于重启该 Pod。

因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。 特别地,被写到 EmptyDirs 中文件的代码,应该对输出文件可能已经存在做好准备。

Init 容器具有应用容器的所有字段。 除了 readinessProbe,因为 Init 容器无法定义不同于完成(completion)的就绪(readiness)的之外的其他状态。 这会在验证过程中强制执行。

在 Pod 上使用 activeDeadlineSeconds,在容器上使用 livenessProbe,这样能够避免 Init 容器一直失败。 这就为 Init 容器活跃设置了一个期限。

在 Pod 中的每个 app 和 Init 容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误。

(三)应用容器

Pod是Kubernetes中用于运行和管理应用程序的基本单元,而Pod中的应用容器则是实际运行应用程序的组件。通过合理地定义和管理Pod和其中的容器,可以构建出高可用、可扩展和易于管理的分布式应用程序

三、镜像拉取策略

Pod 的核心是运行容器,必须指定容器引擎,比如 Docker,启动容器时,需要拉取镜像,k8s 的镜像拉取策略可以由用户指定:

(一)Always

1.基本含义

当设置为Always时,kubelet在每次创建Pod或者重启容器时,无论本地节点上是否已存在该镜像,都会尝试从镜像仓库中拉取的镜像。这确保了你总是使用仓库中最新的镜像版本,但可能会导致不必要的网络流量和拉取时间,尤其是在频繁重启容器的场景下。此策略是默认的镜像拉取策略

2.示例

2.1 编写文件
[root@master01 data]#vim always.yaml
[root@master01 data]#cat always.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx01
spec:
  containers:
    - name: nginx01
      image: nginx              #使用nginx官方镜像,不指定版本默认使用最新版本
      imagePullPolicy: Always   #定义镜像拉取策略为Always
      command: [ "echo", "imagepullpolicy is always" ]
#这指定了容器启动时要运行的命令。
#此例中,容器不会运行nginx服务器,而是会执行echo "imagepullpolicy is always"命令,
#并打印出"imagepullpolicy is always"字符串

#注意:由于command字段覆盖了容器的默认命令(在这种情况下是启动nginx服务器的命令),
#因此即使指定了nginx镜像,容器也不会运行nginx服务器
2.2 查看策略结果

使用yaml文件创建pod后,可以查看event事件,并过滤出nginx01的信息,来查看有关事件,或者使用describe查看详细信息

[root@master01 data]#kubectl apply -f always.yaml 
[root@master01 data]#kubectl get pod nginx01
NAME      READY   STATUS             RESTARTS   AGE
nginx01   0/1     CrashLoopBackOff   2          83s
#Pod的状态为CrashLoopBackOff时,这通常意味着容器在启动后立即崩溃
[root@master01 data]#kubectl get events|grep "pod/nginx01"
56m         Normal    Killing     pod/nginx01     Stopping container nginx01
3m51s       Normal    Scheduled   pod/nginx01     Successfully assigned default/nginx01 to node02
2m18s       Normal    Pulling     pod/nginx01     Pulling image "nginx"
3m35s       Normal    Pulled      pod/nginx01     Successfully pulled image "nginx" in 15.726844912s
2m2s        Normal    Created     pod/nginx01     Created container nginx01
2m2s        Normal    Started     pod/nginx01     Started container nginx01
3m17s       Normal    Pulled      pod/nginx01     Successfully pulled image "nginx" in 15.72008403s
98s         Warning   BackOff     pod/nginx01     Back-off restarting failed container
2m45s       Normal    Pulled      pod/nginx01     Successfully pulled image "nginx" in 15.97180592s
2m2s        Normal    Pulled      pod/nginx01     Successfully pulled image "nginx" in 15.664176207s
#可以发现Pod中的容器在生命周期结束后,由于镜像拉取策略为Always,会重新拉取镜像,而后重启容器

(二)IfNotPresent

1.基本含义

当设置为IfNotPresent时,kubelet首先会检查本地节点上是否已存在指定的镜像。如果存在,就直接使用本地镜像;如果不存在,则会从镜像仓库中拉取。这种方式可以减少不必要的镜像拉取操作,加快启动速度,同时节省网络带宽。它能够利用缓存提高效率,同时保持一定的灵活性

在node节点上查看存在的nginx镜像版本

#node01节点
[root@node01 ~]#docker images |grep nginx
nginx                    1.18.0     c2c45d506085   3 years ago     133MB

#node02节点
[root@node02 ~]#docker images|grep nginx
nginx                    1.18.0     c2c45d506085   3 years ago     133MB

2.示例

通过创建nginx:1.18.0版本的pod实例与创建nginx:1.20.2版本的pod实例,再查看event事件,来鉴别IfNotPresent策略的作用

编写创建nginx:1.18.0版本与nginx:1.20.2版本的pod实例的yaml文件

[root@master01 data]#cat ifnotpresent.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx02
spec:
  containers:
    - name: nginx02
      image: nginx
      imagePullPolicy: IfNotPresent   #指定镜像拉取策略为IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx03
spec:
  containers:
    - name: nginx03
      image: nginx:1.20.2
      imagePullPolicy: IfNotPresent   #指定镜像拉取策略为IfNotPresent

当创建成功时,查看event事件

[root@master01 data]#kubectl describe pod nginx02 |sed -n "/Events/,/$$/p"
#使用describe查看pod的详细信息,并使用sed过滤出Events行到最后一行
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  4m5s  default-scheduler  Successfully assigned default/nginx02 to node02
  Normal  Pulled     4m4s  kubelet            Container image "nginx:1.18.0" already present on machine
#此信息表示容器镜像nginx:1.18.0已经在目标节点node02上存在,所以没有重新拉取镜像,直接使用了现有的镜像。
  Normal  Created    4m4s  kubelet            Created container nginx02
  Normal  Started    4m3s  kubelet            Started container nginx02
[root@master01 data]#kubectl describe pod nginx03 |sed -n "/Events/,/$$/p"
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Pulling    4m10s  kubelet            Pulling image "nginx:1.20.2"
  Normal  Scheduled  4m9s   default-scheduler  Successfully assigned default/nginx03 to node01
  Normal  Pulled     3m39s  kubelet            Successfully pulled image "nginx:1.20.2" in 30.148587341s
#在node01上拉取镜像,拉取镜像时长为30.148587341s
  Normal  Created    3m39s  kubelet            Created container nginx03
  Normal  Started    3m39s  kubelet            Started container nginx03

(三)Never

1.基本含义

当设置为Never时,kubelet不会试图从镜像仓库拉取镜像,仅使用节点上已有的镜像。如果本地节点缺少请求的镜像,Pod将无法启动,并报告错误。

2.示例

编写yaml文件,设置拉取策略为Never

[root@master01 data]#vim never.yaml 
[root@master01 data]#cat never.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx04
spec:
  containers:
    - name: nginx04
      image: nginx:1.14
      imagePullPolicy: Never

查看事件信息

[root@master01 data]#kubectl apply -f never.yaml 
pod/nginx04 created
[root@master01 data]#kubectl get pod nginx04
NAME      READY   STATUS              RESTARTS   AGE
nginx04   0/1     ErrImageNeverPull   0          28s
[root@master01 data]#kubectl get events |grep "pod/nginx04"
51s         Normal    Scheduled           pod/nginx04     Successfully assigned default/nginx04 to node02
9s          Warning   ErrImageNeverPull   pod/nginx04     Container image "nginx:1.14" is not present with pull policy of Never
9s          Warning   Failed              pod/nginx04     Error: ErrImageNeverPull
#创建失败,因为本地没有nginx:1.14版本的镜像文件

注意:对于标签为“:latest”的镜像文件,其默认的镜像获取策略即为“Always”;而对于其他标签的镜像,其默认策略则为“IfNotPresent”

四、容器重启策略

在Kubernetes(K8s)中,重启策略(restartPolicy)定义了Pod中的容器在退出时应如何被重启。Pod的spec字段中包含一个restartPolicy字段,该字段决定了容器在遇到故障或退出时应如何响应。

Kubernetes支持以下三种重启策略

(一)Always

总是重启。这是默认值。当容器终止退出后,总是重启容器。无论容器的退出状态码是什么,它都会被重启

1.编写文件

编写yaml文件,设置重启策略为Always

[root@master01 data]#vim restart-always.yaml 
[root@master01 data]#cat restart-always.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx05
spec:
  containers:
    - name: nginx05
      image: nginx:1.18.0
      args:
      - /bin/sh
      - -c
      - sleep 10; exit 3       #休眠10秒。10秒钟后,退出,并返回状态码为3
  restartPolicy: Always        #设置重启策略为Always

2.查看结果

使用yaml文件创建后,在打开新的终端,进行追踪

[root@master01 data]#kubectl apply -f restart-always.yaml
pod/nginx05 created
[root@master01 data]#kubectl get pod nginx05 -w
NAME      READY   STATUS              RESTARTS   AGE
nginx05   0/1     ContainerCreating   0          2s
nginx05   1/1     Running             0          2s
nginx05   0/1     Error               0          12s   #休眠十秒后退出
nginx05   1/1     Running             1          13s   #重启启动
nginx05   0/1     Error               1          23s   #休眠十秒后退出
nginx05   0/1     CrashLoopBackOff    1          35s   
nginx05   1/1     Running             2          36s
nginx05   0/1     Error               2          46s   #休眠十秒后退出
nginx05   0/1     CrashLoopBackOff    2          61s
nginx05   1/1     Running             3          77s
nginx05   0/1     Error               3          87s
.......

#其结果就是该容器退出后不停的进行重启

注释:,Pod的restartPolicy被设置为Always,这意味着当容器退出时(无论退出状态码是什么),它都将被重启。容器启动后,会运行/bin/sh -c "sleep 10; exit 3"命令,该命令会使容器休眠10秒然后以状态码3退出。由于重启策略是Always,所以容器退出后会立即被重启

(二)OnFailure

仅当容器异常退出(退出状态码非0)时,才重启容器。

1.编写文件

同样的,将重启策略修改为onfailure,当状态码为非0是会重启,而当状态码为0时,则不会重启

[root@master01 data]#vim restart-onfailure.yaml 
[root@master01 data]#cat restart-onfailure.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx06
spec:
  containers:
    - name: nginx06
      image: nginx:1.18.0
      args:
      - /bin/sh
      - -c
      - sleep 10; exit 3 #休眠十秒后退出,并指定状态码为3
  restartPolicy: OnFailure
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx07
spec:
  containers:
    - name: nginx07
      image: nginx:1.18.0
      args:
      - /bin/sh
      - -c
      - sleep 10; exit    #休眠十秒后退出,默认状态码为0
  restartPolicy: OnFailure

2.查看结果

[root@master01 data]#kubectl apply -f restart-onfailure.yaml
pod/nginx06 created
pod/nginx07 created
[root@master01 data]#kubectl get pod nginx06
NAME      READY   STATUS   RESTARTS   AGE
nginx06   1/1     Running    0          3s
[root@master01 data]#kubectl get pod nginx07
NAME      READY   STATUS      RESTARTS   AGE
nginx07   1/1     Running    0          5s
[root@master01 ~]#kubectl get pod nginx06
NAME      READY   STATUS             RESTARTS   AGE
nginx06   0/1     CrashLoopBackOff   1          36s
[root@master01 data]#kubectl get pod nginx07
NAME      READY   STATUS      RESTARTS   AGE
nginx07   0/1     Completed   0          37s

查看状态码为非0的pod实例

[root@master01 data]#kubectl get pod nginx06 -w
NAME      READY   STATUS             RESTARTS   AGE
nginx06   1/1     Running            0          11s
nginx06   0/1     Error              0          12s
nginx06   1/1     Running            1          13s
nginx06   0/1     Error              1          23s
nginx06   0/1     CrashLoopBackOff   1          36s
nginx06   1/1     Running            2          37s
nginx06   0/1     Error              2          47s
nginx06   0/1     CrashLoopBackOff   2          61s
nginx06   1/1     Running            3          73s
......
#当状态码为非0时,与always相同,它会不停的重启

查看状态码为0的pod实例

[root@master01 ~]#kubectl get pod nginx07 -w
NAME      READY   STATUS      RESTARTS   AGE
nginx07   0/1     Completed   0          39s
#可以看到,休眠退出之后,因为是正常退出,状态码为0.所以不会重启

(三)Never

不论状态如何,当容器终止退出时,从不重启容器

1.编写文件

设置重启策略为Never

[root@master01 data]#vim restart-never.yaml 
[root@master01 data]#cat restart-never.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx08
spec:
  containers:
    - name: nginx08
      image: nginx:1.18.0
      args:
      - /bin/sh
      - -c
      - sleep 10; exit
  restartPolicy: Never        #重启策略为Never

2.查看结果

[root@master01 data]#kubectl apply -f restart-never.yaml
pod/nginx08 created
[root@master01 data]#kubectl get pod nginx08
NAME      READY   STATUS    RESTARTS   AGE
nginx08   1/1     Running   0          7s
[root@master01 data]#kubectl get pod nginx08
NAME      READY   STATUS      RESTARTS   AGE
nginx08   0/1     Completed   0          16s
[root@master01 data]#kubectl get pod nginx08
NAME      READY   STATUS      RESTARTS   AGE
nginx08   0/1     Completed   0          32s
#Completed正常退出容器,在Never策略下不会重启

注释:Kubernetes不支持直接重启Pod资源,因为Pod是Kubernetes集群中的最小部署单元。如果你需要更改Pod的配置或重启Pod中的容器,通常的做法是删除并重新创建Pod。但是,通过设置合适的重启策略,你可以确保在容器退出时自动重启容器,而无需手动干预。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐