kubernetes1.4新特性:增加新节点健康状况类型DiskPressure

背景资料

在Kubernetes架构图中可以看到,节点(Node)是一个由管理节点委托运行任务的worker。 它能运行一个或多个Pods,节点(Node)提供了运行容器环境所需要的所有必要条件,在Kubernetes之前版本中叫做Minion。

相关结构体

通过下面这张图可以看到在Kubernetes中节点(Node)的相关结构体信息:

• 结构体Node:表示Kubernetes中的节点,在节点上面运行POD。

• 结构体NodeSpec:存放节点的属性信息。

  1. 属性PodCIDR:表示这个节点上面POD可以使用的IP范围。
  2. 属性ExternalID:这是一个已经被放弃使用的属性。
  3. 属性ProviderID:当节点是公有云厂商提供的云主机时,这个属性表示公有云系统中对云主机的唯一标识,格式为:<ProviderName>://<ProviderSpecificNodeID>
  4. 属性Unschedulable:这是一个布尔型变量,默认是false。如果为true的时候,表示这个节点不能被Kubernetes进行调度,也就是Kubernetes不能在这个节点上创建新的POD,但是不会改变这个节点上已经创建的POD。当要对节点进行维护,那么就可以将这个节点的Unschedulable变量设置成true,然后对节点进行维护操作。可以通过下面命令来修改这个属性:

这里面有一个例外,就是如果使用daemonSet控制器来创建POD的时候,不会关心Unschedulable这个属性是否被设置成了true,这是因为daemonSet控制器认为任何节点上的daemonSet POD都是必须要创建的,同这个属性无关。

•结构体NodeStatus:存放节点当前状态信息。

1. 属性Capacity:存放节点上所有资源总量

2. 属性Allocatable:存放节点上可以被调度使用的可用资源数量

3. 属性Phase:存放节点当前所处在什么阶段,一共有三个取值,分别是“Pending”、“Running”和“Terminated”,分别表示如下阶段:

1)Pending:表示节点已经被添加到Kubernetes集群中,但是还没有被Kubernetes进行配置

2)Running:表示节点已经被Kubernetes配置完成,可以由Kubernetes进行调度使用

3)Terminated:表示节点已经从Kubernetes集群中被删除掉了

•结构体NodeCondition:存放节点健康状况。

1.属性Type:节点健康状况类型,包括Ready、OutOfDisk、MemoryPressure、DiskPressure和NetworkUnavailable,分别表示:

1)Ready:表示节点是健康的,可以随时在上面创建POD

2)OutOfDisk:表示这个节点没有空闲的磁盘空间了,已经不能在上面创建POD了

3)MemoryPressure:表示这个节点上可用内存已经很少了

4)DiskPressure:表示这个节点上可用磁盘空间已经很少了

5) NetworkUnavailable:表示这个节点上网络没有被正确配置

2. 属性Status:表示某种类型健康状况的当前状态,目前只有True、False和Unknown,在kubernetes将来版本中还会继续添加新的状态。

1)True:表示当前类型的健康状况确实存在

2)False:表示当前类型的健康状况不存在

3)Unknown:表示kubernetes无法确定当前类型的健康状况是否存在

  1. 属性LastHeartbeatTime:表示上一次更新状态的时间
  2. 属性LastTransitionTime:表示上一次状态变化的时间
  3. 属性Reason:表示上一次状态变化的简单原因
  4. 属性Message:表示上一次状态变化的详细原因

•  结构体AttachedVolume:存放挂载到节点上的数据卷信息。

  1. 属性Name:挂载到节点上数据卷的名称
  2. 属性DevicePath:挂载到节点上数据卷的有效路径

•  结构体NodeStats:存放节点的统计数据。

  1. 属性NodeName:表示这个节点名称。
  2. 属性SystemContainers:这是一个数组型变量,存放这个节点上所有系统容器的统计信息,这里系统容器指的是以Daemon状态运行的kubelet和Docker容器。
  3. 属性StartTime:表示开始对节点进行统计的时间。
  4. 属性CPU:表示CPU相关的统计数据。
  5. 属性Memory:表示内存相关的统计数据
  6. 属性Network:表示网络相关的统计数据。
  7. 属性Fs:表示Kubernetes模块使用文件系统相关的统计数据。
  8. 属性Runtime:表示用户容器运行时的统计数据。

新特性

在Kubernetes1.4中,结构体NodeCondition新增了一个健康状况类型DiskPressure,用来表示这个节点上可用磁盘空间已经很少了。

新增了这个健康状况类型DiskPressure后,在两个方面会提升Kubernetes的使用:

1.可以在调度POD的时候进行参考,如果节点上确实发生了DiskPressure这件事,那么就会由scheduler模块将POD调度到其他节点上。

2.可以在控制节点的时候进行参考,如果节点上确实发生了DiskPressure这件事,那么就会由kubelet模块回收这个节点上的所有POD,将这些POD驱逐到其他节点上。

下面介绍kubelet模块在控制节点的时候是如何参考使用DiskPressure的,这就需要更细致的分析结构体NodeStats中的五个属性:

1. 属性CPU:表示CPU相关的统计数据。这个属性对应结构体CPUStats:

其中属性Time表示统计数据更新时间,属性UsageNanoCores表示节点上所有CPU在采样窗口内的使用量,属性UsageCoreNanoSeconds表示节点上所有CPU历史使用总量。

2. 属性Memory:表示内存相关的统计数据。这个属性对应结构体MemoryStats:

其中属性Time表示统计数据更新时间,属性AvailableBytes表示可以使用的内存总量,属性UsageBytes表示已经被分配的内存大小,属性WorkingSetBytes表示已经被使用的内存大小,已经被使用的内存大小<=已经被分配的内存大小,也就是说属性WorkingSetBytes<=UsageBytes,属性RSSBytes表示匿名缓存和swap缓存(包括Linuxtransparent huge pages)大小,属性PageFaults表示次要内存缺页错误数,属性MajorPageFaults表示主要内存缺页错误数。

什么叫错缺页错误:

节点上物理内存是有限,但是应用程序的使用需求是无限的,操作系统为了解决这个矛盾,使用了虚拟内存的设计。简单的描述就是,给应用程序一个与物理内存无关的虚拟地址空间,并提供一套映射机制,将虚拟地址映射到物理内存。当然应用程序是不知道有这个映射机制存在的,他唯一需要做的就是尽情的使用自己的虚拟地址空间。操作系统提供的映射机制是运行时动态进行虚拟地址和物理地址之间的映射的,当一个虚拟地址没有对应的物理内存时候,映射机制就分配物理内存,构建映射表,满足应用程序的需求,这个过程就叫缺页错误。与直接访问物理内存不同,缺页错误过程大部分是由软件完成的,消耗时间比较久,所以是影响性能的一个关键指标。Linux把缺页错误又进一步分为次要缺页错误和主要缺页错误。前面提到的分配物理内存,构建映射表过程可以看做是次要缺页错误。主要缺页错误是由swap机制引入的,对于swap情况,地址映射好了后,还需要从外部存储读取数据,这个过程涉及到IO操作,耗时更久。

3.  属性Network:表示网络相关的统计数据。这个属性对应结构体NetworkStats:

其中属性Time表示统计数据更新时间,属性RxBytes表示接收到的字节数,属性RxErrors表示接收错误数,属性TxBytes表示发送出去的字节数,属性TxErrors表示发送错误数。

4. 属性Fs:表示Kubernetes模块使用文件系统相关的统计数据。这个属性对应结构体FsStats:

在kubernetes1.4中新增加了InodesFree和Inodes这两个属性。其中属性AvailableBytes表示文件系统可以使用的存储空间大小,属性CapacityBytes表示文件系统存储空间总量,属性UsedBytes表示使用文件系统上特定任务所占用的存储空间大小,所以UsedByte并不等于CapacityBytes-AvailableBytes,属性InodesFree表示文件系统上空闲inode数量,属性Inodes表示文件系统上inode总量。

什么是inode:

文件储存在硬盘上,硬盘的最小存储单位叫做”扇区”。每个扇区储存512字节。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是4KB,即连续八个扇区组成一个块。文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文称作”索引节点”。

5. 属性Runtime:表示用户容器运行时的统计数据。这个属性对应结构体RuntimeStats:

其中属性ImageFs对应结构体FsStats,这个属性表示文件系统上容器使用镜像所占用空间的统计数据。对于节点来说可以有两种文件系统,一种是root文件系统,提供给kubelet存放日志、提供数据卷等使用;一种是image文件系统,提供给容器存储镜像、读写操作使用。image文件系统可以就是root文件系统,也可以是单独提供给容器镜像使用的文件系统,默认情况下就是root文件系统。

在Kubernetes1.4之前版本中只有MemoryPressure这个健康状况类型,对应节点上结构体MemoryStats的AvailableBytes属性。在Kubernetes1.4中,结构体NodeCondition新增了一个健康状况类型DiskPressure,其实这个DiskPressure就对应root文件系统和image文件系统。更具体的说,就是对应root文件系统中和image文件系统的AvailableBytes属性和inodesFree属性。

当满足DiskPressure发生的条件时,kubelet模块回收这个节点上的所有POD,将这些POD驱逐到其他节点上。这需要在启动kubelet模块时增加eviction相关的参数,比如

–eviction-hard:表示立即进行POD资源回收,并将POD驱逐到其他空闲节点上

–eviction-soft:表示先观察一段时间,之后进行POD资源回收,并将POD驱逐到其他空闲节点上

–eviction-soft-grace-period:表示观察时长

下面是kubelet模块设置使用DiskPressure的例子:

--eviction-hard="nodefs.available<1Gi,nodefs.inodesFree<1,imagefs.available<10Gi,imagefs.inodesFree<10"

当节点上root文件系统可用空间小于1G或者空闲inode数小于1,或者当节点上image文件系统可用空间小于10G或者空闲inode数小于10,那么就会设置DiskPressure为true,kubelet模块接口会立即回收这个节点上的POD,并将POD驱逐到其他空闲节点上。

--eviction-soft="nodefs.available<1.5Gi,nodefs.inodesFree<10,imagefs.available<20Gi,imagefs.inodesFree<100"  

--eviction-soft-grace-period="nodefs.available=1m,imagefs.available=2m"

当节点上root文件系统可用空间小于1.5G或者空闲inode数小于10,并且1分钟后还是这样;或者当image文件系统可用空间小于20G或者空闲inode数小于100,并且2分钟后还是这样,那么就会设置DiskPressure为true,kubelet模块接口会回收这个节点上的POD,并将POD驱逐到其他空闲节点上。

总结

我们可以看到kubernetes正在快速的丰富和完善自身功能,从只有MemoryPressure,到增加了DiskPressure,kubernete给使用者提供了更多方式来处理应用容器化会遇到的问题。我们通过上面结构体的介绍可以发现,还可以继续丰富其他类型的Pressure,比如CPUPress、NetworkPress,这些都需要kubernets社区继续去完善,相信随着kubernetes新版本的发布,功能会变得越来越强大。