劉殊旸,張曼怡,曹 強
(華中科技大學武漢光電國家研究中心,湖北武漢430074)
虛擬化技術[1]已經成為云計算領域中不可或缺的一部分。容器[2,3]作為一種輕量虛擬化技術,相較于基于虛擬機的全虛擬化方式,可以更細粒度地高效使用資源[4]。近幾年來,以 Docker為代表的多種容器工具發展迅猛[5,6]。Docker是一個部署、執行和管理容器的工具,使用官方的Docker hub所提供的標準鏡像可以快速構建容器,實現秒級啟動,在版本保存上更加輕便和低成本[7]。Docker的資源管理機制提供了默認資源設置和手動資源配置這兩種途徑,用戶在創建容器時可以使用默認資源配置,也可以根據需求分配CPU、內存和I/O資源,但是無法在運行過程中根據應用容器的實際資源需求來調整資源配置。Docker對所有容器的資源分配采用公平策略,不區分其中運行的應用類型。然而,在實時型應用容器和批處理型應用容器同時運行時,可能會由于資源分配不足或者不平衡導致實時型應用的性能無法達到服務要求;在服務強度(每秒最大請求數)變化時,無法及時調整資源配置。另外,Docker不限制容器實例的增加,其占用的總資源可能會超過物理機資源限制,使得一些正常運行的容器實例由于資源不足而異常中斷。當運行中的容器實例都偏向使用某種單一資源時,會造成該資源競爭激烈,而其他資源都處于空閑狀態的現象,導致物理機的整體資源利用率比較低。
目前已有一些針對實現Docker調度的研究工作。Monsalve等人[8]針對Docker集群環境提出使用CFS(Completely Fair Scheduler)調度模式,將切分時間片的概念擴展到虛擬化容器層級,解決CPU資源過度使用的問題。Dusia等人[9]針對Docker集群網絡負載的資源分配提出對應用容器設置不同的優先級,保證優先級高的應用容器可以獲得更多的網絡資源。Mcdaniel等人[10]提出設置容器優先級來為容器分配對應比例的I/O資源。Meng等人[11]基于時序分析提出了一種資源預測模型,避免計算資源浪費以及集群動態擴展中可能帶來的性能損失。Guan等人[12]提出了一種基于Docker容器的數據中心資源分配方法,合理調度數據中心資源。上述研究并沒有清楚地分析同構和異構容器下Docker運行時的資源-性能關系,也沒有提出基于異構容器類型的運行時精確動態調度機制,在保證性能的前提下,最大化資源利用率。
本文通過實驗分析了標準容器的資源使用情況和不同類型應用容器的運行特征,提出一種基于運行時的Docker動態調度算法,在容器實例運行過程中對其實際資源使用情況進行實時監控,根據應用容器的運行特征及當前資源使用情況判斷是否產生資源競爭,然后動態調整容器的資源分配,在保證實時型應用容器性能滿足服務要求的前提下,盡量減少對其他運行容器的性能影響。算法還根據節點運行現狀,推薦可運行的應用容器,提升整體資源利用率。
首先通過實驗測試方法,對于代表性應用的Docker實例,進行資源分配和性能實驗分析,為后續調度打下基礎。
實驗具體配置情況如表1所示。

Table 1 Configuration information of the test machine表1 測試機器配置信息
容器中運行的測試程序可以分為批處理型程序和實時型程序,根據其特征,分別選取了針對性的監控性能指標。對于批處理型程序,主要的監控性能指標有CPU利用率、內存占用量、讀磁盤數據量、寫磁盤數據量、執行時間和吞吐率;對于實時型程序,主要的監控性能指標有CPU利用率、內存占用量、實時平均響應時間、讀磁盤數據總量和寫磁盤數據總量。
執行時間只針對批處理型程序,是程序從開始到完成的總執行時間;實時平均響應時間只針對實時型程序,是每秒內測試程序對請求作出響應的平均時間。將測試程序運行中的每周期執行指令數IPC(Instructions Per Circle)和每秒執行的指令數IPS(Instructions Per Second)作為吞吐率的參考值。
為了了解測試程序在容器環境下的實際資源使用情況,本文選取Linux系統下的一個標準壓力測試程序Stress作為測試程序,對其容器化,分析CPU利用率和內存占用量。
Stress程序運行時,設置-c參數指定產生n個進程,每個進程反復計算隨機數的平方根,長時間占用CPU資源,模擬CPU密集型程序;設置-m參數指定產生n個進程,每個進程不斷調用內存分配malloc和內存釋放free函數,長時間占用內存資源,模擬內存密集型程序。
(1)模擬CPU密集型程序。
對容器實例采用默認資源配置,分別運行單個和4個標準測試容器(每個容器8進程),在運行過程中,對每一個容器實例的CPU資源使用情況進行實時監測。
圖1為單個和4個標準測試容器運行時的CPU利用率對比圖。圖1a中,當進程數為8時,單個容器的CPU利用率達到了800%;圖1b中,每個容器的CPU利用率在400%上下浮動,相比單個容器,CPU利用率下降了400%,這說明此時已經出現了CPU資源競爭的現象。

(2)模擬內存密集型程序。
設置 malloc內存的字節數為3 GB,在運行240 s后釋放內存。對容器實例采用默認資源配置,分別運行單個和4個標準測試容器(每個容器1進程),在運行過程中,對每一個容器實例的內存資源使用情況進行實時監測。
圖2為單個和4個標準測試容器時的實時內存占用量。由圖2可知,在內存資源充足時,每個標準測試容器在同一時間使用內存大小基本一致。因此,當多個容器同時運行時,需要對其內存需求量進行提前計算,以避免出現物理機內存空間不足的情況。

Docker為用戶提供了對CPU份額和塊I/O權重的設置方式,但是在使用過程中,如果不清楚測試程序的資源使用特征,很難確定設置資源類型和具體值。因此,在多個容器實例同時運行時,需要根據每個容器中運行程序的實際運行特征,來實時動態調整其資源分配情況,在資源有限的情況下,最大化物理機的整體資源利用率。
本文在容器環境下運行4個典型應用(Memcached[13]、 Speccpu2006[14]、 Parsec[15]、 Filebench[16]),并根據選取的性能指標總結它們的性能特征。
特征表如表2所示,其中最小CPU需求量指物理機上運行的同種應用容器的個數滿足服務品質協議SLA(Service-Level Agreement)要求的前提下,單個容器需要的最小CPU資源。表2中“-”表示該應用容器不存在該特征指標。

Table 2 Operating characteristics of a single application under containers表2 容器環境下單個應用運行特征表
動態調度算法實時監控運行中的容器實例,并結合運行容器及系統狀態,快速調整容器的資源配置;同時根據當前節點資源使用情況,推薦運行最優的實例類型。
通過三張元數據表來記錄調度過程中需要的數據:(1)應用運行特征表:存儲不同應用在容器環境下的運行特征;(2)容器實例狀態表:存儲每個容器實例中的運行應用情況和資源分配情況;(3)物理機資源使用表:存儲每個物理機上的CPU、內存使用情況。
(1)優先級設置。
默認設置:實時型應用的優先級高于批處理型應用,同種類型應用的優先級均為同一級。批處理型應用容器的優先級默認為1,實時型應用容器的優先級默認為2。
手動設置:用戶通過系統提供的接口,查看當前物理機上運行中的容器優先級設置情況,并在新增容器時手動指定優先級。優先級值越大,則優先級越高,可使用的資源數越多。在手動設置容器實例優先級方式下,依然優先滿足實時型應用的資源需求,將實時型應用容器的優先級設置為指定值的兩倍。
(2)優先級更改。
更改實時型應用優先級:判斷當前物理機是否出現資源競爭,若存在資源競爭,此時實時型應用容器在運行中會進行動態調控,可以保證實時型應用在滿足服務要求的前提下,只占用盡量少的資源,用戶只需要對優先級進行調整;若不存在,則修改容器實例狀態表中的優先級字段為指定值的兩倍,并重新計算分配CPU份額,修改相應字段值。
更改批處理型應用優先級:將容器實例狀態表中的指定容器的優先級修改為指定值,然后根據該引用的偏重使用資源類型,重新計算CPU份額或塊I/O權重,修改相應字段值。
(1)增加容器實例。
用戶通過系統提供的接口請求創建應用容器。在創建時需要根據應用容器的運行特征及節點資源使用情況,判斷是否可以完成新增操作。
(2)刪除容器實例。
通過系統提供的接口,可以根據實際需求停止并刪除正在運行的容器實例,同時刪除容器實例狀態表中對應的表項,更新物理機資源使用表。然后查詢應用狀態表獲得當前正在運行的所有應用容器的線程數之和,如果小于物理機最大線程數,則認為此時不存在資源競爭,將物理機資源使用表中的資源競爭狀態值置為0。
當物理機上運行環境變化時,可能會出現資源競爭。由于在容器實例運行前會判斷是否滿足內存限制,因此在運行過程中會存在競爭的關鍵性資源是CPU資源。通過以下兩種方式來判斷是否已經處于資源競爭狀態:
(1)當執行新增容器操作和刪除容器操作時,查詢并計算所有處于運行狀態的應用容器的線程數之和,如果大于物理機最大線程數,則存在資源競爭。
(2)當查詢到數據表中資源競爭狀態為0時,表示不存在資源競爭。之后每3 s獲取一次所有運行的應用容器的CPU利用率,并查詢其在無競爭狀態下的平均CPU利用率,對比兩個值,如果其差值超過100%,則認為可能出現了資源競爭情況,接下來每秒監測一次實時CPU利用率,總共監測3次,如果每次差值都超過100%,則確定處于資源競爭狀態。
當確定出現了資源競爭后,將物理機整體資源狀態表中的資源競爭狀態值更新為1。
在實際環境中,實時型應用容器的服務強度隨時可能發生變化,因此在服務強度發生變化時,需要及時調整資源分配。由于本文中選用的實時型應用容器的關鍵資源為CPU,因此在服務強度變化調度中,主要處理CPU資源的分配。
當沒有出現資源競爭時,只在服務強度增大時,增加實時型應用容器的CPU資源分配。當服務強度減小時,由于此時CPU資源充足,則不需要對分配的CPU資源進行調整。當出現資源競爭時,則適當減少容器實例當前的CPU份額值,僅保障其服務性能滿足SLA協議要求。
根據當前節點資源使用情況,推薦可運行的應用容器,減少與現有運行容器資源競爭的同時,充分利用空閑資源,提高整體資源利用率。針對CPU資源,當系統處于資源競爭狀態時,認為CPU資源已經處于競爭狀態,而內存資源和塊I/O資源都認為是空閑資源。查詢應用容器運行特征表,找到偏重使用空閑資源且競爭資源需求小的應用,并經過增加容器實例算法判斷可以增加后,向用戶推薦運行該應用容器。
使用Python語言實現動態調度系統,調度系統模塊圖如圖3所示。
動態調度系統命令接口如表3所示。

Table 3 Scheduling system command table表3 調度系統命令表
實驗平臺具體配置如表1所示。測試過程中,使用兩臺服務器分別作為測試主節點和客戶端代理。
4.2.1 多容器正常運行測試
同時運行1個Memcached容器和1個Parsec容器。圖4為使用調度系統前后2個容器運行過程中的CPU利用率。由圖5可知,使用調度系統基本不會對應用運行中的CPU利用率造成影響。
圖5為使用調度前后Memcached容器(服務強度為32 000)的平均響應時間。由圖5可知,在兩種情況下,平均響應時間基本處于應用運行正常范圍內。
表4為Parsec容器使用調度前后的運行性能情況,可以看出使用調度系統基本上沒有對Parsec應用運行的性能造成影響。




Table 4 Performance specifications of Parsec containers before and after scheduling表4 使用調度系統前后Parsec容器的運行性能指標
4.2.2 推薦新增應用容器測試
同時運行3個Parsec應用容器,根據表2,其最小CPU需求量為483%,已經達到了CPU資源使用限制,然后通過動態調度算法推薦機制,在節點上新增4個Filebench應用容器。表5為使用調度前后的容器性能情況。

Table 5 Performance of containers before and after scheduling表5 使用調度前后的容器性能情況

平均 I/O 吞吐率/(kb/s) 4 075.599 57.22 I/O平均響應時間/(ms/op)13.6 -
從表5中可以看出,在CPU資源基本達到飽和時,算法分析現有空閑資源,新增偏重相應資源的應用容器,將節點上能夠運行的容器實例數增大2.3倍時,對原本運行容器只造成了9.3%的性能損耗,提高了整體資源利用率。
4.2.3 資源競爭調度測試
同時運行1個Memcached容器(服務強度為80 000)、2個 Parsec容器和1個 Speccpu2006容器。由于運行容器中的線程數之和已經超過了測試物理機可同時運行的CPU線程數,因此在Parsec容器運行完成之前,系統處于資源競爭狀態。
表6為處于資源競爭狀態下,使用調度前后的性能指標對比。從表6中可以看到,在處于資源競爭狀態下的運行過程前309 s中,使用調度可以在90.29%的時間里滿足Memcached容器的響應時間小于10 ms的SLA性能要求;而不使用調度時,只有3.24%的時間內可以滿足性能要求,因此調度對于資源競爭下實時型應用的性能提升非常明顯。同時對比其他幾個批處理型應用的運行情況,可以看出,使用調度后兩個Parsec容器運行完成的平均時間,相比不使用調度,只增加了9 s,而使用調度后Speccpu2006容器的執行時間比不使用更短,這說明調度算法在優先保證實時型應用容器性能的同時,對批處理型應用容器造成的性能損耗非常小。

Table 6 Container operational performance indicators before and after scheduling表6 使用調度前后的容器運行性能指標
4.2.4 服務強度變化調度測試
同時運行1個Memcached容器、2個Parsec容器和1個Speccpu2006容器,在Parsec容器運行完成之前均處于CPU資源競爭環境。在運行過程中首先將Memcached容器的服務強度設置為48 000,在180 s后增大到80 000。
圖6a為使用調度前后Memcached容器平均響應時間。服務強度比較低時,兩種方式都能滿足性能要求。服務強度增大后,不使用調度的平均響應時間基本超過了10 ms;而使用調度后可以在很短的時間內將平均響應時間控制在10 ms內。圖6b為使用調度前后Memcached容器和Speccpu2006容器的CPU利用率。Speccpu2006容器在服務強度變化前后CPU利用率基本不變。Memcached容器在服務強度較低時,使用調度前后的CPU利用率相差不大;服務強度變大后,使用調度后的CPU利用率比不使用時略高。圖6c為使用調度前后2個Parsec容器的CPU利用率。由圖6c可知,使用調度與否對Parsec容器的CPU利用率影響并不明顯。因此,調度算法在優先保障實時型應用容器的性能的同時,也能保證批處理型應用容器的運行性能。
本文針對當前Docker的資源管理機制的不足提出了一種基于運行時的動態調度算法,在優先保證實時型應用容器的服務性能滿足SLA協議要求的同時,也能保證其他批處理型應用容器的運行性能。另外,調度推薦機制可以根據節點的資源使用情況,推薦運行最優實例類型,減少與現有運行容器的資源競爭,提高系統整體資源利用率。實驗表明,使用動態調度算法不會影響應用容器的正常運行。當節點上同時運行實時型和批處理型應用容器時,采用調度機制可以將實時型應用容器滿足服務要求的時間段延長87.5%,僅對同時運行的批處理型應用容器最多造成2.9%的性能開銷。此外,調度算法推薦機制將節點上能夠運行的容器實例數增大2.3倍時,對原本運行的批處理型應用容器最多只造成9.3%的性能損耗。接下來將進一步選取其他類型應用測試調度算法性能,并在該算法的基礎上研究集群的資源動態調整。
