文件系统隔离之 – 深入 prjquota,源码剖析

ext4 prjquota 实现原理,参考了 xfs prjquota,并且复用了linux 内核的磁盘配额管理机制的大部分实现,所以源码上分析起来还是非常简单的

linux内核本身就已经支持user、group级别的磁盘配额管理,用法可以参考:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-disk-quotas

从文件系统实现层面来看,文件系统本身并不了解什么是uid,gid,因此disk quota的实现一定是在raw file system 之上的。正因为是如此,所以 prjquota 得以复用原有 disk quota 的大量实现,之需要在原有基础之上,扩展一个新的 quota 类型而已

具体内核提交的 patch:https://lore.kernel.org/patchwork/patch/541891/

4.14 内核时,已经进入主干,因此可以参考:https://lxr.missinglinkelectronics.com/linux+v4.14/fs/ext4/

简述一下其基本设计:

  1. 在 super block 中,有一块专门用来存储 project id 用量的元数据区
  2. 每个文件,属于哪个 project id,是记录在文件的 xattr 属性里面的(正是因为 ext4 文件系统支持 xattr 扩展,所以才很方便的移植这个特性)
  3. 文件写入的时候,先查找这个文件的 project id,然后判断当前 project 的 usage + 文件的增量的大小,是否超过 project 的 hardlimit,如果超过,返回 EDOUT,文件写入失败

CPI2: CPU performance isolation for shared compute clusters

这是google在13年发表的一片论文:https://dl.acm.org/doi/10.1145/2465351.2465388

这篇论文里,最有价值的地方在于建立了一个对业务透明,能够实时感知在线业务运行质量,并且能自动优化的机制

基本概念

  • CPI:uses cycles-per-instruction,平均每条指令消耗的时钟周期(时间),相当于指令执行的代价。

现代处理器均有多级缓存,类似下面这样的一条指令:“ mov 0x200160(%rip),%rax ”,其执行时间由缓存是否命中决定(L0/L1/L2)。


文件系统隔离之 – 初识 prjquota,原理、实践

prjquota 的前身其实是 subtreequota,最早由 openvz 提出,2010年之后好像就没有消息了,没有进入内核主干,有点遗憾。后来我们移植过一次,但是由于设计过于复杂,功能不稳定,并且缺少社区的技术支持,最终选择了放弃。

prjquota 是 xfs 文件系统的一个原生特性,其设计简单,功能健壮。并且有人尝试把他移植到了 ext4 文件系统上。4系内核已经进入主干

prjquota 功能和 subtreequota 一样,能够限制一组具有相同 prjid 属性的文件的总大小。这些具有相同属性的 prjid,可能散落在不同的目录下,但属于同一个项目的文件拥有一个想同的project id标示,正如同一个用户的文件,或者同一个用户组的文件有相同的UserID,或者GroupID

具体实现,可以参考内核 patch:https://lwn.net/Articles/671627/

1)使能 prjquota 特性

磁盘project quota初始化,如下任意一种方法都可以:

  • 重新格式化一个磁盘来支持project quota: /root/ext4/e2fsprogs/misc/mke2fs /dev/hdb -O quota,project
  • 或者在已有的磁盘上使能project quota:/root/ext4/e2fsprogs/misc/tune2fs /dev/hdb  -O quota,project

mount设备支持project quota:

  • mount -t ext4 -o prjquota /dev/hdb xxxx/   或者:
  • mount -t ext4 /dev/hdb xxxx/; /root/ext4/quota-tools/quotaon  xxxx/,但是这个方法,需要在磁盘上没有任何文件被打开的时候才能执行

创建 project id和quota限制管理

  1. 设置一个目录属于一个project id:/root//ext4/e2fsprogs/misc/chattr -p 1001 xxxx/test1
  2. 使得这个目录下的文件默认继承这个project id:/root//ext4/e2fsprogs/misc/chattr  +P xxxx/test1
  3. 设置project的配额:/root/ext4/quota-tools/setquota -P 1001 100 100 400 500 xxxx,可以重复设置,例如更新quota,立即生效


Mutilate: high-performance memcached load generator for tail latency analysis

multilate 是 leverich 在14年的时候,为了分析数据中心高密度混部场景下延迟敏感问题而开发出来的一个 memcached 性能压测工具,原论文可以了解一下:

https://jacob.leverich.org/papers/2014.mutilate.eurosys.slides.pdf

和 mcperf & memslap 等其他压测工具不太一样的是,multilate 非常适合分析长尾延迟问题,比如,multilate 的输出里面,可以非常直观的看到所有请求的平均延迟、最小延迟、最大延迟、10分位、90分位、95分位、99分位,当然,如果你想要更精确的数据,也可以改改代码,支持到99.9分位等等

代码在这里:https://github.com/leverich/mutilate


网络带宽限制之 – Traffic Control 流控原理

TC(Traffic Control)是Linux内核中目前用于网络带宽流控非常成熟的一个工具,通过使用TC灵活的创建各种队列、并定义队列中的数据包被发送的方式, 从而实现对流量的控制。比如开源的 mesos 使用tc来限制job流量,并在twitter公司内大规模推广

Linux高级路由控制:http://lartc.org/howto/

TC文档:http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html

1. 原理

TC中主要包含两种队列:一类是无类队列(classless qdiscs)规定, 另一类是分类队列(classful qdiscs)规定。 无类队列规定相对简单,而分类队列规定则引出了分类和过滤器等概念,使其流量控制功能增强。

无类队列规定是对进入网络设备的数据流不加区分统一对待的队列规定。使用无类队列规定形成的队列能够 接受数据包以及重新编排、延迟或丢弃数据包。这类队列规 定形成的队列可以对整个网络设备的流量进行整形, 但不能细分各种情况。


The pod and service of kubernetes

我们知道pod和service是kubernetes中非常核心的两个概念,要了解这两个东西,就需要看看它们解决了什么问题。

Pod要解决的问题是:数据共享和交互

而Service,是解决Naming问题的另一种思路

1. Pod要解决什么问题?

共享是Pod最原始的需求,早在google的borg论文里,我们就能看到类似的场景,例如borg中的alloc通常用来运行多个Job,举例:有两个Job,一个job是web server实例,另一个job是负责日志收集

1.1 数据共享

数据共享是最常见的一个场景,pod中有volume来解决这种问题,所谓volume,其实就是在不同的容器之间共享一块磁盘。docker里可以用 –volume= 等用法

1.2 容器交互

交互是更深一层次的共享

我们知道容器之间是天然隔离的,除非使用特别hack的方法,否则你根本就无法看到另外一个容器里的任何东西,事实上你除了能看到你自己之外根本就不知道别人的存在。

多容器共生是这个问题的原始需求,AB容器是一个服务下的两个模块,相互依赖共存亡,既需要做好容器间的隔离,例如CPU、内存、网络带宽等等,又需要解决模块间交互的问题。前面我们说的数据共享只是容器交互最简单的一种形式,除此之外,我们需要解决的共享需求有:

  • 网络
  • 进程体系
  • 文件系统

docker提供一些方法来解决这些问题,例如容器之间共享网络可以使用如下命令:

docker run --tty -i --net=container:11e9bc1b8f5be ubuntu /bin/bash

不过目前kubernetes似乎仅仅支持共享网络,还不支持进程体系、文件系统之间的共享


Heracles: Improving Resource Efficiency at Scale

这是一篇非常经典的,混部领域解决延迟敏感问题的论文,作者当年还只是mit的一名博士生,在google实习,heracles 是这个学生毕业论文里的其中一部分

论文原址:https://dl.acm.org/doi/pdf/10.1145/2749469.2749475

这是一个实时的、自反馈的,大规模提升资源利用率的系统

1. 简介

为了解决LC服务和BE作业混部引起的LC服务SLO下降的问题,我们开发了Heracles,一个实时的控制器,能够动态使用硬件隔离机制和软隔离机制,保证共享资源的干扰问题

Heracles能够在保证LC服务足够SLO的情况下,最大限度的将空闲资源用来运行BE作业,同时,结合实时监控离线分析,自动检测干扰源,并在合适的时机,自动调整隔离机制防御干扰产生

在这里我们分两步走:

第一步,我们首先来研究一些经典案例,最终会抛出一个结论,那就是混部情况下【如无特殊说明,以下混部一律特指LC服务和BE作业】,干扰绝大部分情况下都是不均匀的、但是和负载有较强的相关性,所以,通过静态分区的方式来隔离共享资源是不够的

第二步,然后我们会解释为什么要设计Heracles,并且会证明

  1. 多种隔离机制的互相结合,是实现高利用率并且不打破LC服务SLO的关键所在
  2. 将干扰问题细分成几个独立的子问题,能够大大的降低动态控制的复杂性
  3. 为什么一个运行在所有机器上的、实时的监控程序是必须的

第三步,我们来评估一下Heracles在Google内部生产环境能产生多大的收益,测试表明,能够将机器利用率提高到90%左右

最后,我们通过硬件的一些机制来实现DRAM带宽的监控与隔离,进一步提高Heracles的精确性以及降低对离线分析的依赖


Reconciling High Server Utilization and Sub-millisecond Quality-of-Service

论文原址: http://csl.stanford.edu/~christos/publications/2014.mutilate.eurosys.pdf

In this paper, we analyze the challenges of maintaining high QoS for low-latency workloads when sharing servers with other workloads.

The additional workloads can interfere with resources such as processing cores, cache space, memory or I/O bandwidth

The goal of this work is to investigate if workload colocation and good quality-of-service for latency-critical services are fundamentally incompatible in modern systems, or if instead we can reconcile the two


Intel Cache Allocation Technology: CPU LLC Isolation

1. LLC隔离的工具和原理

LLC是指Last Level cache,目前来说通常也就是L3 Cache,CAT是指Intel架构提供的一组工具&技术,用以支持LLC隔离。隔离的目的是针对Latency sensitive服务程序,提高QoS。可以考虑到两个LS敏感的程序跑在同一个机器上相互影响的程度还是比较大。

相关的一些资料如下:

其中的 17.16 PLATFORM SHARED RESOURCE CONTROL: CACHE ALLOCATION TECHNOLOGY

cpu cache隔离技术的原理基本上就是通过划分LLC,限制进程能使用的cache,前后隔离效果如下:

Cache Allocation Technology Allocates More Resource to High Priority Applications

0

1.1. Intel CAT技术

Intel CAT技术提供一系列工具:

  • 通过CPUID指令,查询当前cpu架构是否支持CAT技术,以及支持哪些资源类型(目前来看一般就是LLC),同时可以查询CLOS的数量以及CBM,CBM是指bitmask的长度
  • 提供一种机制,可以关联CLOSID和bitmask
  • 提供一个特殊的寄存器,存储CLOSID,硬件根据CLOSID决定当前使用哪些资源


cgroup 进程调度之 cfs 时间片限制

一些资料

  1. https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
  2. CPU bandwidth control for CFS

cpu带宽控制的原理是在给定周期内(cpu.cfs_period_us)内限制进程组的运行时间(cpu.cfs_quota_us),这两个参数值通过cpu子系统来设置。

cfs_rq相关的两个成员是 runtime_remainingruntime_expires ,前者是当前进程组的剩余时间片,后者是时间片的到期时间。

内核的做法是:

  1. 每次进程切换的时候更新当前进程的运行时间,检查进程时钟带宽是否超过阈值。
  2. 通过一个定时器,每隔固定的cpu.cfs_period_us周期,更新进程组的时钟带宽