本篇本意是介绍hadoop的部署资源隔离和调度方案yarn。顺便介绍了容器和容器集群管理。
说回yarn隔离分为cpu和内存,cpu基于cgroups,内存自行实现计算ru_maxrss。还对比了k8n的隔离,它内存和cpu都基于cgroups。在调度方面介绍了yarn的两种调度机制Capacity Scheduler和Fair Scheduler。
整体:https://segmentfault.com/a/11...

yarn

yarn是hadoop的资源隔离和调度
运行在YARN上带来的好处 :

一个集群部署多个版本
计算资源按需伸缩
不同负载应用混搭,集群利用率高
共享底层存储,避免数据跨集群迁移

clipboard.png
两层资源调度

  • RM
    负责AM的创建和从AM接收分配请求分配,有调度器(上述的调度算法插件式放这儿),ASM(分配AM)
  • AM
    负责计算分配量(每个容器大小,要多少个容器)/监控/容错,一个容器运行一个任务,AM可以要多个分配给自己内部任务。

1.到RM申请,在一个Container(只是一个java对象,虚拟的,指定资源大小,启动时是运行task的bin文件等)中启动AM
包含异步的分配资源,暂存在缓冲区,等待AM来取
2.AM RPC取资源并与NM通信
AM领取资源后分配任务不是yarn事情,用户自行实现
3.包含各种状态同步,比如7,持续的nm到rm.

隔离

目前只能实现cpu和内存的隔离
基于cgroups
linux/kernel/cgroup,包含子系统:cpu,io,mmemory,net等

clipboard.png

内核中的代码在kennel下。
用户使用:通过文件系统配置(内核给用户提供的方法)
VFS 文件:ext2,ext3磁盘,socket,cgroups 。操作系统实现后可以通过mount挂载到cgroups文件系统
vi /etc/cgconfig.conf。/sys/fs/cgroup/cpuset中配置即可
对于内存并没有直接用cgroups
内存隔离:线程监控进程内存量,不是超过立刻杀死,有个生命期

  1. jvm不足以:每个任务不仅有java进程,reduce用C++
  2. 不能单纯的cgroups内存树直接配置
    Linux中所有的进程都是通过fork()复制来实现的,而为了减少创建进程带来的堆栈消耗和性能影响,Linux使用了写时复制机制来快速创建进程。也就是说,一个子进程刚刚产生时,它的堆栈空间和父进程是完全一致的,那么从一开始它就拥有和父进程同样的ru_maxrss,如果父进程的ru_maxrss比较大,那么由于rusage计算值取最大值,就算在触发写时复制后,子进程使用的实际最大驻留集大小被更新,我们获得的也还是父进程的那个值,也就是说我们永远拿不到子进程真实使用的内存。
    Java创建子进程时采用了“fork() + exec()”的方案,子进程启动瞬间,它的内存使用量与父进程是一致的,exec系函数,这个系别的函数通过将当前进程的使用权转交给另一个程序,这时候进程原有的所有运行堆栈等数据将全部被销毁,因此ru_maxrss也会被清零计算,然后子进程的内存会恢复正常;也就是说,Container(子进程)的创建过程中可能会出现内存使用量超过预先定义的上限值的情况(取决于父进程,也就是NodeManager的内存使用量);此时,如果使用Cgroup进行内存资源隔离,这个Container就可能会被“kill”。
    虽然我们已经可以获得各个Container进程树的内存(物理内存、虚拟内存)使用量,但是我们不能仅凭进程树的内存使用量(物理内存、虚拟内存)是否超过上限值就决定是否“杀死”一个Container,因为“子进程”的内存使用量是有“波动”的,为了避免“误杀”的情况出现,Hadoop赋予每个进程“年龄”属性,并规定刚启动进程的年龄是1,MonitoringThread线程每更新一次,各个进程的年龄加一,在此基础上,选择被“杀死”的Container的标准如下:如果一个Contaier对应的进程树中所有进程(年龄大于0)总内存(物理内存或虚拟内存)使用量超过上限值的两倍;或者所有年龄大于1的进程总内存(物理内存或虚拟内存)使用量超过上限值,则认为该Container使用内存超量,可以被“杀死”。(注意:这里的Container泛指Container进程树)
    fork/exec/线程/进程在另一篇:xx

调度

1.可以占用空闲资源 Capacity Scheduler DefaultResourceCalculator(哪个用得少分哪个),drf
2.平均分配 Fair Scheduler 支持fair,fifo,drf

二者都从根开始选择队列,应用,容器,分配资源(递归直到叶子容器)。每次选择时依据不同。

  • Capacity Scheduler
    在 Capacity Scheduler 中,在比较资源占用率时,不同的资源比较器对资源定义是不一样的。默认的是 DefaultResourceCalculator,它只考虑内存资源。另外一种是 DominantResourceCalculator,采用了 DRF 比较算法,同时考虑内存和 cpu 两种资源
    DRF:每次计算资源分配占用,最大的。选择最大中最小的分配资源

    clipboard.png

    考虑一个有9个cpu和18GB的系统,有两个用户:用户A的每个任务都请求(1CPU,4GB)资源;用户B的每个任务都请求(3CPU,1GB)资源。最终A分配3份,B分配两份

    clipboard.png

  • Fair Scheduler
    fair比较:
    若 s2紧需资源,s1 不紧需资源,把资源给 s2
    若 s1、s2 都紧需资源,把资源给 minShareRatio 更小的,minShareRatio1 = 已使用内存/ 最小资源保证
    若 s1、s2 都不紧需资源, 把资源给 useToWeightRatio 更小的, useToWeightRatio = 已使用内存 / 权重

概述容器/资源 隔离与调度

技术

  • namespace技术用来进行做进程间的隔离,linux namespace包括:mount namespace, uts namespace, ipc namespace, pid namespace, network namespace, user namespace六种,用于将mount点、UTS(hostname, domain name)、IPC资源、进程、网络、用户等六种资源做到进程级别的隔离。容器作为一个普通的进程,使用namespace技术作隔离。
  • pivot_root根文件系统切换。mount –bind /etc /tmp/test/etc方式允许从任何其他位置访问任何文件或目录,但是其他用户仍然能看到这些mount点,而mount namespace可以做到mount点在各个进程之间隔离。尽管如此,目前没有对文件/目录做进程间隔离的namespace,所以有必要制作根文件系统再采用pivot_root命令在容器内替换为这个根文件系统(注:chroot只是在指定的根文件系统下运行命令)。
  • cgroups技术用来做资源限制,这些资源包括CPU、内存、存储、网络等。
  • AUFS文件系统采用CoW写时复制技术将多个文件系统联合到一个挂载点,这样可以为容器实现一个只读的base镜像加一个可写的镜像,从而缩小镜像的体积。

虚拟机/容器

  • 在hadoop的yarn部署中,容器只是个资源单位的虚拟(没有移植的概念,是在机器上运行执行文件进程限制资源)
  • 最初版本的chroot(目录隔离)
  • 虚拟机(独立系统,通过hypervisor把硬件页指向vm,hypercall调用负责vm和下层硬件调用,所以硬件可以共享,但是隔离性更好,lxc因为一个操作系统很难做到硬件完全隔离)
  • LXC(与虚拟机比不需要单独操作系统,共享的更多就更节省,是docker的基础)
    Kernel namespaces (ipc, uts, mount, pid, network and user)
    Apparmor and SELinux profiles
    Seccomp policies
    Chroots (using pivot_root)
    Kernel capabilities
    CGroups (control groups)
  • docker(基于lxc(没有调度分配集群管理);多了https://stackoverflow.com/que...:应用容器,镜像,AUFS可以跨机器/甚至平台移植,增量更改,应用自动部署),rkt(有了k8s之后docker的技术壁垒变低,k8s可以集成任何容器,只要他支持)。可以运行在虚拟机上

资源隔离调度/容器编排管理

  • 从第一版的JobTracker 单进程的资源分配,源于hadoop。
  • 第二版的Borg(google,未公开过)/yarn/mesos(twitter)等双层(单主整体负责分配,多二层负责具体监控等,各个框架调度器并不知道整个集群资源使用情况,只是被动的接收资源;Master仅将可用的资源推送给各个框架)
  • 第三版的omega(google) 去中心化,集群信息共享,乐观锁,集群申请变化快性能会不好(http://dockone.io/article/1153)

以上这些本身容器是抽象调的,隔离和调度就可以实现这些容器的隔离和固定大小的分配。可以和docker等容器一起用(隔离是重复的),用来调度和部署。docker是运行时隔离和镜像
k8s是需要针对具体容器的,重点在于调度部署等,可以作为docker的编排管理,也针对docker做了很多应用。只要支持

  • k8s(google基于omega,开发人员基本都是omega和Borg的)也可以隔离,功能更全容器编排与管理,容器互联,pod组合等
    所以其实可以用任何k8s,yarn来部署和控制docker资源配置。
  • 国内百度云,腾讯云都实现自己的,比如百度的matrix.类似Borg

云计算和云存储的思想都是,海量分布式环境,用户请求返回按需计算收费:云计算是一种按使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问, 进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务)
云计算可以认为包括以下几个层次的服务:基础设施即服务(IaaS),平台即服务(PaaS)和软件即服务(SaaS)

clipboard.png

需要分布式大量副本和不同版本控制升级等,docker为其提供了降低运维的方式(类似其中的Iaas+升级等管理工具);虚拟技术和容器管理为其提供了多租户隔离和调度。
云可以使用虚拟机节约硬件,私有云可以直接使用docker和k8s即节约硬件也节省操作系统占用,虚拟机和docker也可以适当超卖,docker超卖成本低,因为迁移方便,虚拟机貌似迁移成本很高。在提供虚拟机同时也可以提供k8s+docker的服务,使

k8s

基本上完全基于cgroups。但是对于内存/磁盘这种没有就不行的不可压缩资源,会再加一个阈值,防止不稳定,能分配的会少于这个。所以k8s对于内存的限制会在fork时误放大没有处理。
https://juejin.im/post/5b3d8c...


梦想家
107 声望76 粉丝