資源以物理機(ComputeNode)為粒度統計和上報,所有的資源都從屬於單個ComputeNode。這樣對於一些共享的外部資源,例如 EBS、neutron的ip個數等,不能很好的管理和調度。每增加一種資源,就要相應的修改對應的ComputeNode代碼進行統計和管理,不利於橫向擴展。調度之間存在並發問題,每個調度服務之間的實時資源視圖不一致,導致調度的目標節點有延後性,不夠準確。
Pike版本的資源管理
Pike版本將資源抽象出來,增加一層資源管理層,並且區分資源提供者ResourceProvider、資源項ResourceClass、資源清單Inventory、資源分配Allocation,它們的對應關系如下:
ResourceProvider資源提供者
資源提供者表明資源的擁有者,單個物理機、EBS集群都是一個ResourceProvider。每個ResourceProvider可以提供數個ResourceClass的資源。例如ComputeNode是一個ResourceProvider,它提供多個ResourceClass,包括VCPU、MEMORY_MB、DISK_GB。EBS集群也是一個ResourceProvider,提供一個ResourceClass叫做Volume。
class ResourceProvider(API_BASE): """Represents a mapping to a providers of resources.""" id = Column(Integer, primary_key=True, nullable=False) uuid = Column(String(36), nullable=False) name = Column(Unicode(200), nullable=True) generation = Column(Integer, default=0) # 用於解決並發 can_host = Column(Integer, default=0) # 當前資源提供者是否可以作為宿主機
ResourceClass資源項
資源項表明當前資源的類型和名稱,供用戶區分不同的資源。它只表明資源的名稱類別,不包含具體的資源數量等信息。每個資源類型包含數量不等的具體資源Inventory,可以由多個ResourceProvider提供。例如,MEMORY_MB這個資源項,每個ComputeNode都提供該項資源。每個MEMORY_MB都有一個對應的Inventory,表明具體的資源數量、超售比、保留值等資源的配置。
class ResourceClass(API_BASE): """Represents the type of resource for an inventory or allocation.""" id = Column(Integer, primary_key=True, nullable=False) name = Column(String(255), nullable=False)
Inventory資源詳情
資源詳情表明ResourceClass中的具體資源和一些配置。例如對於某臺ComputeNode作為一個ResourceProvider,提供一項資源MEMORY_MB並且該項資源有一個詳細的描述Inventory。
class Inventory(API_BASE): """Represents a quantity of available resource.""" id = Column(Integer, primary_key=True, nullable=False) resource_provider_id = Column(Integer, nullable=False) resource_class_id = Column(Integer, nullable=False) total = Column(Integer, nullable=False) reserved = Column(Integer, nullable=False) # 保留的資源,例如一臺ComputeNode保留給系統的內存,不用於分配 min_unit = Column(Integer, nullable=False) # 分配的最小值,例如VCPUS是1, MEMORY_MB是1024等 max_unit = Column(Integer, nullable=False) # 分配的最大值,例如VCPUS是32, MEMORY_MB是128*1024 step_size = Column(Integer, nullable=False) # 分配的最小單位,例如MEMORY_MB是1024,只能按照G來分配,不能分配512MB allocation_ratio = Column(Float, nullable=False) # 超售比 實際可分配資源=total * allocation_ratio
Allocation資源分配
資源分配表明一個實例需要的一項資源項ResourceClass的具體數值,以及該項資源分配給誰。例如一個雲主機需要2GB內存,那麽就用一個Allocation表示並單獨記錄在數據庫中,等同於之前版本中的Instance中記錄的一項資源的使用(memory_mb_used)。
class Allocation(API_BASE): """A use of inventory.""" id = Column(Integer, primary_key=True, nullable=False) resource_provider_id = Column(Integer, nullable=False) # 資源提供者 consumer_id = Column(String(36), nullable=False) # 資源消耗者 resource_class_id = Column(Integer, nullable=False) # 資源名稱 used = Column(Integer, nullable=False) # 具體數值
以上是資源管理的具體分工,它們的對應關系如下:
ResourceClass: CPU MEMORY_MB DISK_GB ↓ ↓ ↓ ComputeNode -> ResourceProvider -> Inventory(CPU) Inventory(MEMORY_MB) Inventory(DISK_GB) ↙ ↓ ↘ Instance(2core, 2g, 100disk): Allocation(MEMORY_MB: 2G) ↓ ↘ Instance(4core, 4g, 200disk): Allocation(MEMORY_MB: 4G) ↘ Instance(2core, 4g, 100Disk): Allocation(MEMORY_MB: 4G) MEMORY_MB: 8G used
這樣ComputeNode只是作為所有資源中的一個ResourceProvider,所有的資源提供者都是作為平等的ResourceProvider參與調度和資源管理,並且支持動態添加資源類型。
2.並發調度
之前的並發調度
之前的版本中多個調度節點之間沒有同步機制,每個調度節點每次調度時直接從數據庫獲取資源視圖,計算匹配的目標,這樣導致各個節點之間資源視圖不能及時更新,有延後性。只能通過CompudeNode中ResourceTracker的資源鎖和rescheduler來保證資源的最終一致。
Pike並發調度
在新的資源管理下,調度成功後會將消耗的資源記為一個Allocation並寫入數據庫,在寫入數據庫時利用’compare and update’策略實現同步,保證只有在有資源的情況下Alloction才更新成功,選擇的目標才有效。原理如下。
deadlock_retry: $ID, $GENERATION = SELECT id, generation FROM resource_providers WHERE ( <QUERY_TO_IDENTIFY_AVAILABLE_INVENTORY> ); BEGIN TRANSACTION; FOR $RESOURCE_CLASS, $REQUESTED_AMOUNT IN requested_resources: INSERT INTO allocations ( resource_provider_id, resource_class_id, consumer_id, used ) VALUES ( $RESOURCE_PROVIDER_ID, $RESOURCE_CLASS, $INSTANCE_UUID, $REQUESTED_AMOUNT ); $ROWS_AFFECTED = UPDATE resource_providers SET generation = $GENERATION + 1 WHERE generation = $GENERATION; IF $ROWS_AFFECTED == 0: ROLLBACK TRANSACTION; GO TO deadlock_retry; COMMIT TRANSACTION;
通過事物保證每次Allocation的數據庫操作的原子性。獲取資源視圖和更新資源視圖時,通過generation來保證資源一致。總的調度邏輯如下:
HOST = [] FOR $RESOUCE_CLASS, $REQUEST_ALLOCATION FOR REQUESTED_RESOUCES: GET $RESOUCES_PROVIDERS, $GENERATION FOR $RESOUCE_CLASS GET $INVENTORY AND $ALLOCATIONS FOR RESOUCE_CLASS AND RESOUCE_PROVIDER IF $INVENTORY["total"] - sum($ALLOCATIONS["used"] >= REQUEST_ALLCOATION: $HOST.append($RESOURCE_PROVIDER) FILTER $HOSTS WEIGHT $HOSTS FOR $HOST IN $HOSTS: IF (UPDATE ALLOCATION SUCCESS): SELECTED $HOST; return else: ROLLBACK ALLOCATION; IF NO $HOST SELCETED: RAISE NoVildHost
(完)
Tags: 資源 ResourceProvider 調度 提供者 ResourceClass quot
文章來源: