理解 OpenStack Swift (2):架構、原理及功能 [Architecture, Implementation and Features]

本系列文章着重學習和研究OpenStack Swift,包括環境搭建、原理、架構、監控和性能等。html

(1)OpenStack + 三節點Swift 集羣+ HAProxy + UCARP 安裝和配置 前端

(2)原理、架構和性能node

(3)監控git

1. 架構

1.1 整體架構

Swift 的整體架構很是的清晰和獨立:github

# 分層(Tier) 組件(Service) 功能(Function) 特性 部署考量
1 訪問層(Access Tier) Load Balancer 硬件(好比F5)或者軟件(好比HAProxy)負載均衡器,將客戶端的請求按照配置的策略分配到無狀態的 proxy service。    按照實際需求選擇硬件仍是軟件LB
2 Proxy Server
  • 提供 REST API 給客戶端
  • 無狀態的 WSGI 服務,由多個 Proxy Server 組成一個集羣
  • 將客戶端請求轉給某個存儲節點上的 Account,Container 或者 Object 服務

是 CPU 和網絡帶寬敏感的web

  • 分配更多的CPU和網絡帶寬,好比 10GbE 網絡
  • 使用 Memcached 來作 token、account 和 container 數據緩存
  • 和存儲服務分開部署
  • 使用負載均衡器
  • 每每每五個存儲節點使用兩個 proxy server 節點,而後再按比例擴展
  • 將 public network (用於客戶端訪問)和 backend network (用於訪問存儲服務)分開
  • 須要考慮安全性,能夠將 SSL Termination 放在 Proxy Server 上
3 存儲層 (Capactity Tier)

Account Server算法

提供 Account 操做 REST API 是磁盤性能和網絡帶敏感的
  • 對 Account 和 Container 服務使用更好的磁盤,好比 SAS 或者 SSD,來提升性能;
  • 使用 1GbE 或者 10GbE 網絡
  • 須要的話,能夠將 replicaiton network 獨立出來
  • 須要的話,能夠將 Account 和 Container 服務部署到獨立的服務器上
4 Container Server 提供 Container 操做 REST API
5 Object Server 提供 Object 操做 REST API
 6 Consistency Servers 包括 Replicators, Updaters 和 Auditors 等後臺服務,用於保證 object 的一致性

這是一張比較經典的 Swift 物理部署圖:數據庫

1.2 網絡架構

以一個對外提供對象存儲服務的集羣爲例,其網絡架構能夠爲:ubuntu

  • 外部流量被放在一個單獨的(上圖中紫色)VLAN 中,終點爲 LB
  • 控制(管理)網絡鏈接全部節點
  • Swift 前端(front end / public)網絡鏈接 LB 和 全部 Proxy server 節點
  • Swift 後端 (backend / private) 網絡鏈接全部 Proxy server 節點和 存儲節點
  • 須要的話,還能夠從後端網絡中分離出複製(replication)網絡

在網絡帶寬選擇上,swift

  • 考慮到複製數據的容量較大(每每是幾個TB起步),後端網絡每每是用 10GbE 網絡
  • 根據前端負載,前端網絡可使用 1GbE 網絡,或者有條件時使用 10GbE 網絡
  • 管理/IPMI網絡每每是用 1GbE 網絡

這是 SwiftStack 的一個例子:

2. 數據存放

2.1 Swift 的數據存放

2.1.1 Swift 的數據模型

Swift 的數據模型使用瞭如下三個概念來(見下圖1):

  • Account: 帳戶/租戶。Swift 是天生支持多租戶的。若是使用 OpenStack Keystone 作用戶校驗的話,account 與 OpenStack project/tenant 的概念相同。Swift 租戶的隔離性體如今metadata上,而不是體如今 object data 上。數據包括自身元數據 和 container 列表,被保存在 SQLite 數據庫中。
  • Container: 容器,相似於文件系統中的目錄,由用戶自定義,它包含自身的元數據和容器內的對象列表。數據保存在 SQLite 數據庫中。在新版中,Swift 支持在容器內添加文件夾。
  • Object: 對象,包括數據和數據的元數據,以文件形式保存在文件系統上。

     

 (圖1)                                                     (圖2)

 

  • Containers 是用戶建立的,用來 hold objects。
  • objects 能夠是 0 bytes 長度,或者包含數據。
  • container 中的 object 最大大小爲 5GB;超過的話,會作特殊處理
  • 每一個 object 使用它的 name 來被 referenced;Swift 沒有目錄概念
  • 在 object name 中可使用任意的能夠被 ‘URL-encoded’ 的 字符,最大長度爲 URL - coded 以後 1034 個字符
  • object name 中能夠帶 '/' 字符,它會帶來目錄結構的幻覺(illusion),好比 dir/dir2/name。即便看起來象個目錄,可是它仍然只是一個 object name。此時,不須要 dir 或者 dir/dir2 container 的存在。
  • 若是一個 container 全部 objects 的大小爲0,那麼它將看起來象一個目錄。
  • 客戶端使用 HTTP 或者 HTTPS 訪問 Swift,包括讀、寫、刪除 objects。也支持 COPY 操做,它會建立一個新的 object,使用一個新的 object name,包含老 object 的 data。沒有 rename 操做,它會首先 copy 出一個新的,而後再將老的刪除。

2.1.2 選擇數據存放位置

  Swift 保存每一個對象爲多分拷貝,它按照物理位置的特色,儘可能將這些拷貝放在不一樣的物理位置上,來保證數據的地理位置上的可靠性。它主要考慮如下幾種位置屬性:

  • Region:地理位置上的區域,好比不一樣城市甚至不一樣國家的機房,這主要是從災備方面考慮的。
  • Zone:一個數據中心根據物理網絡、供電、空調等基礎設施分開的獨立的域,每每將一個機架(Rack)內的服務器分在一個 Zone 內。
  • Node (節點):物理服務器
  • Disk (磁盤):物理服務器上的磁盤

Swift 在肯定對象的放置位置時,會盡可能將對象及其拷貝放在不會同時損失的物理位置上。見上圖2.

2.1.3 保證數據一致性

    對象及其拷貝放置在某個磁盤上後,Swift 會使用Replicators, Updaters 和 Auditors 等後臺服務來保證其數據的最終一致性。

  • Replicator – 拷貝對象,確保系統的最終一致性(Replicate objects and make a system in a consistent state);恢復磁盤和網絡錯誤(Recover disk failure, network outages situation)
  • Updater – 更新元數據(Update metadata),從容器和帳戶元數據高負載致使的問題上恢復(Recover failure caused by container, account metadata high load)
  • Auditor – 刪除問題帳戶,容器和對象,而後從別的服務器上拷貝過來(Delete problematic account, container or objects and replicate from other server);恢復數據庫和文件數據錯誤(Recover dbs or files which have bit rot problem.

其中,Replicator 服務以可配置的間隔來週期性啓動,默認是 30s,它以 replication 爲最小單位,以 node 爲範圍,週期性地執行數據拷貝。詳細過程請參考文末的參考文檔。考慮到Swift 實現的是最終一致性而非強一致性,它不合適於須要數據強一致性的應用,好比銀行存款和訂票系統等。須要作 replication 的情形包括但不限於:

  • Proxy server 在寫入第三份時失敗,它依然會向客戶端返回成功,後臺服務會寫第三份拷貝
  • 後臺進程發現某個replication 數據出現損壞,它會在新的位置從新寫入
  • 在跨 Region 的狀況下,Proxy server 只會向它所在 Region 的存儲上寫入,遠處 region 上的數據由後臺進程複雜寫入
  • 在更換磁盤或者添加磁盤的狀況下,數據須要從新平衡時

2.2 Swift  是如何實現這些需求的:使用 Ring + 哈希算法

    Swift 根據由管理員配置的 Ring 使用相對簡單直接的算法來肯定對象的存放位置。對象會以文件的形式保存在本地文件系統中,使用文件的擴展屬性來保存對象的元數據,所以,Swift 須要支持擴展屬性的文件系統,目前官方推薦是 XFS。

2.2.1 Ring 的內容和算法

    簡單來講,Swift 的 Proxy Server 根據account,container 和 object 各自的 Ring 來肯定各自數據的存放位置,其中 account 和 container 數據庫文件也是被看成對象來處理的。

所以,Swift 須要 Ring 的配置文件分佈在全部 Proxy節點上。同時,Consistency Servers 須要它來肯定後臺對象拷貝的位置,所以也須要部署在全部存儲節點上。Ring 以文件的形式保存:

  • object.ring.gz
  • container.ring.gz
  • account.ring.gz

在分析 Ring 是如何工做的以前,先來看看 Ring 的幾個關鍵配置:

  • Region,zone 和 disk:前面說過了,略過
  • partition:Swift 再將每一個磁盤分紅若干 partition (分區)。這是後端一致性檢查服務處理拷貝(replication)的基本單位。
  • Replica:對象和拷貝的總份數,常規推薦值是 3。

管理員使用 Swift 提供的 ring 生成工具(swift-ring-builder,位於源碼的bin目錄下,是swift最基本的命令,它與swift/common/ring/下的文件一塊兒實現ring文件建立,添加,平衡,等操做),加上各類配置參數,得出該ring的內容。以 Object ring 爲例,

root@swift1:/etc/swift# swift-ring-builder object.builder
object.builder, build version 6
1024 partitions, 3.000000 replicas, 1 regions, 3 zones, 6 devices, 0.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1
The overload factor is 0.00% (0.000000)
Devices:    id  region  zone      ip address  port  replication ip  replication port      name weight partitions balance meta
             0       1     1   9.115.251.235  6000   9.115.251.235              6000      sdb1 100.00        512    0.00
             1       1     1   9.115.251.235  6000   9.115.251.235              6000      sdc1 100.00        512    0.00
             2       1     2   9.115.251.234  6000   9.115.251.234              6000      sdb1 100.00        512    0.00
             3       1     2   9.115.251.234  6000   9.115.251.234              6000      sdc1 100.00        512    0.00
             4       1     3   9.115.251.233  6000   9.115.251.233              6000      sdb1 100.00        512    0.00
             5       1     3   9.115.251.233  6000   9.115.251.233              6000      sdc1 100.00        512    0.00

該 Ring 的配置爲:1 個 region,3 個 zone,3 個 node,6 個磁盤,每一個磁盤上 512 個分區。

內部實現上,Swift 將該 Ring 的配置保存在其 _replica2part2dev 數據結構中:

其讀法是:

  • 行:將集羣全部的分區都順序編號,每一個分區有惟一的一個ID
  • 列:包含 Ring 中的 id,該 id 惟一肯定了一個 disk;和 replica 的編號。

所以,Swift 經過該數據結構能夠方便地查到某個 replica 應該經過哪些節點上的存儲服務放在哪一個 disk 上。

除了生成 Ring 外,對 Ring 的另外一個重要操做是 rebalance(再平衡)。在你修改builder文件後(例如增減設備),該操做會從新生成ring文件,使系統中的partition分佈平衡。固然,在 rebalance 後,須要從新啓動系統的各個服務。 詳情能夠參考 OpenStack Swift源碼分析(二)ring文件的生成

2.2.2 數據放置和讀取過程

當收到一個須要保存的 object 的 PUT 請求時,Proxy server 會:

  1. 根據其完整的對象路徑(/account[/container[/object]])計算其哈希值,哈希值的長度取決於集羣中分區的總數。
  2. 將哈希值的開頭 N 個字符映射爲數目同 replica 值的若干 partition ID。
  3. 根據 partition ID 肯定某個數據服務的 IP 和 port。
  4. 依次嘗試鏈接這些服務的端口。若是有一半的服務沒法鏈接,則拒絕該請求。
  5. 嘗試建立對象,存儲服務會將對象以文件形式保存到某個磁盤上。(Object server 在完成文件存儲後會異步地調用 container service 去更新container數據庫)
  6. 在3份拷貝中有兩份被成功寫入後, Proxy Server 就會向客戶端返回成功。

 

當 Proxy server 收到一個獲取對象的 GET 請求時,它:

(1)(2)(3)(4)同前面的 PUT 請求,肯定存放全部 replica 的 全部磁盤

(5)排序這些 nodes,嘗試鏈接第一個,若是成功,則將二進制數據返回客戶端;若是不成功,則嘗試下一個。直到成功或者都失敗。

應該說該過程蠻簡單直接,這也符合Swift的整體設計風格。至於具體的哈希算法實現,有興趣能夠看相關論文。大體來講,它實現的是 「unique-as-possible」 即 「儘可能惟一」 的算法,按照 Zone,Node 和 Disk 的順序。對於一個 replica,Swift 首先會去選擇一個沒有該對象 replica 的 zone,若是沒有這樣的 zone,選擇一個已使用 zone 中的沒用過的 node,若是沒有這樣的 node,就選擇已使用的 node 上的一個沒使用過的 disk。

2.2.3 Hash 計算和對象位置查找

(1)存放的目錄取決於哈希值

這裏也代表,對象的存放目錄和其名稱是直接關聯的。所以,在Swift中的,對對象重命名,意味着對象位置的修改,該過程會產生數據拷貝,並且在不少時候是須要跨節點的遠程拷貝。在某些應用中,好比 Hadoop 大數據應用,若是採用 Swift 做爲存儲,在其mapreduce 過程當中,是會產生文件 rename 操做的,這在 Swift 中會帶來嚴重的性能降低。

(2)獲取某對象的存放路徑

root@swift1:~/s1# swift-get-nodes /etc/swift/object.ring.gz AUTH_dea8b51d28bf41599e63464828102759/container1/1

Account         AUTH_dea8b51d28bf41599e63464828102759
Container       container1
Object          1
Partition       277
Hash            456a95e2e66aad55d72756c6b0cd3b75

Server:Port Device      9.115.251.235:6000 sdb1
Server:Port Device      9.115.251.234:6000 sdc1
Server:Port Device      9.115.251.233:6000 sdc1

curl -I -XHEAD "http://9.115.251.235:6000/sdb1/277/AUTH_dea8b51d28bf41599e63464828102759/container1/1"
curl -I -XHEAD "http://9.115.251.234:6000/sdc1/277/AUTH_dea8b51d28bf41599e63464828102759/container1/1"
curl -I -XHEAD "http://9.115.251.233:6000/sdc1/277/AUTH_dea8b51d28bf41599e63464828102759/container1/1"

(3)遠程登陸後者 ssh 後能夠看到保存對象的文件

root@swift1:~/s1# ls /srv/node/sdb1/objects/277/b75/456a95e2e66aad55d72756c6b0cd3b75 -l
total 8
-rw------- 1 swift swift 12 Nov  8 17:17 1447003035.84393.dataroot@swift1:~/s1# cat /srv/node/sdb1/objects/277/b75/456a95e2e66aad55d72756c6b0cd3b75/1447003035.84393.data
222222222222

2.2.4 對象分段

  Swift 對於小的文件,是不分段直接存放的;對於大的文件(大小閾值能夠配置,默認是 5G),系統會自動將其分段存放。用戶也能夠指定分段的大小來存放文件。好比對於 590M 的文件,設置分段大小爲 100M,則會被分爲 6 段被並行的(in parallel)上傳到集羣之中:

root@controller:~/s1# swift upload container1 -S 100000000 tmpubuntu
tmpubuntu segment 5
tmpubuntu segment 2
tmpubuntu segment 4
tmpubuntu segment 1
tmpubuntu segment 3
tmpubuntu segment 0
tmpubuntu
root@controller:~/s1# swift list container1
1
admin-openrc.sh
cirros-0.3.4-x86_64-disk.raw
tmpubuntu

從 stat 中能夠看出它使用一個 manifest 文件來保存分段信息:

root@controller:~/s1# swift stat container1 tmpubuntu
       Account: AUTH_dea8b51d28bf41599e63464828102759
     Container: container1
        Object: tmpubuntu
  Content Type: application/octet-stream
Content Length: 591396864
 Last Modified: Fri, 13 Nov 2015 18:31:53 GMT
          ETag: "fa561512dcd31b21841fbc9dbace118f"
      Manifest: container1_segments/tmpubuntu/1446907333.484258/591396864/100000000/
    Meta Mtime: 1446907333.484258
 Accept-Ranges: bytes
    Connection: keep-alive
   X-Timestamp: 1447439512.09744
    X-Trans-Id: txae548b4b35184c71aa396-0056462d72

可是 list 的時候依然只看到一個文件,緣由是由於 manifest 文件被保存到一個獨立的 container (container1_segments)中。這裏能夠看到 6 個對象:

root@controller:~/s1# swift list container1_segments
tmpubuntu/1446907333.484258/591396864/100000000/00000000
tmpubuntu/1446907333.484258/591396864/100000000/00000001
tmpubuntu/1446907333.484258/591396864/100000000/00000002
tmpubuntu/1446907333.484258/591396864/100000000/00000003
tmpubuntu/1446907333.484258/591396864/100000000/00000004
tmpubuntu/1446907333.484258/591396864/100000000/00000005

每一個對象大小是100M(考慮到存儲效率,不建議每一個對象大小小於100M):

root@controller:~/s1# swift stat container1_segments tmpubuntu/1446907333.484258/591396864/100000000/00000000
       Account: AUTH_dea8b51d28bf41599e63464828102759
     Container: container1_segments
        Object: tmpubuntu/1446907333.484258/591396864/100000000/00000000
  Content Type: application/octet-stream
Content Length: 100000000

並且用戶能夠單獨操做好比修改某一段。Swift 只會負責將全部段鏈接爲用戶所見的大的對象。

關於大文件支持的更多細節,能夠參考 官方文檔 和 Rackspace 的文檔。從上面的描述能夠看出,Swift 對文件分段的支持是比較初級的(固定,不靈活),所以,已經有人提出 Object stripping (對象條帶化)方案,好比下面的方案,不知道是否已經支持仍是將要支持。

2.3 Region

    經過將對象存放在不一樣物理位置上的 Region 內,能夠進一步加強數據的可用性。其基本原則是:對於 N 份 replica 和 M 個 region,每一個 region 中的 replica 數目爲 N/M 的整數,剩餘的 replica 在 M 個region 中隨機選擇。以 N = 3, M = 2 爲例,一個 region 中有 1 個 replica,另外一個 region 中有兩個 replica,以下圖所示:

對於一個 PUT 操做來講,Proxy server 只會將 replica 寫入它所在的 region 中的 node,遠端 region 中的 replica 由 replicator 寫入。所以,Swift 的算法應該儘可能保證 proxy server 所在的 region 中的 replica 份數相對多一些,這也稱爲 replica 的 proxy server 親和性。

顯然,跨 region 的數據複製加劇了對網絡帶寬的要求。

兩種形式的 Region:

(1)遠端 region 實時寫入 replica

(2)遠端 region 的 replica 異步寫入

2.4 Storage Polices (存儲策略)

    上面的描述中,一個Swift 集羣只支持一套 Ring 配置,這意味着整個機器的配置是惟一的。相似 Ceph 中 pool 的定義,Swift 在 2.0 版本(包含在 OpenStack Juno 版本中)中,添加了一個很是大的功能:Storage policy。在新的實現中,一個 Swift 能夠由多套 Ring 配置,每套 Ring 的配置能夠不相同。好比,Ring 1 保存 3 份對象拷貝,Ring 2 保存 2 份對象拷貝。幾個特色:

  • Policy 被實如今 container 級別
  • 建立 container 時能夠指定 policy。一旦被指定,不能夠修改。
  • 一個 policy 能夠被多個 container 共享使用

    經過應用該新的功能,Swift 用戶能夠制定不一樣的存儲策略,來適應不一樣應用的存儲需求。好比對關鍵應用的數據,制定一個存儲策略使得數據被保存到 SSD 上;對於通常關鍵性的數據,指定存儲策略使得數據只保存2份來節約磁盤空間。好比說:

詳細信息,請參考 OpenStack 官方文檔 和 SwiftStack 官方文檔

3. 版本及主要功能

3.1 Juno以及以前主要版本和功能

 

(1)Large object support

(2)Static web hosting

(3) S3 compatible API

(4) Object expiration

(5) Temp url

(6) Global cluster

(7) Storage policy

3.2 Kilo 版本中的更新

新功能

糾刪碼(beta)

Swift如今支持糾刪碼(EC)存儲策略類型。這樣部署人員、以極少的RAW容量達到極高的可用性,如同在副本存儲中同樣。然而,EC須要更多的CPU和網絡資源,因此並不適合全部應用場景。EC很是適合在一個獨立的區域內極少訪問的、大容量數據。

Swift糾刪碼的實現對於用戶是透明的。對於副本存儲和糾刪碼存儲的類型,在API上沒有任何區別。

爲了支持糾刪碼,Swift如今須要依賴PyECLib和liberasurecode。liberasurecode是一個可插件式的庫,容許在你選擇的庫中實現EC算法。

更詳細文檔請參閱 http://swift.openstack.org/overview_erasure_code.html

複合型令牌(Composite tokens)

複合型令牌容許其餘OpenStack服務以客戶端名義將數據存儲於Swift中,因此不管是客戶端仍是服務在更新數據時,都不須要雙方彼此的受權。

一個典型的例子就是一個用戶請求Nova存放一個VM的快照。Nova將請求傳遞給Glance,Glance將鏡像寫入Swift容器中的一組對象中。在這種場景下,用戶沒有來自服務的合法令牌時,沒法直接修改快照數據。一樣,服務自身也沒法在沒有用戶合法令牌的狀況下更新數據。可是數據的確存在於用戶的Swift帳戶中,這樣使得帳戶管理更簡單。

更詳細的文檔請參閱http://swift.openstack.org/overview_backing_store.html

更小規模、不平衡集羣的數據位置更新

Swift數據的存放位置如今根據硬件權重決定。當前,容許運維人員逐漸的添加新的區域(zones)和地域(regions),而不須要當即觸發大規模數據遷移。同時,若是一個集羣是非平衡的(例如,在一個區域(zones)的集羣中,其中一個的容量是另一的兩倍),Swift會更有效的使用現有空間而且當副本在集羣空間不足時發出警告。

全局性集羣複製優化

區域(regions)之間複製時,每次複製只遷移一個副本。這樣遠程的區域(region)能夠在內部複製,避免更多的數據在廣域網(WAN)拷貝。

已知問題

  • 做爲beta更新,糾刪碼(EC)的功能接近完成,可是對於某些功能仍然不完整(像多範圍(multi-range)讀取),而且沒有一個完整的性能測算。這個功能爲了持久性依賴於ssync。部署人員督促咱們作更大規模的測試,而且不要在生產環境部署中使用糾刪碼存儲策略。

升級提示

像往常同樣,你能在不影響最終用戶體驗的前提下,升級到這個版本的Swift。

  • 爲了支持糾刪碼,Swift須要一個新的依賴PyECLib(和liberasurecode等)。而且eventlet的最低版本要求也升高了。

3.3 Liberty 版本中的更新

L版本中Swift 沒有加入大的新功能,詳細狀況能夠參考 官方文檔

3.4 優點

 

 

其它參考文檔:

http://www.florentflament.com/blog/openstack-swift-ring-made-understandable.html

https://www.mirantis.com/blog/configuring-multi-region-cluster-openstack-swift/

OpenStack Swift源碼分析

相關文章
相關標籤/搜索