暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

k8s系列(三)_what is Pod

分布式存储技术 2020-03-12
391

 

A Pod is the basic building block of Kubernetes–the smallest and simplest unit in the Kubernetes object model that you create or deploy. A Pod represents processes running on your Cluster.(官方定义)

pod是kubernets最基本的操作单元,一个pod可以包含一个或者多个紧密相关的容器,一个pod可以被一个容器化的环境看作应用层的逻辑宿主机。一个pod中的多个容器应用通常是紧密耦合的,pod在node节点上被创建,启动和销毁。

 

 


 

 

 

 

 

 

 

 

1.Pod实现原理

我们在学习容器的时候就了解到因为Linux提供了Namespace和Cgroup两种机制才让容器的出现提供了可能。Namespace用于进程之间的隔离,Cgroup用于控制进程资源的使用;Namespace由hostname、PID、filesystem、network、IPC组成。在K8S里,Pod的生成也是基于Namespace和Cgroup的,所以Pod内的架构合成,我们可以用下面这张图画出来:

 

 

由一个叫”pause“的根容器,加上一个或多个用户自定义的容器构造。pause的状态带便了这一组容器的状态,pod里多个业务容器共享pod的Ip和数据卷。 

 


K8S在初始化一个Pod的时候会先启动一个叫Pause的容器,然后再启动用户自定义的业务容器。这个Pause容器我们认为它是一个“根容器”,它主要有两方面作用:

扮演PID 1的角色,处理僵尸进程

Pod里为其他容器共享Linux namespace的基础

首先我们了解下Linux系统下PID为 1 的进程它的作用和意义。在Linux里,PID 为 1的进程,叫超级进程,也叫根进程,它是系统的第一个进程,是其他进程的父进程,所有的进程都会被挂在这个进程下。如果一个子进程的父进程退了,那么这个子进程会被挂到 PID 1 下面。

其次,我们知道容器本身就是一个进程。在一个Namespace下,Pause作为PID为1的进程存在于一个Pod里,其他的业务容器都挂载这个Pause进程下面。这样,一个Namespace下的进程就会以Pause作为根,呈树状的结构存在一个Pod下。

最后,Pause还有个功能是负责处理僵尸进程。僵尸进程:一个进程使用fork函数创建子进程,如果子进程退出,而父进程并没有来得及调用wait或waitpid获取其子进程的状态信息,那么这个子进程的描述符仍然保存在系统中,其进程号会一直存在被占用(而系统的进程号是有限的),这种进程称之为僵尸进程(Z开头)


2.静态 Pod

静态 Pod 直接由特定节点上的kubelet进程来管理,不通过 master 节点上的apiserver。无法与我们常用的控制器Deployment或者DaemonSet进行关联,它由kubelet进程自己来监控,当pod崩溃时重启该pod,kubelete也无法对他们进行健康检查。静态 pod 始终绑定在某一个kubelet,并且始终运行在同一个节点上。 kubelet会自动为每一个静态 pod 在 Kubernetes 的 apiserver 上创建一个镜像 Pod(Mirror Pod),因此我们可以在 apiserver 中查询到该 pod,但是不能通过 apiserver 进行控制(例如不能删除)。

查看etc/kubernetes/manifests目录,发现master节点重要组件的pod都是以静态的方式运行

 


 

3.Pod Hook

 

    Kubernetes 为我们的容器提供了生命周期钩子的,就是我们说的Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。

Kubernetes 为我们提供了两种钩子函数:

PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器ENTRYPOINT之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态。

PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。

如果PostStart或者PreStop钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。

另外我们有两种方式来实现上面的钩子函数:

Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。

HTTP - 对容器上的特定的端点执行HTTP请求

 

以下示例中,定义了一个Nginx Pod,其中设置了PostStart钩子函数,即在容器创建成功后,写入一句话到/usr/share/message文件中。

 

 


 

 

4.Pod的生命周期

这一点我们来分析下Pod的生命周期 lifecycle,在K8S官方文档里,分别通过phase、Conditions、Container probes、Container States、Pod readiness gate、Restart policy、Pod lifetime等几方面来讲述。以下只讨论phase

Pod的状态是PodStatus对象里的phase字段来表示的,这个phase字段有以下一些值:

 


 

5.Pod资源使用机制

可以通过YAML定义一个容器资源

 


 

Cgroup里资源的换算单位:

CPU换算单位

1 CPU = 1000 millicpu(1 Core = 1000m)

0.5 CPU = 500 millicpu (0.5 Core = 500m)

这里的 m 就是毫、毫核的意思,K8S集群中的每一个节点可以通过操作系统的命令来确认本节点的CPU内核数量,然后将这个数量乘以1000,得到的就是节点总CPU总毫数。比如一个节点有四核,那么该节点的CPU总毫量为4000m。如果你要使用0.5 core,则你要求的是 4000*0.5 = 2000m

K8S里是通过以下两个参数来限制和请求CPU的资源的:

spec.containers[].resources.limits.cpu CPU上限值,可以短暂超过,容器也不会被停止。

spec.containers[].resources.requests.cpu CPU请求值,K8S调度算法里的依据值,可以超过。

这里需要明白的是,如果resources.requests.cpu设置的值大于集群里每个Node的最大CPU核心数,那么这个Pod将无法调度(很容易理解,没有Node能满足它)。

 

6.Pod基本操作命令

 

 


 

 

 

 

 

 

 


 


文章转载自分布式存储技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论