Kuberize Ceph RBD API服務

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在《使用Ceph RBD為Kubernetes叢集提供儲存卷》一文中,我們提到:藉助Kubernetes和Ceph的整合,Kubernetes可以使用Ceph RBD為叢集內的Pod提供Persistent Volume。但這一過程中,RBD所使用的image的建立、刪除還需要手動管理,於是我們又基於go-ceph實現了對RBD image的程式化管理,我們的最終目標是要這種對RBD image的管理服務以一個K8s service的形式發布到Kubernetes叢集中去,這就是本文標題中描述的那樣:Kuberize Ceph RBD API服務。

一、Dockerize Ceph RBD API服務

要想使得ceph rbd api Kuberizable,首先要Dockerize Ceph RBD API Service,即容器化。由於go-ceph是Go語言開發,我們的rbd-rest-api同樣用Go語言開發。使用Go語言開發有一個眾所周知的好處,那就是可以編譯為靜態二進位檔案,可以在運行時不依賴任何外部庫,生來內建“適合容器”標籤。但由於go-ceph是一個go binding for librados和librbd,其通過cgo實現Go語言對C庫的連結和調用。這樣一來,我們如果要做static linking,那麼我們就要準備齊全所有librados和librbd所依賴的第三方庫的.a(archive file)。如果你僅僅是執行下面編譯命令,你將得到w行層級的錯誤資訊輸出:

$ go build --ldflags '-extldflags "-static"' .

從錯誤的資訊中,我們可以得到rbd-rest-api靜態編譯依賴的各種第三方庫,包括boost庫(apt-get install libboost-all-dev)、libssl(apt-get install libssl)以及libnss3(apt-get install libnss3-dev)。安裝好這些庫,再修改一下命令列,可將編譯錯誤輸出降低到百行以內:

# go build --ldflags '-extldflags "-static -L /usr/lib/x86_64-linux-gnu -lboost_system -lboost_thread -lboost_iostreams -lboost_random -lcrypto -ldl -lpthread -lm -lz  -lc -L /usr/lib/gcc/x86_64-linux-gnu/4.8/ -lstdc++"' .

不過,你將依舊得到諸多錯誤:

... .../usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/librados.a(Crypto.o): In function `CryptoAESKeyHandler::init(ceph::buffer::ptr const&, std::basic_ostringstream, std::allocator >&)':/build/ceph-10.2.3/src/auth/Crypto.cc:280: undefined reference to `PK11_GetBestSlot'/build/ceph-10.2.3/src/auth/Crypto.cc:291: undefined reference to `PK11_ImportSymKey'/build/ceph-10.2.3/src/auth/Crypto.cc:304: undefined reference to `PK11_ParamFromIV'/build/ceph-10.2.3/src/auth/Crypto.cc:282: undefined reference to `PR_GetError'/build/ceph-10.2.3/src/auth/Crypto.cc:293: undefined reference to `PR_GetError'... ...

這些”undefined reference”指向的符號都是libnss3-dev庫中的,但由於libnss3-dev的安裝並沒有包含libnss3.a檔案,因此即便將libnss3顯式放在連結參數列表中,比如:”-lnss3″也無法連結成功:

/usr/bin/ld: cannot find -lnss3

libnss庫著實不是一個省油燈,經過幾番折騰發現,要想使用libnss的static archive,我們只能手工編譯,代碼在這裡可以擷取到:https://github.com/nss-dev/nss,並且這裡提供了nss的手工編譯方法。

綜上可以看出,純靜態編譯rbd-rest-api是很繁瑣的,於是我們這次選擇預設的動態連結方式,我們只需在docker image中安裝librados和librbd這兩個依賴庫即可,於是rbd-rest-api的Dockerfile的雛形可見:

From ubuntu:14.04MAINTAINER Tony Bai # use aliyun source for ubuntu# before building image ,make sure copy /etc/apt/sources.list here# COPY sources.list /etc/apt/RUN apt-get update && apt-get install -y --no-install-recommends librados-dev librbd-dev \                   && rm -rf /var/lib/apt/lists/*RUN mkdir -p /root/rbd-rest-apiCOPY rbd-rest-api /root/rbd-rest-apiCOPY conf /root/rbd-rest-api/confRUN chmod +x /root/rbd-rest-api/rbd-rest-apiEXPOSE 8080WORKDIR /root/rbd-rest-apiENTRYPOINT ["/root/rbd-rest-api/rbd-rest-api"]

我們一直在Ubuntu 14.04.x環境下進行各種測試,於是我們自然而然的選擇ubuntu:14.04作為我們的base image,構建鏡像:

# docker build -t "test/rbd-rest-api" .... ...Setting up librados-dev (0.80.11-0ubuntu1.14.04.1) ...Setting up librbd-dev (0.80.11-0ubuntu1.14.04.1) ...Processing triggers for libc-bin (2.19-0ubuntu6.9) ... ---> c987abc7a24dRemoving intermediate container 5257ac37392aStep 5 : RUN mkdir -p /root/rbd-rest-api ---> Running in dcabdb990c60 ---> ce0db2a027aaRemoving intermediate container dcabdb990c60Step 6 : COPY rbd-rest-api /root/rbd-rest-api ---> 453fd4b9a27aRemoving intermediate container 8b07b5de7537Step 7 : COPY conf /root/rbd-rest-api/conf ---> e956add07d60Removing intermediate container 6eaf6e4cf334Step 8 : RUN chmod +x /root/rbd-rest-api/rbd-rest-api ---> Running in cb278d1919c7 ---> 1e7b86072011Removing intermediate container cb278d1919c7Step 9 : EXPOSE 8080 ---> Running in 6a3f457eefca ---> e60cefb50f77Removing intermediate container 6a3f457eefcaStep 10 : WORKDIR /root/rbd-rest-api ---> Running in 703baf8c5564 ---> 6f1a5e5e145cRemoving intermediate container 703baf8c5564Step 11 : ENTRYPOINT /root/rbd-rest-api/rbd-rest-api ---> Running in 16dd4e7e3995 ---> 43f885b958c7Removing intermediate container 16dd4e7e3995Successfully built 43f885b958c7# docker imagesREPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZEtest/rbd-rest-api                                      latest              43f885b958c7        57 seconds ago      298 MB

測試啟動鏡像,注意我們“唯讀”掛載了本地路徑/etc/ceph:

# docker run --name rbd-rest-api --rm -p 8080:8080 -v /etc/ceph/:/etc/ceph/:ro test/rbd-rest-api2016/11/14 14:58:17 [I] [asm_amd64.s:2086] http server Running on http://:8080

我們來測試一下這個Docker中的rbd-rest-api service:

# curl  -v   http://localhost:8080/api/v1/pools/* Hostname was NOT found in DNS cache*   Trying 127.0.0.1...* Connected to localhost (127.0.0.1) port 8080 (#0)> GET /api/v1/pools/ HTTP/1.1> User-Agent: curl/7.35.0> Host: localhost:8080> Accept: */*>< HTTP/1.1 200 OK< Content-Length: 130< Content-Type: application/json; charset=utf-8* Server beegoServer:1.7.1 is not blacklisted< Server: beegoServer:1.7.1< Date: Mon, 14 Nov 2016 14:59:29 GMT<{  "Kind": "PoolList",  "APIVersion": "v1",  "Items": [    {      "name": "rbd"    },    {      "name": "rbd1"    }  ]* Connection #0 to host localhost left intact}

測試OK。

這裡不得不提的是:如果你掛載的是僅僅是/etc/ceph/ceph.conf的話,那麼當rbd-rest-api服務收到請求後,會返回:

Errcode=300, errmsg:error rados: No such file or directory

這是因為容器中的rbd-rest-api沒有看到ceph.client.admin.keyring,因此在登入ceph monitor時鑒權失敗了。當然你也可以不映射本地目錄,取而代之的是將/etc/ceph/ceph.conf和/etc/ceph/ceph.client.admin.keyring放入到鏡像中,後一種方法這裡就不詳細描述了。librados給出的錯誤提示真是太差了,本來應該是一個許可權的問題,居然說找不到librados。

二、Kuberize Ceph RBD API服務

容器化測試成功了,接下來就是將Ceph RBD API Kuberize化。根據上面Docker鏡像的設計,承載Ceph RBD API服務 Pod的Node上,必須要安裝了Ceph client,即包括ceph.conf和ceph.client.admin.keyring,於是有選擇性的調度Ceph RBD API服務到安裝了ceph client的kubernetes node上是這一節必須考慮的問題。

我們的思路是將rbd-rest-api的pod通過k8s調度到帶有指定label的k8s node上去,我們給kubernetes叢集的node打標籤,安裝了ceph client的叢集node,打的標籤為:zone=ceph。

# kubectl label nodes 10.46.181.146 zone=ceph# kubectl label nodes 10.47.136.60 zone=ceph# kubectl get nodes --show-labelsNAME            STATUS    AGE       LABELS10.46.181.146   Ready     32d       beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.46.181.146,zone=ceph10.47.136.60    Ready     32d       beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.47.136.60,zone=ceph

接下來就是在rbd-rest-api service的yaml中設定pod的調度策略了:

//rbd-rest-api.yamlapiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: rbd-rest-apispec:  replicas: 2  template:    metadata:      labels:        app: rbd-rest-api    spec:      containers:      - name: rbd-rest-api        image: registry.cn-hangzhou.aliyuncs.com/xxxx/rbd-rest-api:latest        #imagePullPolicy: IfNotPresent        imagePullPolicy: Always        ports:        - containerPort: 8080        volumeMounts:        - mountPath: /etc/ceph          name: ceph-default-config-volume      volumes:      - name: ceph-default-config-volume        hostPath:          path: /etc/ceph      nodeSelector:        zone: ceph      imagePullSecrets:      - name: rbd-rest-api-default-secret---apiVersion: v1kind: Servicemetadata:  name: rbd-rest-api  labels:    app: rbd-rest-apispec:  ports:  - port: 8080  selector:    app: rbd-rest-api

我們可以看到在Deployment的spec中有一個nodeSelector,這個設定可以讓k8s scheduler在調度service時只選擇具備zone=ceph label的Node。注意關於imagePullSecrets的設定,可以參考《Kubernetes從Private Registry中拉取容器鏡像的方法》一文。

2016, bigwhite. 著作權.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.