https://www.jianshu.com/p/cc3ece850433
1. Ceph架構簡介及使用場景介紹
1.1 Ceph簡介
Ceph是一個統一的分布式存儲系統,設計初衷是提供較好的性能、可靠性和可擴展性。
Ceph項目最早起源於Sage就讀博士期間的工作(最早的成果於2004年發表),並隨后貢獻給開源社區。在經過了數年的發展之后,目前已得到眾多雲計算廠商的支持並被廣泛應用。RedHat及OpenStack都可與Ceph整合以支持虛擬機鏡像的后端存儲。
1.2 Ceph特點
- 高性能
- a. 摒棄了傳統的集中式存儲元數據尋址的方案,采用CRUSH算法,數據分布均衡,並行度高。
- b.考慮了容災域的隔離,能夠實現各類負載的副本放置規則,例如跨機房、機架感知等。
- c. 能夠支持上千個存儲節點的規模,支持TB到PB級的數據。
- 高可用性
- a. 副本數可以靈活控制。
- b. 支持故障域分隔,數據強一致性。
- c. 多種故障場景自動進行修復自愈。
- d. 沒有單點故障,自動管理。
- 高可擴展性
- a. 去中心化。
- b. 擴展靈活。
- c. 隨着節點增加而線性增長。
- 特性豐富
- a. 支持三種存儲接口:塊存儲、文件存儲、對象存儲。
- b. 支持自定義接口,支持多種語言驅動。
1.3 Ceph架構
支持三種接口:
- Object:有原生的API,而且也兼容Swift和S3的API。
- Block:支持精簡配置、快照、克隆。
- File:Posix接口,支持快照。
rados.png
1.4 Ceph核心組件及概念介紹
-
Monitor
一個Ceph集群需要多個Monitor組成的小集群,它們通過Paxos同步數據,用來保存OSD的元數據。
-
OSD
OSD全稱Object Storage Device,也就是負責響應客戶端請求返回具體數據的進程。一個Ceph集群一般都有很多個OSD。
-
MDS
MDS全稱Ceph Metadata Server,是CephFS服務依賴的元數據服務。
-
Object
Ceph最底層的存儲單元是Object對象,每個Object包含元數據和原始數據。
-
PG
PG全稱Placement Grouops,是一個邏輯的概念,一個PG包含多個OSD。引入PG這一層其實是為了更好的分配數據和定位數據。
-
RADOS
RADOS全稱Reliable Autonomic Distributed Object Store,是Ceph集群的精華,用戶實現數據分配、Failover等集群操作。
-
Libradio
Librados是Rados提供庫,因為RADOS是協議很難直接訪問,因此上層的RBD、RGW和CephFS都是通過librados訪問的,目前提供PHP、Ruby、Java、Python、C和C++支持。
-
CRUSH
CRUSH是Ceph使用的數據分布算法,類似一致性哈希,讓數據分配到預期的地方。
-
RBD
RBD全稱RADOS block device,是Ceph對外提供的塊設備服務。
-
RGW
RGW全稱RADOS gateway,是Ceph對外提供的對象存儲服務,接口與S3和Swift兼容。
-
CephFS
CephFS全稱Ceph File System,是Ceph對外提供的文件系統服務。
1.5 三種存儲類型-塊存儲
典型設備: 磁盤陣列,硬盤
主要是將裸磁盤空間映射給主機使用的。
優點:
- 通過Raid與LVM等手段,對數據提供了保護。
- 多塊廉價的硬盤組合起來,提高容量。
- 多塊磁盤組合出來的邏輯盤,提升讀寫效率。
缺點:
- 采用SAN架構組網時,光纖交換機,造價成本高。
- 主機之間無法共享數據。
使用場景:
- docker容器、虛擬機磁盤存儲分配。
- 日志存儲。
- 文件存儲。
- …
1.6 三種存儲類型-文件存儲
典型設備: FTP、NFS服務器
為了克服塊存儲文件無法共享的問題,所以有了文件存儲。
在服務器上架設FTP與NFS服務,就是文件存儲。
優點:
- 造價低,隨便一台機器就可以了。
- 方便文件共享。
缺點:
- 讀寫速率低。
- 傳輸速率慢。
使用場景:
- 日志存儲。
- 有目錄結構的文件存儲。
- …
1.7 三種存儲類型-對象存儲
典型設備: 內置大容量硬盤的分布式服務器(swift, s3)
多台服務器內置大容量硬盤,安裝上對象存儲管理軟件,對外提供讀寫訪問功能。
優點:
- 具備塊存儲的讀寫高速。
- 具備文件存儲的共享等特性。
使用場景: (適合更新變動較少的數據)
- 圖片存儲。
- 視頻存儲。
- …
2. Ceph IO流程及數據分布
2.1 正常IO流程圖
步驟:
- client 創建cluster handler。
- client 讀取配置文件。
- client 連接上monitor,獲取集群map信息。
- client 讀寫io 根據crshmap 算法請求對應的主osd數據節點。
- 主osd數據節點同時寫入另外兩個副本節點數據。
- 等待主節點以及另外兩個副本節點寫完數據狀態。
- 主節點及副本節點寫入狀態都成功后,返回給client,io寫入完成。
2.2 新主IO流程圖
說明:
如果新加入的OSD1取代了原有的 OSD4成為 Primary OSD, 由於 OSD1 上未創建 PG , 不存在數據,那么 PG 上的 I/O 無法進行,怎樣工作的呢?
步驟:
- client連接monitor獲取集群map信息。
- 同時新主osd1由於沒有pg數據會主動上報monitor告知讓osd2臨時接替為主。
- 臨時主osd2會把數據全量同步給新主osd1。
- client IO讀寫直接連接臨時主osd2進行讀寫。
- osd2收到讀寫io,同時寫入另外兩副本節點。
- 等待osd2以及另外兩副本寫入成功。
- osd2三份數據都寫入成功返回給client, 此時client io讀寫完畢。
- 如果osd1數據同步完畢,臨時主osd2會交出主角色。
- osd1成為主節點,osd2變成副本。
2.3 Ceph IO算法流程
-
File用戶需要讀寫的文件。File->Object映射:
- a. ino (File的元數據,File的唯一id)。
- b. ono(File切分產生的某個object的序號,默認以4M切分一個塊大小)。
- c. oid(object id: ino + ono)。
-
Object是RADOS需要的對象。Ceph指定一個靜態hash函數計算oid的值,將oid映射成一個近似均勻分布的偽隨機值,然后和mask按位相與,得到pgid。Object->PG映射:
- a. hash(oid) & mask-> pgid 。
- b. mask = PG總數m(m為2的整數冪)-1 。
-
PG(Placement Group),用途是對object的存儲進行組織和位置映射, (類似於redis cluster里面的slot的概念) 一個PG里面會有很多object。采用CRUSH算法,將pgid代入其中,然后得到一組OSD。PG->OSD映射:
- a. CRUSH(pgid)->(osd1,osd2,osd3) 。
2.4 Ceph IO偽代碼流程
locator = object_name
obj_hash = hash(locator) pg = obj_hash % num_pg osds_for_pg = crush(pg) # returns a list of osds primary = osds_for_pg[0] replicas = osds_for_pg[1:]
2.5 Ceph RBD IO流程
步驟:
- 客戶端創建一個pool,需要為這個pool指定pg的數量。
- 創建pool/image rbd設備進行掛載。
- 用戶寫入的數據進行切塊,每個塊的大小默認為4M,並且每個塊都有一個名字,名字就是object+序號。
- 將每個object通過pg進行副本位置的分配。
- pg根據cursh算法會尋找3個osd,把這個object分別保存在這三個osd上。
- osd上實際是把底層的disk進行了格式化操作,一般部署工具會將它格式化為xfs文件系統。
- object的存儲就變成了存儲一個文rbd0.object1.file。
2.6 Ceph RBD IO框架圖
客戶端寫數據osd過程:
- 采用的是librbd的形式,使用librbd創建一個塊設備,向這個塊設備中寫入數據。
- 在客戶端本地同過調用librados接口,然后經過pool,rbd,object、pg進行層層映射,在PG這一層中,可以知道數據保存在哪3個OSD上,這3個OSD分為主從的關系。
- 客戶端與primay OSD建立SOCKET 通信,將要寫入的數據傳給primary OSD,由primary OSD再將數據發送給其他replica OSD數據節點。
2.7 Ceph Pool和PG分布情況
說明:
- pool是ceph存儲數據時的邏輯分區,它起到namespace的作用。
- 每個pool包含一定數量(可配置)的PG。
- PG里的對象被映射到不同的Object上。
- pool是分布到整個集群的。
- pool可以做故障隔離域,根據不同的用戶場景不一進行隔離。
2.8 Ceph 數據擴容PG分布
場景數據遷移流程:
- 現狀3個OSD, 4個PG
- 擴容到4個OSD, 4個PG
現狀:
擴容后:
說明
每個OSD上分布很多PG, 並且每個PG會自動散落在不同的OSD上。如果擴容那么相應的PG會進行遷移到新的OSD上,保證PG數量的均衡。
3. Ceph心跳機制
3.1 心跳介紹
心跳是用於節點間檢測對方是否故障的,以便及時發現故障節點進入相應的故障處理流程。
問題:
- 故障檢測時間和心跳報文帶來的負載之間做權衡。
- 心跳頻率太高則過多的心跳報文會影響系統性能。
- 心跳頻率過低則會延長發現故障節點的時間,從而影響系統的可用性。
故障檢測策略應該能夠做到:
- 及時:節點發生異常如宕機或網絡中斷時,集群可以在可接受的時間范圍內感知。
- 適當的壓力:包括對節點的壓力,和對網絡的壓力。
- 容忍網絡抖動:網絡偶爾延遲。
- 擴散機制:節點存活狀態改變導致的元信息變化需要通過某種機制擴散到整個集群。
3.2 Ceph 心跳檢測
OSD節點會監聽public、cluster、front和back四個端口
- public端口:監聽來自Monitor和Client的連接。
- cluster端口:監聽來自OSD Peer的連接。
- front端口:供客戶端連接集群使用的網卡, 這里臨時給集群內部之間進行心跳。
- back端口:供客集群內部使用的網卡。集群內部之間進行心跳。
- hbclient:發送ping心跳的messenger。
3.3 Ceph OSD之間相互心跳檢測
步驟:
- 同一個PG內OSD互相心跳,他們互相發送PING/PONG信息。
- 每隔6s檢測一次(實際會在這個基礎上加一個隨機時間來避免峰值)。
- 20s沒有檢測到心跳回復,加入failure隊列。
3.4 Ceph OSD與Mon心跳檢測
OSD報告給Monitor:
- OSD有事件發生時(比如故障、PG變更)。
- 自身啟動5秒內。
- OSD周期性的上報給Monito
- OSD檢查failure_queue中的伙伴OSD失敗信息。
- 向Monitor發送失效報告,並將失敗信息加入failure_pending隊列,然后將其從failure_queue移除。
- 收到來自failure_queue或者failure_pending中的OSD的心跳時,將其從兩個隊列中移除,並告知Monitor取消之前的失效報告。
- 當發生與Monitor網絡重連時,會將failure_pending中的錯誤報告加回到failure_queue中,並再次發送給Monitor。
- Monitor統計下線OSD
- Monitor收集來自OSD的伙伴失效報告。
- 當錯誤報告指向的OSD失效超過一定閾值,且有足夠多的OSD報告其失效時,將該OSD下線。
3.5 Ceph心跳檢測總結
Ceph通過伙伴OSD匯報失效節點和Monitor統計來自OSD的心跳兩種方式判定OSD節點失效。
- 及時:伙伴OSD可以在秒級發現節點失效並匯報Monitor,並在幾分鍾內由Monitor將失效OSD下線。
- 適當的壓力:由於有伙伴OSD匯報機制,Monitor與OSD之間的心跳統計更像是一種保險措施,因此OSD向Monitor發送心跳的間隔可以長達600秒,Monitor的檢測閾值也可以長達900秒。Ceph實際上是將故障檢測過程中中心節點的壓力分散到所有的OSD上,以此提高中心節點Monitor的可靠性,進而提高整個集群的可擴展性。
- 容忍網絡抖動:Monitor收到OSD對其伙伴OSD的匯報后,並沒有馬上將目標OSD下線,而是周期性的等待幾個條件:
- 目標OSD的失效時間大於通過固定量osd_heartbeat_grace和歷史網絡條件動態確定的閾值。
- 來自不同主機的匯報達到mon_osd_min_down_reporters。
- 滿足前兩個條件前失效匯報沒有被源OSD取消。
- 擴散:作為中心節點的Monitor並沒有在更新OSDMap后嘗試廣播通知所有的OSD和Client,而是惰性的等待OSD和Client來獲取。以此來減少Monitor壓力並簡化交互邏輯。
4. Ceph通信框架
4.1 Ceph通信框架種類介紹
網絡通信框架三種不同的實現方式:
- Simple線程模式
- 特點:每一個網絡鏈接,都會創建兩個線程,一個用於接收,一個用於發送。
- 缺點:大量的鏈接會產生大量的線程,會消耗CPU資源,影響性能。
- Async事件的I/O多路復用模式
- 特點:這種是目前網絡通信中廣泛采用的方式。k版默認已經使用Asnyc了。
- XIO方式使用了開源的網絡通信庫accelio來實現
- 特點:這種方式需要依賴第三方的庫accelio穩定性,目前處於試驗階段。
4.2 Ceph通信框架設計模式
設計模式(Subscribe/Publish)
訂閱發布模式又名觀察者模式,它意圖是“定義對象間的一種一對多的依賴關系,
當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新”。
4.3 Ceph通信框架流程圖
步驟:
- Accepter監聽peer的請求, 調用 SimpleMessenger::add_accept_pipe() 創建新的 Pipe 到 SimpleMessenger::pipes 來處理該請求。
- Pipe用於消息的讀取和發送。該類主要有兩個組件,Pipe::Reader,Pipe::Writer用來處理消息讀取和發送。
- Messenger作為消息的發布者, 各個 Dispatcher 子類作為消息的訂閱者, Messenger 收到消息之后, 通過 Pipe 讀取消息,然后轉給 Dispatcher 處理。
- Dispatcher是訂閱者的基類,具體的訂閱后端繼承該類,初始化的時候通過 Messenger::add_dispatcher_tail/head 注冊到 Messenger::dispatchers. 收到消息后,通知該類處理。
- DispatchQueue該類用來緩存收到的消息, 然后喚醒 DispatchQueue::dispatch_thread 線程找到后端的 Dispatch 處理消息。
4.4 Ceph通信框架類圖
4.5 Ceph通信數據格式
通信協議格式需要雙方約定數據格式。
消息的內容主要分為三部分:
- header //消息頭類型消息的信封
- user data //需要發送的實際數據
- payload //操作保存元數據
- middle //預留字段
- data //讀寫數據
- footer //消息的結束標記
class Message : public RefCountedObject { protected: ceph_msg_header header; // 消息頭 ceph_msg_footer footer; // 消息尾 bufferlist payload; // "front" unaligned blob bufferlist middle; // "middle" unaligned blob bufferlist data; // data payload (page-alignment will be preserved where possible) /* recv_stamp is set when the Messenger starts reading the * Message off the wire */ utime_t recv_stamp; //開始接收數據的時間戳 /* dispatch_stamp is set when the Messenger starts calling dispatch() on * its endpoints */ utime_t dispatch_stamp; //dispatch 的時間戳 /* throttle_stamp is the point at which we got throttle */ utime_t throttle_stamp; //獲取throttle 的slot的時間戳 /* time at which message was fully read */ utime_t recv_complete_stamp; //接收完成的時間戳 ConnectionRef connection; //網絡連接 uint32_t magic = 0; //消息的魔術字 bi::list_member_hook<> dispatch_q; //boost::intrusive 成員字段 }; struct ceph_msg_header { __le64 seq; // 當前session內 消息的唯一 序號 __le64 tid; // 消息的全局唯一的 id __le16 type; // 消息類型 __le16 priority; // 優先級 __le16 version; // 版本號 __le32 front_len; // payload 的長度 __le32 middle_len;// middle 的長度 __le32 data_len; // data 的 長度 __le16 data_off; // 對象的數據偏移量 struct ceph_entity_name src; //消息源 /* oldest code we think can decode this. unknown if zero. */ __le16 compat_version; __le16 reserved; __le32 crc; /* header crc32c */ } __attribute__ ((packed)); struct ceph_msg_footer { __le32 front_crc, middle_crc, data_crc; //crc校驗碼 __le64 sig; //消息的64位signature __u8 flags; //結束標志 } __attribute__ ((packed));
5. Ceph CRUSH算法
5.1 數據分布算法挑戰
- 數據分布和負載均衡:
- a. 數據分布均衡,使數據能均勻的分布到各個節點上。
- b. 負載均衡,使數據訪問讀寫操作的負載在各個節點和磁盤的負載均衡。
- 靈活應對集群伸縮:
- a. 系統可以方便的增加或者刪除節點設備,並且對節點失效進行處理。
- b. 增加或者刪除節點設備后,能自動實現數據的均衡,並且盡可能少的遷移數據。
- 支持大規模集群:
- a. 要求數據分布算法維護的元數據相對較小,並且計算量不能太大。隨着集群規模的增 加,數據分布算法開銷相對比較小。
5.2 Ceph CRUSH算法說明
-
CRUSH算法的全稱為:Controlled Scalable Decentralized Placement of Replicated Data,可控的、可擴展的、分布式的副本數據放置算法。
-
PG到OSD的映射的過程算法叫做CRUSH 算法。(一個Object需要保存三個副本,也就是需要保存在三個osd上)。
-
CRUSH算法是一個偽隨機的過程,他可以從所有的OSD中,隨機性選擇一個OSD集合,但是同一個PG每次隨機選擇的結果是不變的,也就是映射的OSD集合是固定的。
5.3 Ceph CRUSH算法原理
CRUSH算法因子:
-
層次化的Cluster Map
反映了存儲系統層級的物理拓撲結構。定義了OSD集群具有層級關系的 靜態拓撲結構。OSD層級使得 CRUSH算法在選擇OSD時實現了機架感知能力,也就是通過規則定義, 使得副本可以分布在不同的機 架、不同的機房中、提供數據的安全性 。 -
Placement Rules
決定了一個PG的對象副本如何選擇的規則,通過這些可以自己設定規則,用戶可以自定義設置副本在集群中的分布。
5.3.1 層級化的Cluster Map
CRUSH Map是一個樹形結構,OSDMap更多記錄的是OSDMap的屬性(epoch/fsid/pool信息以及osd的ip等等)。
葉子節點是device(也就是osd),其他的節點稱為bucket節點,這些bucket都是虛構的節點,可以根據物理結構進行抽象,當然樹形結構只有一個最終的根節點稱之為root節點,中間虛擬的bucket節點可以是數據中心抽象、機房抽象、機架抽象、主機抽象等。
5.3.2 數據分布策略Placement Rules
數據分布策略Placement Rules主要有特點:
- a. 從CRUSH Map中的哪個節點開始查找
- b. 使用那個節點作為故障隔離域
- c. 定位副本的搜索模式(廣度優先 or 深度優先)
rule replicated_ruleset #規則集的命名,創建pool時可以指定rule集 { ruleset 0 #rules集的編號,順序編即可 type replicated #定義pool類型為replicated(還有erasure模式) min_size 1 #pool中最小指定的副本數量不能小1 max_size 10 #pool中最大指定的副本數量不能大於10 step take default #查找bucket入口點,一般是root類型的bucket step chooseleaf firstn 0 type host #選擇一個host,並遞歸選擇葉子節點osd step emit #結束 }
5.3.3 Bucket隨機算法類型
-
一般的buckets:適合所有子節點權重相同,而且很少添加刪除item。
-
list buckets:適用於集群擴展類型。增加item,產生最優的數據移動,查找item,時間復雜度O(n)。
-
tree buckets:查找負責度是O (log n), 添加刪除葉子節點時,其他節點node_id不變。
-
straw buckets:允許所有項通過類似抽簽的方式來與其他項公平“競爭”。定位副本時,bucket中的每一項都對應一個隨機長度的straw,且擁有最長長度的straw會獲得勝利(被選中),添加或者重新計算,子樹之間的數據移動提供最優的解決方案。
5.4 CRUSH算法案例
說明:
集群中有部分sas和ssd磁盤,現在有個業務線性能及可用性優先級高於其他業務線,能否讓這個高優業務線的數據都存放在ssd磁盤上。
普通用戶:
高優用戶:
配置規則:
6. 定制化Ceph RBD QOS
6.1 QOS介紹
QoS (Quality of Service,服務質量)起源於網絡技術,它用來解決網絡延遲和阻塞等問題,能夠為指定的網絡通信提供更好的服務能力。
問題:
我們總的Ceph集群的iIO能力是有限的,比如帶寬,IOPS。如何避免用戶爭取資源,如果保證集群所有用戶資源的高可用性,以及如何保證高優用戶資源的可用性。所以我們需要把有限的IO能力合理分配。
6.2 Ceph IO操作類型
-
ClientOp:來自客戶端的讀寫I/O請求。
-
SubOp:osd之間的I/O請求。主要包括由客戶端I/O產生的副本間數據讀寫請求,以及由數據同步、數據掃描、負載均衡等引起的I/O請求。
-
SnapTrim:快照數據刪除。從客戶端發送快照刪除命令后,刪除相關元數據便直接返回,之后由后台線程刪除真實的快照數據。通過控制snaptrim的速率間接控制刪除速率。
-
Scrub:用於發現對象的靜默數據錯誤,掃描元數據的Scrub和對象整體掃描的deep Scrub。
-
Recovery:數據恢復和遷移。集群擴/縮容、osd失效/從新加入等過程。
6.3 Ceph 官方QOS原理
mClock是一種基於時間標簽的I/O調度算法,最先被Vmware提出來的用於集中式管理的存儲系統。(目前官方QOS模塊屬於半成品)。
基本思想:
- reservation 預留,表示客戶端獲得的最低I/O資源。
- weight 權重,表示客戶端所占共享I/O資源的比重。
- limit 上限,表示客戶端可獲得的最高I/O資源。
6.4 定制化QOS原理
6.4.1 令牌桶算法介紹
基於令牌桶算法(TokenBucket)實現了一套簡單有效的qos功能,滿足了雲平台用戶的核心需求。
基本思想:
- 按特定的速率向令牌桶投放令牌。
- 根據預設的匹配規則先對報文進行分類,不符合匹配規則的報文不需要經過令牌桶的處理,直接發送。
- 符合匹配規則的報文,則需要令牌桶進行處理。當桶中有足夠的令牌則報文可以被繼續發送下去,同時令牌桶中的令牌量按報文的長度做相應的減少。
- 當令牌桶中的令牌不足時,報文將不能被發送,只有等到桶中生成了新的令牌,報文才可以發送。這就可以限制報文的流量只能是小於等於令牌生成的速度,達到限制流量的目的。
6.4.2 RBD令牌桶算法流程
步驟:
- 用戶發起請求異步IO到達Image中。
- 請求到達ImageRequestWQ隊列中。
- 在ImageRequestWQ出隊列的時候加入令牌桶算法TokenBucket。
- 通過令牌桶算法進行限速,然后發送給ImageRequest進行處理。
6.4.3 RBD令牌桶算法框架圖
現有框架圖:
令牌圖算法框架圖:
作者:Lucien_168
鏈接:https://www.jianshu.com/p/cc3ece850433
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。
