3.4.1 Pod概览

理解Pod
Pod是kubernetes中可以创建和部署的最小也最简的单位。
Pod代表着集群中运行的进程。

Pod中封装着应用的容器,存储、独立的网络IP,管理容器如何运行的策略选项。
Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或多个容器组合在一起共享资源。

Pod中如何管理多个容器

Pod中可以同时运行多个进程(作为容器运行)协同工作。
同一个Pod中的容器会自动的分配到同一个Node上。
同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。

例如:你有一个容器作为Web服务器运行,需要用到共享的Volume,有另外一个sidecar容器来从远端获取资源更新这些文件。
image.png

Pod中可以共享两种资源:网络和存储。

网络
每个Pod中都会被分配一个唯一的IP地址。
Pod中的所有容器共享网络空间,包括IP地址和端口。
Pod内部的容器可以使用localhost互相通信。
Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。

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

使用Pod
当Pod被创建后,它会被KUbernetes调度到集群的Node上。直到Pod的进程终止、被删除、因为缺少资源被驱逐或者Node故障之前都会保持在那个Node上。

注意:重启Pod中的容器和重启Pod不是一回事。Pod只提供容器的运行环境和保持容器的运行状态,重启容器不会造成Pod重启。

Pod不会自愈。
如果运行Pod的Node故障,或者是调度器本身故障,这个Pod就会被删除。
如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。

在Kubernetes中通常使用Controller来管理Pod。

Pod和Controller
Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。
如果一个Pod出现故障,Controller就能自动将该节点上的Pod到其他健康的Node上。

包含一个或多个的Controller实例:

  • Deployment
  • StatefulSet
  • DaemonSet

通常,Controller会用你提供的Template来创建相应的Pod。

3.4.2 Pod解析

什么是Pod?
Docker是最常用的运行时环境。
Pod中共享的环境包括Linux的namespace、cgroup和其他可能的隔绝环境。

Pod中的容器共享IP地址和端口号,它们之间可以使用localhost互相发现。可以通过进程间互相通信(例如SystemV信号或者POSIX共享内存)。

不同Pod之间的容器具有不同的IP地址,不能直接通过IPC通信。

Pod中容器也有访问共享Volume的权限,这些volume会被定义为Pod的一部分并挂载到应用容器的文件系统中。

Pod中的容器共享namespace和volume,不支持共享PID的namespace。

Pod被创建后,被分配一个唯一的ID(UID),调度到节点上,并一直维持期望的状态直到被终结或者被删除。

Volume和Pod有着相同的生命周期(当其UID存在时)。
当Pod因为某种原因被删除或者被新创建的相同的Pod取代,它相关的东西(例如volume)也会被销毁和再创建一个新的volume。

Pod中应用容器的hostname被设置成Pod的名字。

通常单个Pod中不会运行一个应用的多个实例。
kubernetes-pod-cheatsheet.png
其他替代选择
为什么不直接在一个容器中运行多个应用程序呢?

  1. 透明。让Pod中的容器对基础设施可见。以便基础设施为这些容器提供服务,例如进程管理和资源监控。这可以为用户带来极大的便利。
  2. 解耦软件依赖。每个容器都可以进行版本管理、独立编译和发布。
  3. 使用方便。用户不必运行自己的进程管理器,还要担心错误信号传播等。
  4. 效率。因为由基础架构提供更多的职责,容器变的更加轻量级。

Pod的终止
示例流程如下:

  1. 用户发送删除pod的命令,默认宽限期是30秒;
  2. 在Pod超过该宽限期后API server就会更新Pod的状态为“dead”;
  3. 在客户端命令行上显示的Pod状态为“terminating”;
  4. 跟第三步同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程:

    1. i.如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在 运行,第二步会再增加2秒的宽限期;<br /> ii.向Pod中的进程发送TERM信号;<br /> 5.跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量;<br /> 6.过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。<br /> 7.Kubelet会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。PodAPI中消失,并且在客户端也不可见。

3.4.3 Init容器

Init容器
它是一种专用容器,在应用程序容器启动之前运行,用来包含一些应用镜像中不存在的实用工具或安装脚本。

理解Init容器
Init容器与普通容器很相似,除了以下两点:

  • Init容器总是运行到成功完成为止;
  • 每个Init容器都必须在下一个Init容器启动之前成功完成。

Init容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。
Init容器不支持Readiness Probe,因为他们必须在Pod之前运行完成。
Init容器使用Linux namespace,因此它们能够具有访问Secret的权限。而应用容器则不能。

3.4.4 Pause容器

Pause容器特性:

  • 镜像非常小,目前在700k左右;
  • 永远处于Pause状态。

Pause容器主要是解决Pod中的网络问题。

Pause容器的作用:
kubernetes中的Pause容器主要为每个业务容器提供如下功能:

  • 在Pod中担任Linux命名空间共享的基础;
  • 启动pid命名空间,开启init进程。

image.png

3.4.6 Pod生命周期

Pod phase
Pod的phase是Pod在其生命周期中的简单宏观概述。
下面是phase可能的值:

  • 挂起(pending):Pod被kubernetes系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度Pod的时间和通过网络下载镜像的时间,这可能需要花点时间。
  • 运行中(Running):该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或者重启状态。
  • 成功(Succeeded): Pod中的所有容器都被成功终止,并且不会再重启。
  • 失败(Failed):Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
  • 未知(Unknown):因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败。

image.png
容器探针
探针是由kubelet对容器执行的定期诊断。
要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序:

  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定端口和路径上的容器的IP地址执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。

Kubelet可以选择是否执行在容器上运行两种探针执行和作出反应:

  • livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success.
  • readiness Probe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。

Pod的重启策略:Always、OnFailure和Never。
存活探针由kubelet来执行,因此所有的请求都在kubelet的网络命名空间中进行。

3.4.7 Pod hook

Pod hook由kubernetes管理的kubelet发起,当容器中的进程启动前或者容器中的进程终止之前运行。包含在容器的生命周期之中。
可以同时为Pod中的所有容器都配置hook。

Hook的类型包括两种:

  • exec: 执行一段命令
  • HTTP:发送HTTP请求。