什麼是capacity scheduler
Capacity Scheduler調度器以隊列爲單位劃分資源。簡單通俗點來說,就是一個個隊列有獨立的資源,隊列的結構和資源是可以進行配置的,如下圖:
default隊列佔30%資源,analyst和dev分別佔40%和30%資源;類似的,analyst和dev各有兩個子隊列,子隊列在父隊列的基礎上再分配資源。
隊列以分層方式組織資源,設計了多層級別的資源限制條件以更好的讓多用戶共享一個Hadoop集羣,比如隊列資源限制、用戶資源限制、用戶應用程序數目限制。隊列裏的應用以FIFO方式調度,每個隊列可設定一定比例的資源最低保證和使用上限,同時,每個用戶也可以設定一定的資源使用上限以防止資源濫用。而當一個隊列的資源有剩餘時,可暫時將剩餘資源共享給其他隊列。
特性
Capacity調度器具有以下的幾個特性:
- 層次化的隊列設計,這種層次化的隊列設計保證了子隊列可以使用父隊列設置的全部資源。這樣通過層次化的管理,更容易合理分配和限制資源的使用。
- 容量保證,隊列上都會設置一個資源的佔比,這樣可以保證每個隊列都不會佔用整個集羣的資源。
- 安全,每個隊列有嚴格的訪問控制。用戶只能向自己的隊列裏面提交任務,而且不能修改或者訪問其他隊列的任務。
- 彈性分配,空閒的資源可以被分配給任何隊列。當多個隊列出現爭用的時候,則會按照比例進行平衡。
- 多租戶租用,通過隊列的容量限制,多個用戶就可以共享同一個集羣,同時保證每個隊列分配到自己的容量,提高利用率。
- 操作性,yarn支持動態修改調整容量、權限等的分配,可以在運行時直接修改。還提供給管理員界面,來顯示當前的隊列狀況。管理員可以在運行時,添加一個隊列;但是不能刪除一個隊列。管理員還可以在運行時暫停某個隊列,這樣可以保證當前的隊列在執行過程中,集羣不會接收其他的任務。如果一個隊列被設置成了stopped,那麼就不能向他或者子隊列上提交任務了。
- 基於資源的調度,協調不同資源需求的應用程序,比如內存、CPU、磁盤等等。
配置
開啓調度器
在ResourceManager中配置它要使用的調度器,配置方式是修改conf/yarn-site.xml,設置屬性:
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>
配置隊列
調度器的核心就是隊列的分配和使用了,修改conf/capacity-scheduler.xml
可以配置隊列。
Capacity調度器默認有一個預定義的隊列——root,所有的隊列都是它的子隊列。隊列的分配支持層次化的配置,使用.來進行分割,比如yarn.scheduler.capacity.<queue-path>.queues
下面是配置的樣例,比如root下面有三個子隊列:
<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>
隊列屬性
yarn.scheduler.capacity.<queue-path>.capacity
它是隊列的資源容量佔比(百分比)。系統繁忙時,每個隊列都應該得到設置的量的資源;當系統空閒時,該隊列的資源則可以被其他的隊列使用。同一層的所有隊列加起來必須是100%。
yarn.scheduler.capacity.<queue-path>.maximum-capacity
隊列資源的使用上限。由於系統空閒時,隊列可以使用其他的空閒資源,因此最多使用的資源量則是該參數控制。默認是-1,即禁用。
yarn.scheduler.capacity.<queue-path>.minimum-user-limit-percent
每個任務佔用的最少資源。比如,你設置成了25%。那麼如果有兩個用戶提交任務,那麼每個任務資源不超過50%。如果3個用戶提交任務,那麼每個任務資源不超過33%。如果4個用戶提交任務,那麼每個任務資源不超過25%。如果5個用戶提交任務,那麼第五個用戶需要等待才能提交。默認是100,即不去做限制。
yarn.scheduler.capacity.<queue-path>.user-limit-factor
每個用戶最多使用的隊列資源佔比,如果設置爲50.那麼每個用戶使用的資源最多就是50%。
運行和提交應用限制
yarn.scheduler.capacity.maximum-applications
yarn.scheduler.capacity.<queue-path>.maximum-applications
設置系統中可以同時運行和等待的應用數量。默認是10000.
yarn.scheduler.capacity.maximum-am-resource-percent
yarn.scheduler.capacity.<queue-path>.maximum-am-resource-percent
設置有多少資源可以用來運行app master,即控制當前激活狀態的應用。默認是10%。
隊列管理
yarn.scheduler.capacity.<queue-path>.state
隊列的狀態,可以使RUNNING或者STOPPED.如果隊列是STOPPED狀態,那麼新應用不會提交到該隊列或者子隊列。同樣,如果root被設置成STOPPED,那麼整個集羣都不能提交任務了。現有的應用可以等待完成,因此隊列可以優雅的退出關閉。
yarn.scheduler.capacity.root.<queue-path>.acl_submit_applications
訪問控制列表ACL控制誰可以向該隊列提交任務。如果一個用戶可以向該隊列提交,那麼也可以提交任務到它的子隊列。
yarn.scheduler.capacity.root.<queue-path>.acl_administer_queue
設置隊列的管理員的ACL控制,管理員可以控制隊列的所有應用程序。同樣,它也具有繼承性。
注意: ACL的設置是user1,user2 group1,group2這種格式。如果是則代表任何人。空格表示任何人都不允許。默認是.
其他屬性
yarn.scheduler.capacity.resource-calculator
資源計算方法,默認是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator
,它只會計算內存。DominantResourceCalculator
則會計算內存和CPU。
yarn.scheduler.capacity.node-locality-delay
調度器嘗試進行調度的次數。一般都是跟集羣的節點數量有關。默認40(一個機架上的節點數)
一旦設置完這些隊列屬性,就可以在web ui上看到了。可以訪問下面的連接:
xxx:8088/scheduler
修改隊列配置
如果想要修改隊列或者調度器的配置,可以修改
vi $HADOOP_CONF_DIR/capacity-scheduler.xml
修改完成後,需要執行下面的命令:
$HADOOP_YARN_HOME/bin/yarn rmadmin -refreshQueues
注意:
- 隊列不能被刪除,只能新增。
- 更新隊列的配置需要是有效的值
- 同層級的隊列容量限制相加需要等於100%。
- 如果希望自己的任務調度到queue1隊列,只需在啓動任務時指定:mapreduce.job.queuename參數爲queue1即可,默認爲default隊列
ACL設置的一個坑
Hadoop Yarn集羣使用隊列進行任務調度和資源分配,同時支持使用ACL控制隊列允許指定用戶提交,配置中支持兩種操作的acl權限配置acl_administer_queue和acl_submit_applications。按照語意,如果要控制是否能提交作業,只要配置隊列的acl_submit_applications屬性即可,按照文檔,也就是這個意思。
從源碼發現其實不是的,只要有administer權限的,就能提交作業:
@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());
}
如果要限制用戶對queue的權限root queue一定要設置,不能只設置leaf queue。因爲權限是根權限具有更高的優先級,看代碼註釋:
// recursively look up the queue to see if parent queue has the permission
意思是說檢查用戶是否有權限時,是先看leaf queue(如default)有沒有權限,如果沒有,再往上找父節點(root)看有沒有權限,如果有,成功提交任務。
如果不設置root.acl_submit_applications和root.acl_administer_queue時,默認所有leaf節點都會有所有權限,即在leaf節點設置的一切acl都無效。
所以一定要在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節點拒絕所有人提交job,這樣就可以由leaf節點直接控制權限了。
原文:https://www.jianshu.com/p/1d5df94de97f