這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在《使用Ceph RBD為Kubernetes叢集提供儲存卷》一文中,我們瞭解到,在Kubernetes和ceph的整合過程中,有一個步驟是需要手動操作的,那就是建立ceph osd pool下面的rbd image。我們需要想辦法去除這一手動步驟。關於方案,我們首先想到的就是是否可以調用Ceph提供的REST API來管理rbd的pool和image?
Ceph提供了兩套REST API方案:ceph-rest-api和Calamari。不過從現有資料來看,這兩套REST API似乎都沒有提供操作pool下image的服務介面。Calamari計劃實現image的service介面,但目前已經沒有實現。
在Ceph REST API對rbd的覆蓋還全面的情況下,我們只能自己動手,豐衣足食了:我們需要利用ceph提供library API實現對pool和image的管理,並對外提供自訂的Service API。如果你是一名gopher,那麼go-ceph這個golang ceph library API binding將會給你帶來不小的協助。go-ceph實質上是通過cgo做的一個ceph c library的golang binding,覆蓋較為全面:rados、rbd和cephfs都支援。
一、安裝go-ceph和依賴
首先,由於用的是cgo,使用go-ceph包的程式在編譯時間勢必要去連結ceph的c library,因此我們在開發環境中需要首先安裝go-ceph包的一些依賴(在ubuntu 14.04上):
# apt-get install librados-dev# apt-get install librbd-dev# ls /usr/include/radosbuffer_fwd.h buffer.h crc32c.h librados.h librados.hpp memory.h page.h rados_types.h rados_types.hpp# ls /usr/include/rbdfeatures.h librbd.h librbd.hpp
接下來就是安裝go-ceph自身了,我們通過最常用的go get命令就可以很順利的下載到go-ceph包。
# go get github.com/ceph/go-ceph
二、go-ceph:串連Ceph叢集
go-ceph的文檔不多,但go-ceph使用起來並不算困難,關於go-ceph中各個包的用法,可以參考對應包中的*_test.go檔案。
串連Ceph叢集的方法之一如下:
//github.com/bigwhite/experiments/blob/master/go-ceph/conn.gopackage mainimport ( "fmt" "github.com/ceph/go-ceph/rados")func main() { conn, err := rados.NewConn() if err != nil { fmt.Println("error when invoke a new connection:", err) return } err = conn.ReadDefaultConfigFile() if err != nil { fmt.Println("error when read default config file:", err) return } err = conn.Connect() if err != nil { fmt.Println("error when connect:", err) return } fmt.Println("connect ceph cluster ok!") conn.Shutdown()}
這裡conn對象採用的是讀取預設設定檔(/etc/ceph/ceph.conf)的方式擷取的mon node資訊,go-ceph文檔中稱還可以通過命令列參數以及環境變數的方式擷取。但命令列參數的方式,我個人試了幾次都沒能連上。即便是對照著librados c api的文檔進行參數傳遞也沒成。
三、go-ceph:管理pool
Pool是Ceph叢集的一個邏輯概念,一個Ceph叢集可以有多個pool,每個pool是邏輯上的隔離單位。不同的pool可以有完全不一樣的資料處理方式,比如Replica Size(副本數)、Placement Groups、CRUSH Rules、快照、所屬者等。go-ceph支援對pool的建立、查看以及刪除等管理操作:
//github.com/bigwhite/experiments/blob/master/go-ceph/pool.go... ...func newConn() (*rados.Conn, error) { conn, err := rados.NewConn() if err != nil { return nil, err } err = conn.ReadDefaultConfigFile() if err != nil { return nil, err } err = conn.Connect() if err != nil { return nil, err } return conn, nil}func listPools(conn *rados.Conn, prefix string) { pools, err := conn.ListPools() if err != nil { fmt.Println("error when list pool", err) os.Exit(1) } fmt.Println(prefix, ":", pools)}func main() { conn, err := newConn() if err != nil { fmt.Println("error when invoke a new connection:", err) return } defer conn.Shutdown() fmt.Println("connect ceph cluster ok!") listPools(conn, "before make new pool") err = conn.MakePool("new_pool") if err != nil { fmt.Println("error when make new_pool", err) return } listPools(conn, "after make new pool") err = conn.DeletePool("new_pool") if err != nil { fmt.Println("error when delete pool", err) return } listPools(conn, "after delete new_pool")}
執行pool.go:
# go run pool.goconnect ceph cluster ok!before make new pool : [rbd rbd1]after make new pool : [rbd rbd1 new_pool]after delete new_pool : [rbd rbd1]
四、go-ceph:管理image
image是我們真正要去管理的對象(pool可以採用預設的”rbd”),image的管理依賴go-ceph下的rbd包:
//github.com/bigwhite/experiments/blob/master/go-ceph/image.go... ...func listImages(ioctx *rados.IOContext, prefix string) { imageNames, err := rbd.GetImageNames(ioctx) if err != nil { fmt.Println("error when getImagesNames", err) os.Exit(1) } fmt.Println(prefix, ":", imageNames)}func main() { conn, err := newConn() if err != nil { fmt.Println("error when invoke a new connection:", err) return } defer conn.Shutdown() fmt.Println("connect ceph cluster ok!") ioctx, err := conn.OpenIOContext("rbd") if err != nil { fmt.Println("error when openIOContext", err) return } defer ioctx.Destroy() listImages(ioctx, "before create new image") name := "go-ceph-image" img, err := rbd.Create(ioctx, name, 1<<20, 20) if err != nil { fmt.Println("error when create rbd image", err) return } listImages(ioctx, "after create new image") err = img.Remove() if err != nil { fmt.Println("error when remove image", err) return } listImages(ioctx, "after remove new image")}
這裡要注意的是rbd.Create這個方法,如果第三個參數(image size)傳遞過小,那麼rbd.Create會報錯,比如;如果我們將那一夥代碼改為:
img, err := rbd.Create(ioctx, name, 1<<10, 10)
那麼執行image.go時,會得到一下錯誤:
error when create rbd image rbd: ret=-33
33就是linux errno,其含義是:
#define EDOM 33 /* Math argument out of domain of func */
猜測這個參數的單位是位元組,具體參數的合法範圍,文檔和代碼並沒有給出顯式說明。
五、小結
go-ceph實現了rbd pool/images的基本管理功能,為提供rbd restful api奠定了基礎。寫了三篇長文後,來一篇短的,營養算不上多,用於備忘還好。
2016, bigwhite. 著作權.