OpenStack 的各組件的架構和功能
Nova 組件解析
負責虛擬機創建、管理和銷毀、提供計算資源服務的 Nova;
通過 Nova 可以實現:
- 訪問虛擬機
- 創建和啟動虛擬機
Nova 是怎么運作的?除了圖形界面和命令行之外,我們還需要怎樣去配置和使用 Nova?
1-1. Nova 的架構
Nova-console 和 Nova-consoleauth 這兩個組件,主要是為了讓用戶能夠通過 VNC 客戶端或 SPICE 客戶端來訪問虛擬機的界面。推薦使用 SPICE 客戶端,因為SPICE 客戶端提供了很多高級的特性,比方說,對 USB 設備的支持,SPICE 還支持多屏顯示等等功能,這些特性在桌面虛擬化環境中非常有用處,在桌面雲環境中也非常有用,但使用 SPICE 就需要對 nova.conf 文件做一些修改,比如:
// nova.conf的修改:
[spice]
enabled = True [default] vnc_enabled = False
1-2. 虛擬機的調度機制
- 第一個方面:placement(放置)。 把虛擬機放在哪個物理機上啟動
- 第二個方面:migration(遷移)。 從哪個物理機遷移到哪個物理機上
Nova 有一個組件叫作調度器,Scheduler 直譯過來就是調度器,它實際上只完成了 placement 的工作,migration 實際上是由其它組件來協同完成的。
在 OpenStack 的上下文里,特指這個運行的 nova-compute 服務的機器才叫做宿主機。
1-3. Nova 對虛擬機的調度機制
通過修改 nova.conf 文件修改調度器的配置,nova 默認的這個調度器成為 filter scheduler,這種調度器分兩步來決定虛擬機的位置。第一步先經過一些 filters,filters 的每一種都代表着一種限制條件,通過這些 filters 選出來一些可用的 host,作為第二步的輸入;第二步是稱重,實際上是對宿主機進行排序。
下面舉個例子進行說明,這里有一個非常常用的 filter 叫作 Ramfilter,Ram:設置超配比例。
[ Nova 對虛擬機的調度機制:]
(1)把所有的 filters 都用上:
scheduler_available_filters = nova.scheduler.filters.all_filters
(2)選擇其中的一部分:
scheduler_default_filter = RetryFilter, AvailabilityZoneFilter, RamFilter, ComputeFilter,ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter
(3)用 Python 實現自己的 filter,老師用 RamFilter 做的例子如圖所示:
對虛擬機進行排序(稱重 weighting)
兩種選擇:
- 希望負載盡可能均衡
- 希望負載盡可能集中,用盡可能少的 host 來承載我們的虛擬機,我們使用的 host 就會比較少,那么運維的成本包括用電、制冷的費用都會比較低
Swift 組件解析
提供對象存儲服務的分布式存儲 Swift;
[ Swift 的特點:]
- Swift 歷史比較長
- Swift 比較獨立(和其他組件的耦合度比較低;不依賴於第三方的軟件或設備,甚至不依賴於 Keystone 做用戶的認證和授權;)
- Swift 是做對象存儲的(這里的對象存儲就是指,采用 RESTful 接口,支持直接從互聯網訪問存儲系統進行數據的讀寫。對象存儲往往采用扁平的數據組織形式,在文件數量很多的情況下不至於出現明顯的性能衰減,也就是我們說對象存儲的概念哦
OpenStack 其它的很多項目實現具體功能的時候往往需要依賴於第三方的軟件或設備,比如說 Nova 啟動虛擬機、管理虛擬機就必須通過一個第三方的 Hypervisor,還有 Cinder 提供塊存儲服務必須通過第三方的存儲設備。Swift 就不同了,Swift 可以從上面的 RESTful 接口把堆棧一直管到底,以至於管到最后把數據到底放在哪個服務器的哪個硬盤上都可以做到,整個是完整的存儲系統,現在有專門基於 Swift 實現的存儲系統例如 swiftstack;
swift 提供的對象存儲 和 ceph這類分布式存儲
[ Swift 數據的組織形式:]
扁平的組織形式,Swift 的數據組織形式分為三級,只有這三級
- Account
- Container
- Object
與可以分 N 多層能夠不斷有文件夾的創建的數據組織形式不一樣,Swift 的整個存儲結構從邏輯上划分為一個個的 Account,然后每個 Account 底下再分為一個個的 Container,每個 Object 實際上是放在每個 Container 底下的。
[ Swift 的接口:]
與 OpenStack 的其它組件的接口很類似,也是 RESTful Web API,總共有四個部分組成。第一個是 HTTP 操作(GET/PUT/DELETE/POST);第二個是認證信息(主要是身份信息);第三個是指示資源地址的 URL(具體到 Swift,應該包含存儲系統的域名/地址加上存儲數據的 Account、Container、Object 的整個信息的完整的 URL);第四個是數據與元數據。
例子:
crul -i -X GET
https://storage.clouddrive.com/v1/my_account?format=json\-H
"X-Auth-User:jdoe" -H "X-Auth-Key:jdoepassword"
storage.clouddrive.com 是對象存儲的域名或者說地址,接着取 my_account 下面的 Container 的信息,后面帶的是用戶的認證信息 username 和 password 。先看下方返回結果:
根據上圖我可以發現,API 調用以后返回的結果 Response 主要分為兩段:1.頭部。有兩個要點,一個是它給出了這個 Account 下面 Container 的數量是 2,然后這個 Account 里面總共用了多大的存儲空間,用了多少的字節或者說存了多少字節的數據進去,這里是 14。接着看下面的內容:
根據上圖我可以發現,這是一個 json 的返回形式,把每一個 Container 都列出來了,可以看到第一個 Container 里面沒有 Object,所以它占用的字節數也是 0。
[ Swift 的軟件架構:]
如圖所示:
從上面下來是 Swift API,通過 Proxy Server 來實現,Proxy Server 左右兩邊分別連了兩個東西:一個是做身份認證用的,往往是 Keystone,右邊是一個 Cache 服務,這個 Cache 不去緩存實際的 Object 的數據,緩存的主要是用戶的身份信息,別的會緩存一點其他的東西,不會去緩存數據,所以 Swift 是沒有緩存的,原生設計就是沒有緩存的;從 Proxy Server 下來會有三個 ring:Object Ring,Container Ring 和 Account Ring,ring 是一致性 HASH 實現。(一致性 HASH 是什么? 分布式存儲系統中為了把數據分布到各個節點上,用的一種數據結構就是一致性 HASH,后續會詳細展開探討。)下面是實際提供存儲服務的進程或者說 Server,有 Object Server,Container Server 和 Account Server,有一個統一的稱呼:Storage Server,對這些信息的默認的存儲方式都是三副本。
[ 搭建 Swift 時需要的注意事項:]
Swift 的部署需要注意哪些?一個典型的 Swift 部署像圖里畫的樣子:
圖所示的是一個小型的 Swift 集群典型配置,想讓 Swift 進行良好的工作,需要注意一些容易被人去忽視和經常犯錯的地方,避免對 Swift 產生一些錯誤的認識,誤認為 Swift 可靠性不行或性能不行,注意下面五個點:
- 采用的是全對等架構,就是每個節點每個 Server 都是一樣的,有 Proxy Server,有 Object Server, 有 Container Server 等等都是一樣的。(實際上 Swift 從軟件到部署都是一個全對等的概念在里面,是 Swift 架構的最突出的特點之一,讓 Swift 能夠很好的去做橫向擴展,沒有單點故障)。
- 怎么把服務器組織起來呢?實際上,上面它有一個 Load Banlancer,能夠把服務器(實際上是 Proxy Server)組成一個集群,Load Banlancer 能夠把用戶的這些請求給它分配到各個實際的服務節點上。
- 每個服務器是一個zone Swift 是要求分 zone 的,要把服務器存儲區域給隔離開,然后把這些副本放到不同的 zone 里面去,所以這地方小規模集群一般都是讓每個 Server 作為一個 zone。
- 作為小規模的部署,服務器的數量最少是5個(官方推薦的最小集群,達到比較好的效果)。
- 不要用虛擬機(存數據的地方都不可能說是用虛擬化去做支撐的),不要用 RAID(用服務器用盤陣的時候經常會對它做 RAID,但是做完 RAID 以后會對我們的 Swift 帶來一些性能上不可預知的結果,Swift 本身具有數據管理的機制)。
[ Swift2.0的新功能:]
存儲策略:讓用戶能夠自由的選擇數據的存儲策略
Swift 的存儲策略一部分由搭建存儲系統的 Deployer 決定,另外一部分是由使用存儲系統的 Client 決定的,用戶在這個里面以 Container 為力度,可以去指定這個存儲策略。
Cinder 組件解析
提供塊存儲服務的 Cinder;
傳統數據中心的存儲設備經常聽到 SAN 或者盤陣這些詞匯,是通過網絡連接給服務器提供存儲空間的一類設備。硬盤對應了一個術語:塊設備,傳統存儲也叫塊存儲。SAN 是典型的塊存儲,還有一類存儲設備叫作 NUS。硬盤或者 LUN 是掛在服務器上的。
如果是在虛擬化環境之下,也可以像雲硬盤一樣掛載到虛擬機上,作為虛擬機的一個硬盤,也就是虛擬機的一個卷 Volume。Cinder 是提供塊存儲服務的,有時候也會說 Cinder 提供卷管理或者說是提供卷服務的。
SAN 設備與網絡的兩種連接主要有兩種形式:第一種是 Fibre Channel(光纖通道,簡稱 FC),另外一種是 iSCSI(是基於以太網協議的)。
如果是 FC,需要在服務器上裝上 HBA 卡,用專用的光纖給它連到存儲設備上。如果是 iSCSI 的話,走的是以太網協議和 IP 協議,所以不需要專用存儲的網絡連接了,用 iSCSI 的越來越多。
3-1 Cinder的組成架構
如上圖所示,Cinder 的架構還是非常簡單的,里面有 Cinder 的 API,是用來提供 RESTful API 的,供客戶端或者是其它組件來訪問;中間還有一個 database,同樣還有消息隊列,Cinder 比較核心的兩個組件:左邊的 Cinder Scheduler 調度器,右邊的 Cinder Volume。
通常情況下,如果我們使用了多個存儲設備來做 Cinder 的后端,通常需要運行多個 Volume 的實例,如圖示意:
Scheduler 的任務是在有訪問請求的時候、有創建 Volume 請求的時候選擇通過哪個 Cinder Volume 實例來創建卷,這就是 Scheduler 和 Volume 的分工。
重點分析一下 Volume,特別需要注意的一點是數據的流向,與 Swift 的區別是比較大的,Swift 對它的操作不僅僅是通過 Swift Proxy Server 提供的 RESTful API 進行操作,它的數據也是通過 RESTful API 走的,我們要把數據放在 Swift 里面或者從 Swift 里把數據拿出來,都通過 RESTful Web API。但是在 Cinder 不一樣,Cinder API 基本上只能提供一些操作和管理功能,是直接通過 FC/iSCSI 傳輸數據到服務器。那 Volume 的作用到底是什么呢?數據不會通過 Volume 去走,也不會通過 RESTful API。實際上 Volume 里邊有一個模塊叫 Volume Driver,這個 driver 針對每一個存儲設備都不一樣,也被稱為 Volume 插件,這個插件往往是由存儲設備的廠商提供的。Volume 的核心主要是作用在這個 Driver 上,driver 的作用是什么?Driver 跟我們通常的單機的操作系統的驅動的含義不一樣,這里的 Volume Driver 驅動主要是相當於一個適配的功能,把后端的設備的接口適配成 Cinder 的統一接口。
[ 補充:什么是軟件定義存儲?]
隨着我們數據中心的存儲設備數量和種類以及上層應用的種類越來越多,上層應用對存儲的需求也各不相同,所以就出現一個問題,怎么樣去把這些設備給整合起來從而怎么樣去更好的服務於上層應用,於是就出現了軟件定義存儲的概念。看一張從 EMC 官網上得到的圖:
軟件定義存儲,一方面是為了隱藏底下的硬件的異構性,不論我們用的是什么硬件,不論我們用的是什么規模的硬件,不論我們用的是什么型號的硬件,不論我們用的是哪個廠商的硬件,只要軟件定義存儲這一套軟件支持,它對上層隱藏了底層的異構性;另外一方面是對上層應用的支持,提供了多樣化存儲的接口,比如說經常提到的 Hadoop 的 HDFS,還有提供對象存儲的接口,還有塊存儲的接口,用來支持不同的應用。有了這樣一個系統,那么加存儲設備的人和構建底下這些存儲基礎設施的人就不用去擔心上層應用會怎么樣,只需要按照現在存儲規模的需求和性能的需求往上加存儲設備就行了,或者說只要擴大現在的存儲設備的容量就行了,上層應用也不用擔心底下怎么樣去適應。只要暴露接口就行了。
OpenStack 的存儲最主要的兩個組件是 Swift(提供的是對象存儲的接口)和 Cinder(提供了一堆 driver,Volume 里面嵌入的,這些 driver 可以調用不同的存儲設備,只要有 driver 就可以把存儲設備給連接上,實際上就起到了屏蔽底層硬件異構性的作用。第二,Cinder 提供的是塊存儲的接口),實際上也就是說我們現在在網頁上這個層面,至少已經支持了最常用的兩種存儲接口,正好對應了軟件定義存儲的兩個方面。基於 OpenStack 我們其實是可以做一個軟件定義存儲的系統出來的。
Swift 提供對象存儲時,對底層硬件是否有異構性限制。
Neutron 組件解析
軟件定義網絡項目 Neutron;
Nrutron 又被稱為 OpenStack networking。
有一個概念叫作層(Tier/Layer)。兩種層有什么區別呢?先說一下傳統的網絡,傳統數據中心的網絡是分為幾個級別的,首先是服務器接入第一級交換機叫作接入交換機,接入交換機往往是在一個機架的頂部(所以也被稱為架頂交換機 TOR),可能是有堆疊的比如說是兩個交換機來實現的,如下圖所示最上部分的兩個交換機。然后,會接入一個叫作匯聚層的交換機(匯聚交換機),往往是放在一排機架的頂頭位置,這一層往往被叫做匯聚層。然后接入的是核心交換機,把匯聚交換機連起來的交換機就是核心交換機,核心交換機是數據中心非常大的網絡節點,往往也不只一個。
傳統中心的數據網絡分為接入層、匯聚層和核心層,也叫作三個層次(Tier)。如今的網絡對三層網絡做了演進。
但是在 OpenStack 里,層不是指的 Tier,而是協議棧的層,也就是 Layer。根據 ISO 的網絡模型,實際上網絡是分為七個 Layer,OpenStack 主要關注的是第二和第三層。第二層是數據量層 Datalink,第三層是網絡層 Network。交換機 Switches 是工作在數據量層的典型設備,而路由器 Routers 是典型的工作在網絡層的,Neutron 主要關注這兩層。
假如沒有 OpenStack Neutron ,虛擬化世界的網絡是什么樣子的? 會使用虛擬網橋,是一個二層設備,是軟件實現的網橋,不存在物理信號的問題,被認為是一個虛擬的跑在服務器寄主機內部的交換機,把虛擬機都連在這個交換機上,如下拓撲圖:
如果僅僅是做一個虛擬化的環境,問題倒是不大,但如果放在雲的環境上就會出現問題了,因為雲涉及到租戶之間流量隔離的問題,網橋無法滿足這種需求,網橋完全是一個連通的,跟一個普通的交換機沒啥區別。那么,說一說 Nova-network 又是怎么樣的情況呢?
Nova-network 在以前的網橋的基礎上,加了一個模塊,因此可以有兩種工作模式。第一種是:Flat DHCP 工作模式。可以提供像 DHCP 一樣的功能。
第二種是:基於 VLAN 的隔離。可以使用 VLAN 的方式把各種租戶隔離開,勉強滿足了雲的需求,在一個對網絡要求不是很高的簡單雲計算環境中使用 Nova-Network 就可以了。
事實上我們還有其它的一些需求,比如我們要實現一個比較大的二層,要實現對流量的控制,Nova-network 就不能滿足要求了。那么,Neutron 在一種非常普遍的環境中跟 Nova-network 有多大的區別呢?
[ Neutron 有的功能:]
- 提供 VLAN 的隔離
- 提供軟件定義網絡 SDN(比如:L2-in-L3 的隧道,像 VXLAN、GRE 隧道;還支持 OpenFlow 協議)
- 支持第三方的 API 擴展
- 支持第三方的 Plugin 擴展
我們可以開發自己的組件、插件放在 Neutron 生態里,與 Cinder 非常類似。
Neutron 支持租戶創建自己的虛擬網絡,看一個例子如圖:
圖里有兩個租戶,每個租戶創建了自己的網絡,有自己的路由器,租戶之間的網絡是隔離的,並且每個租戶還可以定義自己網絡的拓撲,這點很重要,復拓撲(Rich Topologies)是開發 Neutron 項目的重要目的。
在傳統的物理網絡架構中,會希望對每層應用都互相使用相對隔離的網絡,然后我們可以在上面對每層進行負載均衡或者是做一些集群的方案,但是在虛擬世界中,如果我們使用 Nova-network 很難實現。而 Neutron 誕生以后,這個問題就得到了解決。后續學習的 Heat 在工作的過程中就利用了 Neutron 的功能,是 Neutron 的一個很好的應用案例。
PS:構建一個基於三層架構的Web服務
- 第一層:Web 頁面服務器
- 第二層:應用服務器
- 第三層:數據庫服務器
Horizon 組件解析
提供基於 Web 的一個 GUI 的 Horizon;
Horizon 提供可視化的 GUI 圖形界面。讓用戶去操作這些項目使用的各種資源。Horizon 的內部架構是怎么樣的?我們如果要做二次開發,應該怎么去做?了解 Horizon 可以不妨先去了解 Python 的一個 Web 開發框架 Django。
[ 內部分為三個層次:]
- Dashboard
- PanelGroup
- Panel
每一組可視化的界面都是 PanelGroup,每一個 Dashboard 在 Django 里都是一個 App,OpenStack 的文件夾里的 openstackdashboard 文件夾里有一個 settings.py 文件,里面有一個變量叫 INSTALLEDAPP 定義了目前存在的這些 dashboard
官方的社區版里面一般有四個 dashboard
1. openstack_dashboard.dashboards.project // 普通用戶 2. openstack_dashboard.dashboards.admin // 管理員 3. openstack_dashboard.dashboards.settings // 右上角設置面板 4. openstack_dashboard.dashboards.router // 一般是看不見的
Glance 組件解析
提供虛擬機鏡像管理和存儲服務的 Glance;
虛擬機鏡像存儲服務的,典型的對象存儲應用
[ Glance 的架構:]
Glance API Server 提供 RESTful API,所有的訪問請求會通過它 Glance Registry Server 組件對鏡像進行注冊,還可以提供鏡像檢索服務 Glance 可以使用不同的存儲后端,有亞馬遜的 S3 Store,有 Swift 對象存儲,有 HTTP Store,有 Filesystem Store(Glance 本地的一個文件存儲)
PS:對象存儲這種扁平的數據組織結構的存儲方式一定是將來的一個趨勢,為什么?人在使用計算機的時候會使用一級一級的目錄去把文件塞到不同的目錄底下,建立一個樹狀的結構是為了方便我們自己去查找。而在寫程序的時候,是通過數據庫去管理這些數據,通過索引去管理這些元數據,並不需要一級一級的目錄結果,Glance 通過 Registry Server 去找到這些鏡像、檢索這些鏡像,所以我們的程序真正需要的是一個地址加上一個 ID,或者是一個地址加上一個 key。那么,對象存儲正好就是地址加上 ID。所以說,對象存儲會逐漸取代分布式文件系統,成為 Server 端的主流。(PS:當然,塊存儲是被替代不了的)不知道為什么。
[ Glance的緩存機制:]
把 Glance API Server 做橫向擴展,做一個負載均衡的集群,下面再轉到實際的存儲后端去,但是可能某些鏡像會特別的有很多訪問,這樣的話某一個點的壓力還是會很大,於是就有了緩存機制,每個通過 Glance 到達服務器的 Server 端的鏡像,都會緩存到 API Server 上,注意,如果我們有多個 API Server,隨着用戶訪問請求的增多,被經常訪問的那個同一個鏡像會在每一個 API Server 上都有一個,醬紫的話,在后續再有訪問請求的時候就會直接用 API Server 上的鏡像文件,而不會再去訪問到存儲后端上來,這個機制對終端用戶來說是透明的,終端用戶並不清楚這個 Glance 服務獲取的鏡像到底是存在哪里的。
[ 緩存管理需要注意的幾個地方:]
- 對 Cache 總量大小的限制(周期性的運行,
glance-cache-pruner --image_cache_max_size=*
) - 要清理一些狀態異常的 Cache 文件(
glance-cache-cleaner
) - 如果新加了一個 API Server 到負載均衡的集群環境里,新的 API Server 上沒有緩存,所以還提供了預取某些熱門鏡像到新增的 API 節點中的機制(
glance-cache-manage --host=<HOST> queue-image <IMAGE_ID>
)PS:這也是在雲環境中經常會去使用的一種方法 - 我們可以手動刪除緩存鏡像來釋放空間
Keystone 組件解析
提供身份認證和授權的 Keystone;
在 OpenStack 里面 Keystone 有兩個作用。
- 第一個是:權限管理(用戶的建權、授權;涉及到的概念有用戶、租戶、角色),租戶是一組用戶的集合,租戶可以是一個企業一個部門一個小組等等。租戶與用戶之間往往是多對多的關系。
- 第二個是:服務目錄(服務、端點),OpenStack 的每個服務需要在 Keystone 里注冊以后才能提供給用戶去使用,端點 Endpoint 可以理解為服務暴露出來的訪問點,,每一個端點都對應一個服務的訪問接口的實例。
關於角色 Role,安全領域有一個叫作基於角色的訪問控制,Keystone 也是這樣的一種安全機制,Role 是 Keystone 的訪問機制里面的核心。那么對於 Role 怎么去操作呢?它最重要的命令就是 user-role-add
,簡單來說這個命令就是指定某個用戶具有某個角色。還有一個非常重要的用途,那就是實現用戶和租戶多對多的關系。下面舉個例子怎么樣去實現用戶和租戶之間多對多關系的操作方法。
// 創建租戶tenant1
# keystone tenant-create --name tenant1 --enabled true // 創建另外一個租戶tenant2 # keystone tenant -create --name tenant2 --enabled true // 創建兩個用戶 user1 和 user2 和登錄密碼 # keystone user -create --name user1 --tenant -id <tenant-id of tenant1> --pass password --enabled true # keystone user -create --name user2 --tenant -id <tenant-id of tenant2> --pass password --enabled true // user-role-add 命令,這里的-user-id 實際上是 上面的 user2 的 id,-tenant-id 實際上是前面我們的tenant1 的 id,將 user2 加到 tenant1 里面,tenant1 就對應了兩個用戶:user1 和 user2,user2 就對應了兩個tenant:tenant1 和 tenant2 # keystone user-role-add -user-id 7b32f4fc92704947802d2eca95edff0d -role-id 2493283f09c1475198f2337a47aa398f -tenant-id 0647347fa21d4221b0197cd282465a00
Role 在 Keystone 里面是一個關鍵的東西。
有一個問題,Keystone 是否解決了 OpenStack 的雲安全問題呢?其實遠遠不夠,它只是實現了對 OpenStack 各種服務的訪問權限的控制。Keystone 不能和雲安全划等號的。公有雲上常見的安全防護手段有:
- 安全訪問(OpenStack 會暴露出來一些 API 或 Endpoint,客戶是通過 HTTP 協議訪問的,實際上我們應該允許通過 HTTPS 協議訪問)
- 內置防火牆功能(FWIIS,Firewall as a Service,用戶可以通過配置內置防火牆讓雲上的和環境或者應用更安全)
- 加密數據存儲(雲的管理員可以獲取雲存儲上的文件,所以用戶的文件需要加密讓雲的管理員無法查看、檢索、分析,但是不是所有的客戶端都提供給用戶加密數據存儲的功能)
- 幫助用戶檢測安全狀況(主動監測租戶的安全狀況並給出提示,給出一些安全防護的提示,甚至在出現嚴重安全問題的情況下,會主動去把租戶的服務下線以保證整個雲的安全)
8. 總結
Nova
- nova-console
- nova-consoleauth
- nova-compute
- nova-conductor
- nova-scheduler
Swift
- 對象存儲的特點
- 強調 Swift 的全對等架構
- 極高的可擴展性
- Swift 集群部署中的注意事項
Cinder
- 提供塊存儲服務或者說卷服務
- 通過 Cinder-volume 里面的 Driver 支持不同的存儲設備
Neutron
- 租用可以制定自己的 rich toplogy 的虛擬網絡
- 通過各種 agent 和 plugin 實現具體的功能並和第三方設備、軟件對接
Horizon
- 三級代碼組織形式
Glance
- 掌握了 Glance 的鏡像
- 對 Glance 做負載均衡
Keystone
- 通過 Role 進行權限管理
- 通過 Role 將同一個用戶分配到不同的 tenant 中
可以說,OPENSTACK不僅是一種產品,更是一種模式。