背景
yarn默認(rèn)使用的是最簡(jiǎn)單的FIFO調(diào)度器,即一個(gè)default隊(duì)列,所有用戶共享,分配資源也是先到先得,沒(méi)有優(yōu)先級(jí)之分。有時(shí)一兩個(gè)任務(wù)就把資源全占了,其他任務(wù)吃不到資源造成饑餓,顯然這樣的資源分配是不合理的(在當(dāng)今社會(huì)主義之中,我們要共同富裕?。?。yarn還有兩種資源調(diào)度器,capacity schedule和fair schedule,本文主要研究下capacity schedule。
什么是capacity schedule
Capacity Schedule調(diào)度器以隊(duì)列為單位劃分資源。簡(jiǎn)單通俗點(diǎn)來(lái)說(shuō),就是一個(gè)個(gè)隊(duì)列有獨(dú)立的資源,隊(duì)列的結(jié)構(gòu)和資源是可以進(jìn)行配置的,如下圖:

default隊(duì)列占30%資源,analyst和dev分別占40%和30%資源;類似的,analyst和dev各有兩個(gè)子隊(duì)列,子隊(duì)列在父隊(duì)列的基礎(chǔ)上再分配資源。
隊(duì)列以分層方式組織資源,設(shè)計(jì)了多層級(jí)別的資源限制條件以更好的讓多用戶共享一個(gè)Hadoop集群,比如隊(duì)列資源限制、用戶資源限制、用戶應(yīng)用程序數(shù)目限制。隊(duì)列里的應(yīng)用以FIFO方式調(diào)度,每個(gè)隊(duì)列可設(shè)定一定比例的資源最低保證和使用上限,同時(shí),每個(gè)用戶也可以設(shè)定一定的資源使用上限以防止資源濫用。而當(dāng)一個(gè)隊(duì)列的資源有剩余時(shí),可暫時(shí)將剩余資源共享給其他隊(duì)列。
特性
Capacity調(diào)度器具有以下的幾個(gè)特性:
● 層次化的隊(duì)列設(shè)計(jì),這種層次化的隊(duì)列設(shè)計(jì)保證了子隊(duì)列可以使用父隊(duì)列設(shè)置的全部資源。這樣通過(guò)層次化的管理,更容易合理分配和限制資源的使用。
● 容量保證,隊(duì)列上都會(huì)設(shè)置一個(gè)資源的占比,這樣可以保證每個(gè)隊(duì)列都不會(huì)占用整個(gè)集群的資源。
● 安全,每個(gè)隊(duì)列又嚴(yán)格的訪問(wèn)控制。用戶只能向自己的隊(duì)列里面提交任務(wù),而且不能修改或者訪問(wèn)其他隊(duì)列的任務(wù)。
● 彈性分配,空閑的資源可以被分配給任何隊(duì)列。當(dāng)多個(gè)隊(duì)列出現(xiàn)爭(zhēng)用的時(shí)候,則會(huì)按照比例進(jìn)行平衡。
● 多租戶租用,通過(guò)隊(duì)列的容量限制,多個(gè)用戶就可以共享同一個(gè)集群,同時(shí)保證每個(gè)隊(duì)列分配到自己的容量,提高利用率。
● 操作性,yarn支持動(dòng)態(tài)修改調(diào)整容量、權(quán)限等的分配,可以在運(yùn)行時(shí)直接修改。還提供給管理員界面,來(lái)顯示當(dāng)前的隊(duì)列狀況。管理員可以在運(yùn)行時(shí),添加一個(gè)隊(duì)列;但是不能刪除一個(gè)隊(duì)列。管理員還可以在運(yùn)行時(shí)暫停某個(gè)隊(duì)列,這樣可以保證當(dāng)前的隊(duì)列在執(zhí)行過(guò)程中,集群不會(huì)接收其他的任務(wù)。如果一個(gè)隊(duì)列被設(shè)置成了stopped,那么就不能向他或者子隊(duì)列上提交任務(wù)了。
● 基于資源的調(diào)度,協(xié)調(diào)不同資源需求的應(yīng)用程序,比如內(nèi)存、CPU、磁盤(pán)等等。
配置
開(kāi)啟調(diào)度器
在ResourceManager中配置它要使用的調(diào)度器,配置方式是修改conf/yarn-site.xml,設(shè)置屬性:
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>
配置隊(duì)列
調(diào)度器的核心就是隊(duì)列的分配和使用了,修改conf/capacity-scheduler.xml可以配置隊(duì)列。
Capacity調(diào)度器默認(rèn)有一個(gè)預(yù)定義的隊(duì)列——root,所有的隊(duì)列都是它的子隊(duì)列。隊(duì)列的分配支持層次化的配置,使用.來(lái)進(jìn)行分割,比如yarn.scheduler.capacity.<queue-path>.queues
下面是配置的樣例,比如root下面有三個(gè)子隊(duì)列:
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>a,b,c</value>
<description>The queues at the this level (root is the root queue).
</description>
</property>
<property>
<name>yarn.scheduler.capacity.root.a.queues</name>
<value>a1,a2</value>
<description>The queues at the this level (root is the root queue).
</description>
</property>
<property>
<name>yarn.scheduler.capacity.root.b.queues</name>
<value>b1,b2,b3</value>
<description>The queues at the this level (root is the root queue).
</description>
</property>
隊(duì)列屬性
yarn.scheduler.capacity.<queue-path>.capacity
它是隊(duì)列的資源容量占比(百分比)。系統(tǒng)繁忙時(shí),每個(gè)隊(duì)列都應(yīng)該得到設(shè)置的量的資源;當(dāng)系統(tǒng)空閑時(shí),該隊(duì)列的資源則可以被其他的隊(duì)列使用。同一層的所有隊(duì)列加起來(lái)必須是100%。
yarn.scheduler.capacity.<queue-path>.maximum-capacity
隊(duì)列資源的使用上限。由于系統(tǒng)空閑時(shí),隊(duì)列可以使用其他的空閑資源,因此最多使用的資源量則是該參數(shù)控制。默認(rèn)是-1,即禁用。
yarn.scheduler.capacity.<queue-path>.minimum-user-limit-percent
每個(gè)任務(wù)占用的最少資源。比如,你設(shè)置成了25%。那么如果有兩個(gè)用戶提交任務(wù),那么每個(gè)任務(wù)資源不超過(guò)50%。如果3個(gè)用戶提交任務(wù),那么每個(gè)任務(wù)資源不超過(guò)33%。如果4個(gè)用戶提交任務(wù),那么每個(gè)任務(wù)資源不超過(guò)25%。如果5個(gè)用戶提交任務(wù),那么第五個(gè)用戶需要等待才能提交。默認(rèn)是100,即不去做限制。
yarn.scheduler.capacity.<queue-path>.user-limit-factor
每個(gè)用戶最多使用的隊(duì)列資源占比,如果設(shè)置為50.那么每個(gè)用戶使用的資源最多就是50%。
運(yùn)行和提交應(yīng)用限制
yarn.scheduler.capacity.maximum-applications / yarn.scheduler.capacity.<queue-path>.maximum-applications
設(shè)置系統(tǒng)中可以同時(shí)運(yùn)行和等待的應(yīng)用數(shù)量。默認(rèn)是10000.
yarn.scheduler.capacity.maximum-am-resource-percent / yarn.scheduler.capacity.<queue-path>.maximum-am-resource-percent
設(shè)置有多少資源可以用來(lái)運(yùn)行app master,即控制當(dāng)前激活狀態(tài)的應(yīng)用。默認(rèn)是10%。
隊(duì)列管理
yarn.scheduler.capacity.<queue-path>.state
隊(duì)列的狀態(tài),可以使RUNNING或者STOPPED.如果隊(duì)列是STOPPED狀態(tài),那么新應(yīng)用不會(huì)提交到該隊(duì)列或者子隊(duì)列。同樣,如果root被設(shè)置成STOPPED,那么整個(gè)集群都不能提交任務(wù)了。現(xiàn)有的應(yīng)用可以等待完成,因此隊(duì)列可以優(yōu)雅的退出關(guān)閉。
yarn.scheduler.capacity.root.<queue-path>.acl_submit_applications
訪問(wèn)控制列表ACL控制誰(shuí)可以向該隊(duì)列提交任務(wù)。如果一個(gè)用戶可以向該隊(duì)列提交,那么也可以提交任務(wù)到它的子隊(duì)列。
yarn.scheduler.capacity.root.<queue-path>.acl_administer_queue
設(shè)置隊(duì)列的管理員的ACL控制,管理員可以控制隊(duì)列的所有應(yīng)用程序。同樣,它也具有繼承性。
注意:ACL的設(shè)置是user1,user2 group1,group2這種格式。如果是則代表任何人。空格表示任何人都不允許。默認(rèn)是.
其他屬性
yarn.scheduler.capacity.resource-calculator
資源計(jì)算方法,默認(rèn)是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator,它只會(huì)計(jì)算內(nèi)存。DominantResourceCalculator則會(huì)計(jì)算內(nèi)存和CPU。
yarn.scheduler.capacity.node-locality-delay
調(diào)度器嘗試進(jìn)行調(diào)度的次數(shù)。一般都是跟集群的節(jié)點(diǎn)數(shù)量有關(guān)。默認(rèn)40(一個(gè)機(jī)架上的節(jié)點(diǎn)數(shù))
一旦設(shè)置完這些隊(duì)列屬性,就可以在web ui上看到了??梢栽L問(wèn)下面的連接:
xxx:8088/scheduler
修改隊(duì)列配置
如果想要修改隊(duì)列或者調(diào)度器的配置,可以修改
vi $HADOOP_CONF_DIR/capacity-scheduler.xml
修改完成后,需要執(zhí)行下面的命令:
$HADOOP_YARN_HOME/bin/yarn rmadmin -refreshQueues
注意:
- 隊(duì)列不能被刪除,只能新增。
- 更新隊(duì)列的配置需要是有效的值
- 同層級(jí)的隊(duì)列容量限制相加需要等于100%。
- 如果希望自己的任務(wù)調(diào)度到queue1隊(duì)列,只需在啟動(dòng)任務(wù)時(shí)指定:mapreduce.job.queuename參數(shù)為queue1即可,默認(rèn)為default隊(duì)列
ACL設(shè)置的一個(gè)坑
Hadoop Yarn集群使用隊(duì)列進(jìn)行任務(wù)調(diào)度和資源分配,同時(shí)支持使用ACL控制隊(duì)列允許指定用戶提交,配置中支持兩種操作的acl權(quán)限配置acl_administer_queue和acl_submit_applications。按照語(yǔ)意,如果要控制是否能提交作業(yè),只要配置隊(duì)列的acl_submit_applications屬性即可,按照文檔,也就是這個(gè)意思。
從源碼發(fā)現(xiàn)其實(shí)不是的,只要有administer權(quán)限的,就能提交作業(yè):
@Override
public void submitApplication(ApplicationId applicationId, String userName,
String queue) throws AccessControlException {
// Careful! Locking order is important!
// Check queue ACLs
UserGroupInformation userUgi = UserGroupInformation.createRemoteUser(userName);
if (!hasAccess(QueueACL.SUBMIT_APPLICATIONS, userUgi)
&& !hasAccess(QueueACL.ADMINISTER_QUEUE, userUgi)) {
throw new AccessControlException("User " + userName + " cannot submit" +
" applications to queue " + getQueuePath());
}
如果要限制用戶對(duì)queue的權(quán)限r(nóng)oot queue一定要設(shè)置,不能只設(shè)置leaf queue。因?yàn)闄?quán)限是根權(quán)限具有更高的優(yōu)先級(jí),看代碼注釋:
// recursively look up the queue to see if parent queue has the permission
意思是說(shuō)檢查用戶是否有權(quán)限時(shí),是先看leaf queue(如default)有沒(méi)有權(quán)限,如果沒(méi)有,再往上找父節(jié)點(diǎn)(root)看有沒(méi)有權(quán)限,如果有,成功提交任務(wù)。
如果不設(shè)置root.acl_submit_applications和root.acl_administer_queue時(shí),默認(rèn)所有l(wèi)eaf節(jié)點(diǎn)都會(huì)有所有權(quán)限,即在leaf節(jié)點(diǎn)設(shè)置的一切acl都無(wú)效
所以一定要在capacity-scheduler.xml中配置:
<property>
<name>yarn.scheduler.capacity.root.acl_submit_applications</name>
<value> </value>
</property>
<property>
<name>yarn.scheduler.capacity.root.acl_administer_queue</name>
<value> </value>
</property>
按上面配置以后,root節(jié)點(diǎn)拒絕所有人提交job,這樣就可以由leaf節(jié)點(diǎn)直接控制權(quán)限了。