雲計算與openstack學習(八)

Nova 組件如何協同工作 


Nova 物理部署方案

前面大家已經看到 Nova 由很多子服務組成,同時我們也知道 OpenStack 是一個分佈式系統,可以部署到若干節點上,那麼接下來大家可能就會問: Nova 的這些服務在物理上應該如何部署呢?

對於 Nova,這些服務會部署在兩類節點上:計算節點和控制節點。 計算節點上安裝了 Hypervisor,上面運行虛擬機。 由此可知: 1. 只有 nova-compute 需要放在計算節點上。 2. 其他子服務則是放在控制節點上的。

下面我們可以看看實驗環境的具體部署情況。 通過在計算節點和控制節點上運行 ps -elf|grep nova 來查看運行的 nova 子服務

計算節點

計算節點 devstack-compute1 上只運行了 nova-compute 子服務

控制節點

控制節點 devstack-controller 上運行了若干 nova-* 子服務

RabbitMQ 和 MySQL 也是放在控制節點上的

可能細心的同學已經發現我們的控制節點上也運行了 nova-compute。 這實際上也就意味着 devstack-controller 既是一個控制節點,同時也是一個計算節點,也可以在上面運行虛機。

這也向我們展示了 OpenStack 這種分佈式架構部署上的靈活性: 可以將所有服務都放在一臺物理機上,作爲一個 All-in-One 的測試環境; 也可以將服務部署在多臺物理機上,獲得更好的性能和高可用。

另外,也可以用 nova service-list 查看 nova-* 子服務都分佈在哪些節點上

從虛機創建流程看 nova-* 子服務如何協同工作

從學習 Nova 的角度看,虛機創建是一個非常好的場景,涉及的 nova-* 子服務很全,下面是流程圖。

  1. 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發送請求:“幫我創建一個虛機”

  2. API 對請求做一些必要處理後,向 Messaging(RabbitMQ)發送了一條消息:“讓 Scheduler 創建一個虛機”

  3. Scheduler(nova-scheduler)從 Messaging 獲取到 API 發給它的消息,然後執行調度算法,從若干計算節點中選出節點 A

  4. Scheduler 向 Messaging 發送了一條消息:“在計算節點 A 上創建這個虛機”

  5. 計算節點 A 的 Compute(nova-compute)從 Messaging 中獲取到 Scheduler 發給它的消息,然後在本節點的 Hypervisor 上啓動虛機。

  6. 在虛機創建的過程中,Compute 如果需要查詢或更新數據庫信息,會通過 Messaging 向 Conductor(nova-conductor)發送消息,Conductor 負責數據庫訪問。

上面是創建虛機最核心的幾個步驟,當然也省略了很多細節,我們會在後面的章節詳細討論。 這幾個步驟向我們展示了 nova-* 子服務之間的協作的方式,也體現了 OpenStack 整個系統的分佈式設計思想,掌握這種思想對我們深入理解 OpenStack 會非常有幫助。

OpenStack 通用設計思路

沒有人喜歡此內容

 


image143.5.png

API 前端服務

每個 OpenStack 組件可能包含若干子服務,其中必定有一個 API 服務負責接收客戶請求。

以 Nova 爲例,nova-api 作爲 Nova 組件對外的唯一窗口,向客戶暴露 Nova 能夠提供的功能。 當客戶需要執行虛機相關的操作,能且只能向 nova-api 發送 REST 請求。 這裏的客戶包括終端用戶、命令行和 OpenStack 其他組件。

設計 API 前端服務的好處在於: 1. 對外提供統一接口,隱藏實現細節 2. API 提供 REST 標準調用服務,便於與第三方系統集成 3. 可以通過運行多個 API 服務實例輕鬆實現 API 的高可用,比如運行多個 nova-api 進程

Scheduler 調度服務

對於某項操作,如果有多個實體都能夠完成任務,那麼通常會有一個 scheduler 負責從這些實體中挑選出一個最合適的來執行操作。

在前面的例子中,Nova 有多個計算節點。 當需要創建虛機時,nova-scheduler 會根據計算節點當時的資源使用情況選擇一個最合適的計算節點來運行虛機。

調度服務就好比是一個開發團隊中的項目經理,當接到新的開發任務時,項目經理會評估任務的難度,考察團隊成員目前的工作負荷和技能水平,然後將任務分配給最合適的開發人員。

除了 Nova,塊服務組件 Cinder 也有 scheduler 子服務,後面我們會詳細討論。

Worker 工作服務

調度服務只管分配任務,真正執行任務的是 Worker 工作服務。

在 Nova 中,這個 Worker 就是 nova-compute 了。 將 Scheduler 和 Worker 從職能上進行劃分使得 OpenStack 非常容易擴展:

  1. 當計算資源不夠了無法創建虛機時,可以增加計算節點(增加 Worker)

  2. 當客戶的請求量太大調度不過來時,可以增加 Scheduler

Driver 框架

OpenStack 作爲開放的 Infrastracture as a Service 雲操作系統,支持業界各種優秀的技術。 這些技術可能是開源免費的,也可能是商業收費的。 這種開放的架構使得 OpenStack 能夠在技術上保持先進性,具有很強的競爭力,同時又不會造成廠商鎖定(Lock-in)。

那 OpenStack 的這種開放性體現在哪裏呢? 一個重要的方面就是採用基於 Driver 的框架。

以 Nova 爲例,OpenStack 的計算節點支持多種 Hypervisor。 包括 KVM, Hyper-V, VMWare, Xen, Docker, LXC 等。

Nova-compute 爲這些 Hypervisor 定義了統一的接口,hypervisor 只需要實現這些接口,就可以 driver 的形式即插即用到 OpenStack 中。 下面是 nova driver 的架構示意圖

在 nova-compute 的配置文件 /etc/nova/nova.conf 中由 compute_driver 配置項指定該計算節點使用哪種 Hypervisor 的 driver

在我們的環境中因爲是 KVM,所以配置的是 Libvirt 的 driver。

不知大家是否還記得我們在學習 Glance 時談到: OpenStack 支持多種 backend 來存放 image。 可以是本地文件系統,Cinder,Ceph,Swift 等。

其實這也是一個 driver 架構。 只要符合 Glance 定義的規範,新的存儲方式可以很方便的加入到 backend 支持列表中。

再後面 Cinder 和 Neutron 中我們還會看到 driver 框架的應用。

Messaging 服務

在前面創建虛機的流程示意圖中,我們看到 nova-* 子服務之間的調用嚴重依賴 Messaging。 Messaging 是 nova-* 子服務交互的中樞。

以前沒接觸過分佈式系統的同學可能會不太理解爲什麼不讓 API 直接調用Scheduler,或是讓Scheuler 直接調用 Compute,而是非要通過 Messaging 進行中轉。 這裏做一些解釋。

程序之間的調用通常分兩種:同步調用和異步調用。

同步調用

API 直接調用 Scheduler 的接口就是同步調用。 其特點是 API 發出請求後需要一直等待,直到 Scheduler 完成對 Compute 的調度,將結果返回給 API 後 API 才能夠繼續做後面的工作。

異步調用

API 通過 Messaging 間接調用 Scheduler 就是異步調用。 其特點是 API 發出請求後不需要等待,直接返回,繼續做後面的工作。 Scheduler 從 Messaging 接收到請求後執行調度操作,完成後將結果也通過 Messaging 發送給 API。

在 OpenStack 這類分佈式系統中,通常採用異步調用的方式,其好處是:

  1. 解耦各子服務 子服務不需要知道其他服務在哪裏運行,只需要發送消息給 Messaging 就能完成調用。

  2. 提高性能 異步調用使得調用者無需等待結果返回。這樣可以繼續執行更多的工作,提高系統總的吞吐量。

  3. 提高伸縮性 子服務可以根據需要進行擴展,啓動更多的實例處理更多的請求,在提高可用性的同時也提高了整個系統的伸縮性。而且這種變化不會影響到其他子服務,也就是說變化對別人是透明的。

在後面各章節,我們都能看到 Messaging 的應用。

Database

OpenStack 各組件都需要維護自己的狀態信息。 比如 Nova 中有虛機的規格、狀態,這些信息都是在數據庫中維護的。 每個 OpenStack 組件在 MySQL 中有自己的數據庫。

小結

Nova 是 OpenStack 中最重要的組件,也是很典型的組件。 Nova 充分體現了 OpenStack 的設計思路。 理解了這種思路,再來學習 OpenStack 的其他組件就能夠舉一反三,清晰容易很多。

Nova 組件詳解 - 每天5分鐘玩轉 OpenStack(26)

沒有人喜歡此內容

 


本節開始,我們將詳細講解 Nova 的各個子服務。

前面架構概覽一節知道 Nova 有若干 nova-* 的子服務,下面我們將依次學習最重要的幾個。
今天先討論 nova-api 和 nova-conductor。

nova-api

Nova-api 是整個 Nova 組件的門戶,所有對 Nova 的請求都首先由 nova-api 處理。 Nova-api 向外界暴露若干 HTTP REST API 接口。 在 keystone 中我們可以查詢 nova-api 的 endponits。

客戶端就可以將請求發送到 endponits 指定的地址,向 nova-api 請求操作。 當然,作爲最終用戶的我們不會直接發送 Rest AP I請求。 OpenStack CLI,Dashboard 和其他需要跟 Nova 交換的組件會使用這些 API。

Nova-api 對接收到的 HTTP API 請求會做如下處理: 1. 檢查客戶端傳人的參數是否合法有效 2. 調用 Nova 其他子服務的處理客戶端 HTTP 請求 3. 格式化 Nova 其他子服務返回的結果並返回給客戶端

nova-api 接收哪些請求? 簡單的說,只要是跟虛擬機生命週期相關的操作,nova-api 都可以響應。 大部分操作都可以在 Dashboard 上找到。

打開Instance管理界面

點擊下拉箭頭,列表中就是 nova-api 可執行的操作。

OpenStack 用術語 “Instacne” 來表示虛擬機,後面我們將統一使用這個術語。

nova-conductor

nova-compute 需要獲取和更新數據庫中 instance 的信息。 但 nova-compute 並不會直接訪問數據庫,而是通過 nova-conductor 實現數據的訪問。

image177.png

這樣做有兩個顯著好處:

  1. 更高的系統安全性

  2. 更好的系統伸縮性

更高的安全性

在 OpenStack 的早期版本中,nova-compute 可以直接訪問數據庫,但這樣存在非常大的安全隱患。 因爲 nova-compute 這個服務是部署在計算節點上的,爲了能夠訪問控制節點上的數據庫,就必須在計算節點的 /etc/nova/nova.conf 中配置訪問數據庫的連接信息,比如

[database]

connection = mysql+pymysql://root:secret@controller/nova?charset=utf8

試想任意一個計算節點被******,都會導致部署在控制節點上的數據庫面臨極大風險。

爲了解決這個問題,從 G 版本開始,Nova 引入了一個新服務 nova-conductor,將 nova-compute 訪問數據庫的全部操作都放到 nova-conductor 中,而且 nova-conductor 是部署在控制節點上的。 這樣就避免了 nova-compute 直接訪問數據庫,增加了系統的安全性。

更好的伸縮性

nova-conductor 將 nova-compute 與數據庫解耦之後還帶來另一個好處:提高了 nova 的伸縮性。

nova-compute 與 conductor 是通過消息中間件交互的。 這種鬆散的架構允許配置多個 nova-conductor 實例。 在一個大規模的 OpenStack 部署環境裏,管理員可以通過增加 nova-conductor 的數量來應對日益增長的計算節點對數據庫的訪問。

 nova-scheduler 如何選擇計算節點 

沒有人喜歡此內容

 


本節重點介紹 nova-scheduler 的調度機制和實現方法:即解決如何選擇在哪個計算節點上啓動 instance 的問題。

創建 Instance 時,用戶會提出資源需求,例如 CPU、內存、磁盤各需要多少。

OpenStack 將這些需求定義在 flavor 中,用戶只需要指定用哪個 flavor 就可以了。

可用的 flavor 在 System->Flavors 中管理。

Flavor 主要定義了 VCPU,RAM,DISK 和 Metadata 這四類。 nova-scheduler 會按照 flavor 去選擇合適的計算節點。 VCPU,RAM,DISK 比較好理解,而 Metatdata 比較有意思,我們後面會具體討論。

下面介紹 nova-scheduler 是如何實現調度的。

在 /etc/nova/nova.conf 中,nova 通過 scheduler_driver,scheduler_available_filters 和 scheduler_default_filters 這三個參數來配置 nova-scheduler。

Filter scheduler

Filter scheduler 是 nova-scheduler 默認的調度器,調度過程分爲兩步:

  1. 通過過濾器(filter)選擇滿足條件的計算節點(運行 nova-compute)

  2. 通過權重計算(weighting)選擇在最優(權重值最大)的計算節點上創建 Instance。

scheduler_driver=nova.scheduler.filter_scheduler.FilterScheduler

Nova 允許使用第三方 scheduler,配置 scheduler_driver 即可。 這又一次體現了OpenStack的開放性。

Scheduler 可以使用多個 filter 依次進行過濾,過濾之後的節點再通過計算權重選出最適合的節點。

上圖是調度過程的一個示例:

  1. 最開始有 6 個計算節點 Host1-Host6

  2. 通過多個 filter 層層過濾,Host2 和 Host4 沒有通過,被刷掉了

  3. Host1,Host3,Host5,Host6 計算權重,結果 Host5 得分最高,最終入選

Filter

當 Filter scheduler 需要執行調度操作時,會讓 filter 對計算節點進行判斷,filter 返回 True 或 False。

Nova.conf 中的 scheduler_available_filters 選項用於配置 scheduler 可用的 filter,默認是所有 nova 自帶的 filter 都可以用於濾操作。

scheduler_available_filters = nova.scheduler.filters.all_filters

另外還有一個選項 scheduler_default_filters,用於指定 scheduler 真正使用的 filter,默認值如下

scheduler_default_filters = RetryFilter, AvailabilityZoneFilter, RamFilter, DiskFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter

Filter scheduler 將按照列表中的順序依次過濾。 下面依次介紹每個 filter。

RetryFilter

RetryFilter 的作用是刷掉之前已經調度過的節點。

舉個例子方便大家理解: 假設 A,B,C 三個節點都通過了過濾,最終 A 因爲權重值最大被選中執行操作。 但由於某個原因,操作在 A 上失敗了。 默認情況下,nova-scheduler 會重新執行過濾操作(重複次數由 scheduler_max_attempts 選項指定,默認是 3)。 那麼這時候 RetryFilter 就會將 A 直接刷掉,避免操作再次失敗。 RetryFilter 通常作爲第一個 filter。

AvailabilityZoneFilter

爲提高容災性和提供隔離服務,可以將計算節點劃分到不同的Availability Zone中。

例如把一個機架上的機器劃分在一個 Availability Zone 中。 OpenStack 默認有一個命名爲 “Nova” 的 Availability Zone,所有的計算節點初始都是放在 “Nova” 中。 用戶可以根據需要創建自己的 Availability Zone。

創建 Instance 時,需要指定將 Instance 部署到在哪個 Availability Zone中。

nova-scheduler 在做 filtering 時,會使用 AvailabilityZoneFilter 將不屬於指定 Availability Zone 的計算節點過濾掉。

RamFilter

RamFilter 將不能滿足 flavor 內存需求的計算節點過濾掉。

對於內存有一點需要注意: 爲了提高系統的資源使用率,OpenStack 在計算節點可用內存時允許 overcommit,也就是可以超過實際內存大小。 超過的程度是通過 nova.conf 中 ram_allocation_ratio 這個參數來控制的,默認值爲 1.5

ram_allocation_ratio = 1.5

其含義是:如果計算節點的內存有 10GB,OpenStack 則會認爲它有 15GB(10*1.5)的內存。

DiskFilter

DiskFilter 將不能滿足 flavor 磁盤需求的計算節點過濾掉。

Disk 同樣允許 overcommit,通過 nova.conf 中 disk_allocation_ratio 控制,默認值爲 1

disk_allocation_ratio = 1.0

CoreFilter

CoreFilter 將不能滿足 flavor vCPU 需求的計算節點過濾掉。

vCPU 同樣允許 overcommit,通過 nova.conf 中 cpu_allocation_ratio 控制,默認值爲 16

cpu_allocation_ratio = 16.0

這意味着一個 8 vCPU 的計算節點,nova-scheduler 在調度時認爲它有 128 個 vCPU。 需要提醒的是: nova-scheduler 默認使用的 filter 並沒有包含 CoreFilter。 如果要用,可以將 CoreFilter 添加到 nova.conf 的 scheduler_default_filters 配置選項中。

ComputeFilter

ComputeFilter 保證只有 nova-compute 服務正常工作的計算節點才能夠被 nova-scheduler調度。
ComputeFilter 顯然是必選的 filter。

ComputeCapabilitiesFilter

ComputeCapabilitiesFilter 根據計算節點的特性來篩選。

這個比較高級,我們舉例說明。 例如我們的節點有 x86_64 和 ARM 架構的,如果想將 Instance 指定部署到 x86_64 架構的節點上,就可以利用到 ComputeCapabilitiesFilter。

還記得 flavor 中有個 Metadata 嗎,Compute 的 Capabilitie s就在 Metadata中 指定。

“Compute Host Capabilities” 列出了所有可設置 Capabilities。

點擊 “Architecture” 後面的 “+”,就可以在右邊的列表中指定具體的架構。

配置好後,ComputeCapabilitiesFilter 在調度時只會篩選出 x86_64 的節點。 如果沒有設置 Metadata,ComputeCapabilitiesFilter 不會起作用,所有節點都會通過篩選。

ImagePropertiesFilter

ImagePropertiesFilter 根據所選 image 的屬性來篩選匹配的計算節點。 跟 flavor 類似,image 也有 metadata,用於指定其屬性。

例如希望某個 image 只能運行在 kvm 的 hypervisor 上,可以通過 “Hypervisor Type” 屬性來指定。

點擊 “+”,然後在右邊的列表中選擇 “kvm”。

配置好後,ImagePropertiesFilter 在調度時只會篩選出 kvm 的節點。 如果沒有設置 Image 的Metadata,ImagePropertiesFilter 不會起作用,所有節點都會通過篩選。

ServerGroupAntiAffinityFilter

ServerGroupAntiAffinityFilter 可以儘量將 Instance 分散部署到不同的節點上。

例如有 inst1,inst2 和 inst3 三個 instance,計算節點有 A,B 和 C。 爲保證分散部署,進行如下操作:

  1. 創建一個 anti-affinity 策略的 server group “group-1”

nova server-group-create --policy anti-affinity group-1

請注意,這裏的 server group 其實是 instance group,並不是計算節點的 group

  1. 依次創建 Instance,將inst1, inst2和inst3放到group-1中

nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst1 nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst2 nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst3

因爲 group-1 的策略是 AntiAffinity,調度時 ServerGroupAntiAffinityFilter 會將 inst1, inst2 和 inst3 部署到不同計算節點 A, B 和 C。

目前只能在 CLI 中指定 server group 來創建 instance。

創建 instance 時如果沒有指定 server group,ServerGroupAntiAffinityFilter 會直接通過,不做任何過濾。

ServerGroupAffinityFilter

與 ServerGroupAntiAffinityFilter 的作用相反,ServerGroupAffinityFilter 會盡量將 instance 部署到同一個計算節點上。 方法類似

  1. 創建一個 affinity 策略的 server group “group-2”

nova server-group-create --policy affinity group-2

  1. 依次創建 instance,將 inst1, inst2 和 inst3 放到 group-2 中

nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst1 nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst2 nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst3

因爲 group-2 的策略是 Affinity,調度時 ServerGroupAffinityFilter 會將 inst1, inst2 和 inst3 部署到同一個計算節點。

創建 instance 時如果沒有指定 server group,ServerGroupAffinityFilter 會直接通過,不做任何過濾。

Weight

經過前面一堆 filter 的過濾,nova-scheduler 選出了能夠部署 instance 的計算節點。 如果有多個計算節點通過了過濾,那麼最終選擇哪個節點呢?

Scheduler 會對每個計算節點打分,得分最高的獲勝。 打分的過程就是 weight,翻譯過來就是計算權重值,那麼 scheduler 是根據什麼來計算權重值呢?

目前 nova-scheduler 的默認實現是根據計算節點空閒的內存量計算權重值: 空閒內存越多,權重越大,instance 將被部署到當前空閒內存最多的計算節點上。

日誌

是時候完整的回顧一下 nova-scheduler 的工作過程了。 整個過程都被記錄到 nova-scheduler 的日誌中。 比如當我們部署一個 instance 時

打開 nova-scheduler 的日誌 /opt/stack/logs/n-sch.log(非 devstack 安裝其日誌在 /var/log/nova/scheduler.log)

日誌顯示初始有兩個 host(在我們的實驗環境中就是 devstack-controller 和 devstack-compute1),依次經過 9 個 filter 的過濾(RetryFilter, AvailabilityZoneFilter, RamFilter, DiskFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter),兩個計算節點都通過了。

那麼接下來就該 weight 了:

可以看到因爲 devstack-controller 的空閒內存比 devstack-compute1 多(7466 > 3434),權重值更大(1.0 > 0.4599),最終選擇 devstack-controller。

注:要顯示 DEBUG 日誌,需要在 /etc/nova/nova.conf 中打開 debug 選項

[DEFAULT] debug = True

nova-scheduler 就是這些內容了,稍微有些複雜哈(因爲靈活嘛),大家這兩天可以好好消化一下。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章