Kubernetes 的临时存储空间
首先
本文将总结关于使用Kubernetes的临时存储的注意事项等内容。
临时存储是什么。
在Kubernetes中,作为临时存储处理的对象包括以下三个方面。
-
- emptyDir volume
Pod でマウントして利用する emptyDir 内で利用するストレージ
log directory
Pod で動作するすべてのコンテナから出力されるログ
writable layers
Pod で動作しているすべてのコンテナのローカルディスクに対しての書き込みした内容
这也适用于Pod.spec.resource.requests/limit指定的内容。请注意,不包括hostPath、Local Volume等emptyDir以外的Volume。
临时存储资源的请求和限制
从v1.11版本开始,可以在Pod.spec.resource.requests/limit中设置临时存储。使用方法似乎与内存等相同。有关详细信息,请参阅https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#requests-and-limits-setting-for-local-ephemeral-storage。
设置了Pod.spec.resource.requests中的ephemeral-storage的Pod会如何被调度?
Note: The provided statement appears to be in Japanese. If you are looking for a translation into Chinese, here’s one possible option:
设置了Pod.spec.resource.requests中的ephemeral-storage的Pod会如何被调度?
如果查看https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#how-pods-with-ephemeral-storage-requests-are-scheduled ,会发现写道:
当Pod被创建时,调度器会选择要执行该Pod的节点。
每个节点都有其可以提供给Pod的本地临时存储的最大值。详细信息请参阅节点可分配性。
调度器会确保要调度的所有容器的请求合计少于节点资源的容量。
看起来 resource.requests.memory 等行为相同。
拥有临时存储限制的 Pod 会发生什么?
请参阅 https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#how-pods-with-ephemeral-storage-limits-run,其内容如下所述。
在容器级隔离中,当容器的可写层和日志的使用量超过资源限制值时,Pod 将被驱逐。
在Pod级隔离中,当所有容器的本地临时存储使用量和Pod的emptyDir卷超过限制时,Pod 将被驱逐。
监视ephemeral-storage的使用情况
为了执行上述的 evict 操作,需要监视每个存储的使用情况。在以下链接中描述了如何进行此项监视:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#monitoring-ephemeral-storage-consumption
本地临时存储在使用时将被Kubelet持续监视。监视将定期扫描每个emptyDir卷、日志目录和可写层。
从Kubernetes 1.15开始,集群管理员可以通过使用项目配额来管理emptyDir卷(不包括日志目录和可写层)。项目配额最初是基于XFS实现的,但最近也在ext4中进行了移植。项目配额可用于监视和限制。在1.15版本中,仅监视功能作为Alpha版本可用。
配额比目录扫描更快、更准确。一旦目录被分配给项目,所有在该目录下创建的文件都将在该项目内创建,并且在内核级别跟踪该项目使用的所有文件的块使用情况。如果文件被创建并删除,但仍然有打开的文件描述符在使用,它将继续占用空间。这个空间将由配额跟踪,但不会在目录扫描中显示。
Kubernetes使用以1048576为开始的项目ID。该ID在/etc/projects和/etc/projid中注册和使用。如果项目ID范围已被其他系统使用,则这些项目的ID必须在/etc/projects和/etc/projid中注册,以防止Kubernetes使用它们。
为了启用项目配额,集群管理员需要执行以下步骤:
启用FeatureGate的LocalStorageCapacityIsolationFSQuotaMonitoring功能。在v1.15中,默认情况下是禁用的。
在启用项目配额的情况下创建root分区(或运行时分区)。XFS文件系统已启用,但对于ext4,必须指定进行构建。
在启用项目配额的情况下挂载root分区(或运行时分区)。
据看起来是由kubelet中的eviction-manager进行的。具体来说,这是在https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/eviction_manager.go#L447中实现的。
驱逐管理者
kubelet的驱逐管理器不仅监视瞬态存储,还监视节点的内存、进程标识号等资源情况。当可用资源少于指定值时,该组件将执行驱逐操作。对于可压缩的资源,如CPU等,无需特别处理。但对于不可压缩的资源,如内存和磁盘,必须通过停止Pod(容器)来回收,因此需要使用此类组件进行驱逐和回收。详细信息请参阅 https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/。
这个 eviction 的阈值可以通过 kubelet 的启动参数 –eviction-soft 或 –eviction-hard 来指定。
soft 和 hard 的区别在于在被驱逐时指定的容忍时间(grace-period)的差异。soft 可以优雅地关闭,等待发送 SIGKILL 直到达到 Pod 指定的值或者 –eviction-max-pod-grace-period 指定的时间,而 hard 马上发送 SIGKILL,因此无法进行优雅的关闭。–eviction-soft 没有默认值,因此在资源不足的情况下,最好设置一个值以便进行优雅关闭。
eviction-manager 的运行机制是怎样的。
通过定期执行 https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/eviction_manager.go#L223 中的方法,基本上会通过回收资源进行驱逐。
在这里,我们会检查节点的资源情况,并在 https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/eviction_manager.go#L265 中计算超过阈值的资源。
如果在这些资源中有可以通过 GC 或其他方式回收的资源,则先运行 GC。如果仍然无法回收或者 GC 无法解决问题,则转向驱逐过程。
然后获取活动的 pods,并在 https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/eviction_manager.go#L360 中为应该被驱逐的 Pod 进行优先级排序。
内存是通过 https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/helpers.go#L670 进行排序,磁盘略微复杂,需要根据是否使用 imageFS 等条件进行处理,但基本上是按照以下顺序进行排序以确定优先级。
-
- requests の値を超えているか(超えていない場合は evict の対象外)
-
- Pod priority
- そのリソースの利用量
在此之后,我们将使用算出的 activePods 值在 https://github.com/kubernetes/kubernetes/blob/v1.15.1/pkg/kubelet/eviction/eviction_manager.go#L37 中进行逐出操作。一旦进行了逐出操作并返回,被逐出的 Pod 似乎只有一个在每个循环中。
看起来,evict已经实现了。虽然evict本身只有这么多,但是对于内存,还有OOMKill等其他停止方法,所以请注意。
总结
本文整理了使用Kubernetes的临时存储(主要是evict行为)时需要注意的事项。本次总结旨在调查是否有防止Pod由于磁盘容量不足而进行的硬性驱逐的方法,但我们发现除了调整–eviction-soft之外别无他法。由于似乎使用本地磁盘需要注意的事项很多,所以我希望能继续深入调查。