Pod是kubernetes中可以创建和部署的最小单位。Pod代表着集群中运行的进程。
Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。
Pod中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络IP,管理容器如何运行的策略选项。Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。
Docker是kubernetes中最常用的容器运行时,但是Pod也支持其他容器运行时。
Pod有两种使用方式:
“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。
一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位 —— 一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。
每个Pod都是应用的一个实例。如果想平行扩展应用的话(运行多个实例),应该运行多个Pod,每个Pod都是一个应用实例。在Kubernetes中,这通常被称为replication。
Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。
注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个容器来从远端获取资源更新这些文件。
Pod中可以共享两种资源:网络和存储。
网络:每个Pod都会被分配一个唯一的IP地址(虚拟ip)。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
存储:可以为一个Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。
Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。
Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。
Pod模版是包含了其他object的Pod定义,例如Replication Controllers,Jobs和DaemonSets。Controller根据Pod模板来创建实际的Pod。
Kubernetes中的基本组件kube-controller-manager就是用来控制Pod的状态和生命周期的
kubelet负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理;
Pod 的 status 字段是一个 PodStatus 对象,PodStatus中有一个 phase 字段。
phase值:
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
Pod 中的所有容器都被成功终止,并且不会再重启。
Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败
Pod 有一个 PodStatus 对象,其中包含一个 PodCondition 数组。 PodCondition 数组的每个元素都有一个 type 字段和一个 status 字段。type 字段是字符串,可能的值有 PodScheduled、Ready、Initialized、Unschedulable和ContainersReady。status 字段是一个字符串,可能的值有 True、False 和 Unknown。
有关 Pod 和容器状态的详细信息,请参阅 PodStatus 和 ContainerStatus。Pod 状态信息取决于当前的 ContainerState。
一般来说,Pod 不会消失,直到人为销毁他们。这可能是一个人或控制器。
这个规则的唯一例外是成功或失败的 phase 超过一段时间(由 master 确定)的Pod将过期并被自动销毁。
Pod在设计支持就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐。
通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployments),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。
因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。
用户需要能够发送删除请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期(倒计时),会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。
示例流程:
1). 用户发送删除pod的命令,默认宽限期是30秒;
2). API 服务器中的Pod 对象会随时间的推移而更新,在宽限期内,Pod 被视为dead。在Pod超过该宽限期后API server就会更新Pod的状态为“dead”;
3). 在客户端命令行上显示的Pod状态为“terminating”;
4). 在第三步的同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程:
1). 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
2). 向Pod中的进程发送TERM信号,停止进程;
5). 跟第三步同时,该Pod将从该service的端点列表中删除;
6). 过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。
7). Kublete会在API server中完成Pod的的删除,同时将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。
删除宽限期默认是30秒。 kubectl delete命令支持 —grace-period= 选项,允许用户设置自己的宽限期。
如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force 和 --grace-period=0 来强制删除pod。
Pod的强制删除是通过在集群和etcd中将其定义为删除状态。当执行强制删除命令时,API server不会等待该pod所运行在节点上的kubelet确认,就会立即将该pod从API server中移除,这时就可以创建跟原pod同名的pod了。这时,在节点上的pod会被立即设置为terminating状态,不过在被强制删除之前依然有一小段优雅删除周期。
PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always。 restartPolicy 适用于 Pod 中的所有容器。
restartPolicy 仅指通过同一节点上的 kubelet 重新启动容器。失败的容器由 kubelet 以五分钟为上限的指数退避延迟(10秒,20秒,40秒…)重新启动,并在成功执行十分钟后重置计时器。一旦绑定到一个节点,Pod 将永远不会重新绑定到另一个节点。
Pod hook(钩子)是由Kubernetes管理的kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为Pod中的所有容器都配置hook。
Hook的类型包括两种:
Preset 就是预设,有时候想要让一批容器在启动的时候就注入一些信息,比如 secret、volume、volume mount 和环境变量,而又不想一个一个的改这些 Pod 的 template,这时候就可以用到 PodPreset 这个资源对象了。
每个 Pod 可以匹配零个或多个 Pod Prestet;并且每个 PodPreset 可以应用于零个或多个 Pod。
禁用特定 Pod 的 Pod Preset:
在某些情况下,可能不希望 Pod 被任何 Pod Preset 所改变。在这些情况下,可以在 Pod 的 Pod Spec 中添加注释:podpreset.admission.kubernetes.io/exclude:“true”