1. 程式人生 > >大資料平臺中資源控制在不同作業系統上的實現

大資料平臺中資源控制在不同作業系統上的實現

大資料平臺中資源控制在不同作業系統上的實現

在大資料迅速發展的今天,很大一部分支援來自於底層技術的不斷髮展,其中非常重要的一點就是系統資源的管理和控制,大資料平臺的核心就是對資源的排程管理,在排程和管理之後如何對這些資源進行控制便成了另一個重要的問題。大資料系統中使用者成千上萬的作業程序跑在叢集中,如果不能對這些程序的資源進行控制,那麼大資料平臺將變得舉步維艱,整個叢集便會隨時崩潰。同時,大資料作業的排程也是基於資源的配額進行分配,大資料的作業本身就承載了資源配額的屬性,但是這些作業是否按照配額進行執行和計算,是否超過了指定的配額導致overuse,是否達不到指定的配額導致資源浪費,這一直以來都是大資料平臺面對和要解決的問題。
大資料平臺中資源控制在不同作業系統上的實現


  本文針對大資料平臺中資源控制這個層面來詳細介紹資源控制在不同作業系統上的具體技術實現,以及大資料平臺和資源控制的整合。

資源控制使用的系統功能

cgroup簡介

cgroup是Linux核心的一部分,cgroup可以為一組程序定義組群分配資源,這個組群分配資源可以包含CPU時間,記憶體,網路頻寬,並且定義的這些資源分配可以動態修改。cgroup以一種層級結構(hierarchical)聚合和管理程序,將所有任務程序以資料夾的形式組成一個控制族群樹,子控制組自動繼承父節點的特定屬性,子控制組還可以有自己特定的屬性。

cgroup提供一些subsystem作為控制族群樹的根節點,所有的任務程序都以這些子系統為入口按樹狀結構設定資源配額。RedHatLinux7.3提供12個cgroup子系統,根據名稱和功能列出如下。

cgroup各子系統功能

可通過以下命令檢視作業系統支援的cgroup子系統,同時顯示各個子系統掛載的根目錄(也可以檢視系統檔案/proc/mount或者使用命令lssubsys-a):

cgroup的操作沒有提供系統API呼叫或者命令列,而是直接訪問cgroupmount的這個檔案系統,舉個例子描述下cgroup介面的使用方式。

1.建立一個目錄用於指定需要控制的作業程序,建立之後系統在會每一級自動生成所有的配置檔案,可以將該目錄認為是一個資源控制組。

2.新增需要的程序到該資源控制組,可以新增多個程序ID

3.設定該資源控制組的實體記憶體使用配額

如果不進行設定,預設情況下,繼承根目錄的記憶體配置,即系統記憶體。

下面介紹下大資料系統中常用的配額設定。

記憶體:實體記憶體的設定檔案為memory子系統下的memory.limit_in_bytes,虛擬記憶體為memory.memsw.limit_in_bytes。如果同時設定這兩個引數,需要先設定memory.limit_in_bytes,因為虛擬記憶體的配額只有在實體記憶體用完後開始生效。在Linux系統上,只有當實體記憶體消耗完後才開始消耗虛擬記憶體,超過配額後再申請的話就會觸發OOMkill掉程序。注意:OOMkiller也可以關閉,需要向memory.oom_control中寫入1,這樣當程序嘗試申請的記憶體超過允許,那麼它就會被暫停,直到額外的記憶體被釋放。

CPU:對CPU的配額控制是通過CPU子系統下的cpu.cfs_period_us和cpu.cfs_quota_us兩個引數控制。cpu.cfs_period_us表示重新分配CPU時間的週期,預設為100000,即百毫秒。cpu.cfs_quota_us就是在這期間內可使用的cpu時間,預設-1,即無限制。所以預設情況下CPU的使用為100%。如果需要將CPU的使用設定為50%,可以將cpu.cfs_quota_us設為50000,cpu.cfs_period_us保持100000,表示每隔100毫秒分配CPU時間,持續使用50毫秒。對CPU的限制不像記憶體,超過配額後再申請的話就會觸發OOMkill掉程序,CPU設定配額後進程不會超過該配額的使用。

JobObjects簡介

Windows平臺也有對應的核心物件用來控制作業對系統資源的訪問,而且控制的範圍比Linux廣,包括剪下板,關閉Windows的許可權,視窗許可權等。不同於Linux,Windows通過系統API來實現對作業物件的訪問。

WindowsJobObjects支援的列表

Windows上使用核心作業物件的流程大概如下:

建立核心作業物件:呼叫::CreateJobObject()建立一個核心物件,剛建立的物件沒有和程序關聯。

把限制屬性設定到作業物件:呼叫::SetInformationJobObject()可以設定如上列表中的限制屬性到該作業物件。

將程序加入到作業物件:呼叫::AssignProcessToJobObject()將程序加入到作業中,如果該程序產生子程序,那麼該子程序會自動成為作業的一部分。

關閉作業物件:呼叫::CloseHandle()關閉作業物件的控制代碼。

需要注意以下幾點:

一個程序屬於一個作業物件之後,不能再assign給另一個作業物件。

在Windows開啟UAC的系統中,沒有提示許可權的程序會被加入到一個預設的相容性系統作業物件中,所以必須使用CREATE_BREAKAWAY_FROM_JOB引數建立程序使該程序脫離預設的作業物件。

新啟動的程序最好使用CREATE_SUSPEND引數這樣可以在程序啟動之前加入到作業物件中,防止起啟動的新的子程序逃離作業物件。

Windows對於記憶體的管理與Linux不同,Windows上的實體記憶體指的是WorkingSet,虛擬記憶體指的是committedmemory,在Windows工作管理員中看的話實體記憶體指的是“工作設定(記憶體)”,虛擬記憶體指的是“提交大小”。CPU通過CpuRate設定,CpuRate的含義是執行緒在每10000個處理器排程週期內被排程的週期數,比如需要限制到20%,就設定CpuRate為2000。

下面直接以C++程式碼為例來說明如果建立和管理作業物件,同時包含如何與ACE程序物件如何整合。

Docker容器資源控制

目前在Linux生態圈,用Docker釋出和執行程式基本已經成為一個標準,同時用Docker管理本地私有云也越來越流行,尤其對於用Kubernetes管理的容器雲,如何限制容器資源變得非常重要。

在RedHat上,Docker擁有自己的cgroup控制目錄,位於各個子系統下的system.slice的資料夾裡面。當我們啟動一個docker容器之後,就會產生這個容器ID開頭的一個子目錄,用來配置這個容器裡面的所有程序對系統資源的使用。

其中task目錄中存放的為容器中程序的PID,以我們這個示例來說,我們在容器中啟動了/bin/sh程序,這個程序ID為2730。

雲端計算中Docker容器的資源收集

目前通過Docker容器部署大資料平臺也比較流行,但是大資料平臺需要獲取每個節點執行環境的資源配額,對於已經執行在Docker容器裡面的程序,如何判斷自己擁有多少系統資源也可以通過cgroup檔案系統獲取。但是Docker容器裡面看到的cgroup的檔案目錄和宿主機不同,docker容器裡面沒有system.slice資料夾,直接以/sys/fs/cgroup/開頭,可以通過命令檢視。所以可以通過這個目錄下的memory.limit_in_bytes獲取容器自身的實體記憶體配額。對於容器中CPUcore數目的獲取,可以通過這個公式獲取到近似的core數:min(1,(int)ceil(cpu.cfs_quota_us/cpu.cfs_period_us))。

用Kubernetes部署的容器平臺需要提前定義資源配額,否則容器可以使用到宿主機的所有資源,資源配額在YAML檔案的resources中定義:

YARN容器管理

作為容器管理的平臺,Kubernetes主要用來在容器中部署分散式應用程式,YARN作為一個資源管理平臺也支援容器的管理,主要用來以容器的方式執行大資料作業。像Spark將YARN作為資源管理器執行Sparkjob。

YARN支援對現有容器大小的調整(cgroup和jobobjects都支援修改資源配額),當用戶從YARN申請了一些固定大小的容器,想改變容器資源配額的大小的時候不需要釋放掉這些容器重新申請,YARN支援動態改變已經分配的容器的大小。

結束語

隨著大資料和雲端計算技術的發展,資源控制和管理作為底層技術已經非常成熟,掌握這些技術便可以在大資料處理中游刃有餘。