1. 程式人生 > >Ceph轉角遇見k8s:記分散式系統界一對名角的浪漫牽手_Kubernetes中文社群

Ceph轉角遇見k8s:記分散式系統界一對名角的浪漫牽手_Kubernetes中文社群

1、“佛說前世無數次的痛苦掙扎,換得今生的一次邂逅。

話說分散式系統界的名角ceph,志向遠大,他要做分散式儲存領域的linux,但接觸過ceph的愛好者在初次使用ceph時,都經歷過比較痛苦的部署過程。還好後來有了ceph-deploy工具,部署會簡單很多。但是由於ceph安裝包的依賴關係有點複雜,特別是在沒有匹配作業系統版本的ceph安裝包時,通過原始碼編譯並安裝也是更加頭痛的一件事情:

  1. 不僅需要依賴包,而且需要開發包;
  2. 編譯過程漫長,一個4核8GB的主機編譯需要將近兩個多小時;
  3. 佔用磁碟空間大,大約十幾個GB。

雖然ceph比較平易近人,但對於ceph叢集的運維也是一個折騰運維工程師的苦差事。Ceph元件中的程序異常掉線,需要及時將其拉起來。服務元件使用的資源如果不加限制,會互相影響。mon是整個叢集的關鍵元件,因此更需要保證其高可用。

2、當ceph遇上k8s,就有了我們下面要介紹的愛情故事了,快搬來小馬紮聽我慢慢道來。

在這裡先簡單介紹一下ceph及k8s兩個的性格特點:

Ceph號稱高可用的分散式儲存系統,通過多個MON節點(通常為3個)維護叢集的狀態及元資料資訊,而真正儲存資料的OSD節點通過向MON節點彙報狀態,並通過CRUSH演算法將資料副本佈局到相應OSD的所在磁碟上,完成資料的持久化儲存。為了保證每個資料副本的高可用,通常採用三副本或EC方式。而提供檔案服務的mds元件和提供物件儲存的rgw元件都不儲存實際資料,只是作為服務態程序存在。

K8s是Google開源的容器叢集管理系統,為容器化的應用提供資源排程、部署執行、服務發現、擴容縮容等整一套功能。系統分為管理節點和容器化節點兩種,通過管理節點將服務例項以pod為單位排程到容器化的計算節點上執行。K8s的管理理念很牛:像管理畜生一樣管理你的應用,還別說,伺服器資源的利用率顯著提升。

此處,默默無聞的幕後工作者docker要出來吼一下了。Docker出身高貴,是核心家族namespace和cgroup的後裔,他通過把應用所依賴的環境及軟體庫打包在映象中,讓應用在容器內自由執行,通過虛擬網路,和外界互聯。

Ceph想要和k8s牽手,需要有一個磨合的過程,要摒棄一些個性,和容器大家庭做好融合。

首先ceph的osd元件需要使用到節點上的磁碟,一個osd對應一個磁碟。因此osd的pod需要和響應的主機繫結。Mon只是提供叢集狀態維護,除了少量的集群系統資料,可以執行在任何節點上,但它必須有一個固定的IP地址提供給眾多OSD及客戶端連線,而k8s的service恰好解決了這樣一個問題。同樣mds和rgw也可以採用service對外提供服務地址和負載均衡。

而這些少量的狀態和配置資料可以通過k8s的PV儲存,這樣,服務元件就可以在任何節點上執行。

3、牽手細節

硬體及基礎軟體環境:多臺通過區域網互聯的主機,並且作為容器化的主機有相應的磁碟或分割槽,linux作業系統核心(3.10以上)支援docker。

首先,需要在基礎環境上部署一套完整的k8s叢集,然後需要準備一個ceph的docker映象,本文中使用docker.io/ceph/daemon:tag-build-master-jewel-centos-7。

1. 準備工作

先建立用於儲存ceph叢集狀態資訊的持久化卷(PV)以及PVC,本文用於PV的分散式儲存採用NFS。

pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-conf
spec:
capacity:
storage: 10Mi
accessModes:
– ReadWriteMany
nfs:
path: /ceph4k8s/conf
server: 192.168.6.21

apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-data
spec:
capacity:
storage: 10Gi
accessModes:
– ReadWriteMany
nfs:
path: /ceph4k8s/data
server: 192.168.6.21

Pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-conf
spec:
accessModes:
– ReadWriteMany
resources:
requests:
storage: 10Mi

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-data
spec:
accessModes:
– ReadWriteMany
resources:
requests:
storage: 10Gi

2. 需要通過容器POD將ceph的MON元件部署起來,步驟如下:

首先建立RC和service,如mon.yaml檔案所示:

apiVersion: v1
kind: ReplicationController
metadata:
app: ceph-mon
spec:
replicas: 1
selector:
app: ceph-mon
template:
metadata:
labels:
app: ceph-mon
spec:
hostname: mon
containers:
– name: ceph-mon
image: docker.io/ceph/daemon:4k8s
imagePullPolicy: Never
ports:
– containerPort: 6789
protocol: TCP
env:
– name: MON_IP
value: ceph-mon
– name: CEPH_PUBLIC_NETWORK
value: 18.18.0.0/16
– name: CEPH_CLUSTER_NETWORK
value: 192.168.0.0/16
args:
– mon
volumeMounts:
– mountPath: /etc/ceph
name: ceph-conf
– mountPath: /var/lib/ceph
name: ceph-data
volumes:
– name: ceph-conf
persistentVolumeClaim:
claimName: ceph-conf
– name: ceph-data
persistentVolumeClaim:
claimName: ceph-data


kind: Service
apiVersion: v1
metadata:
labels:
app: ceph-mon
name: ceph-mon
namespace: default
spec:
type: NodePort
clusterIP: 11.11.1.1
ports:
– port: 6789
targetPort: 6789
selector:
app: ceph-mon

執行kubectl create -f mon.yaml

待POD正常啟動後,可以發現nfs中的PV目錄被寫入了叢集的系統資料。

Kubectl exec ceph-mon-xxxxx — ceph -s

顯示如下資訊:

cluster fa6fba4c-40f6-4c51-8a5d-fd0be12dc421
health HEALTH_ERR
64 pgs are stuck inactive for more than 300 seconds
64 pgs stuck inactive
no osds
monmap e1: 1 mons at {mon=18.18.67.2:6789/0}
election epoch 3, quorum 0 mon
osdmap e1: 0 osds: 0 up, 0 in
flags sortbitwise
pgmap v2: 64 pgs, 1 pools, 0 bytes data, 0 objects
0 kB used, 0 kB / 0 kB avail
64 creating

3. 建立OSD的POD,網路採用host方式

採用這種網路方式,一方面是通訊效率高;另一方面是能夠利用主機名和裝置(OSD)形成所屬關係,便於crush map中區分不同host上的osd。由於OSD與MON進行網路連線時,通訊元件中會對比驗證傳送的源IP地址與目標IP地址,如果不一致將出錯。而我們通過將MON元件服務化後,對外提供固定的虛擬IP(CLUSTER-IP),而自己內部是採用Pod-IP,因此在此處會因驗證不通過而無法建立連線,因此需要將原始碼中src/msg/async/AsyncConnection.cc:1158和vi src/msg/simple/Pipe.cc:981附近的IP驗證程式碼註釋掉,然後重新編譯,替換映象中的可執行檔案ceph-osd、ceph-mds、radosgw

建立osd-0.yaml檔案

apiVersion: v1
kind: ReplicationController
metadata:
name: ceph-osd
spec:
replicas: 1
selector:
name: ceph-osd
template:
metadata:
labels:
name: ceph-osd
spec:
nodeName: 192.168.0.21
containers:
– name: ceph-osd
image: docker.io/ceph/daemon:4k8s
imagePullPolicy: Never
securityContext:
privileged: true
env:
– name: OSD_DEVICE
value: /dev/sdb
– name: OSD_TYPE
value: disk
args:
– osd
volumeMounts:
– mountPath: /etc/ceph
name: ceph-conf
– mountPath: /var/lib/ceph
name: ceph-data
– mountPath: /dev
name: dev
hostNetwork: true
volumes:
– name: ceph-conf
persistentVolumeClaim:
claimName: ceph-conf
– name: ceph-data
persistentVolumeClaim:
claimName: ceph-data
– name: dev
hostPath:
path: “/dev”

其中nodeName和環境變數中OSD_DEVICE要根據實際部署的多個OSD來設定。

執行kubectl create -f osd-*.yaml之後,再到mon容器中執行ceph -s,可以發現osd都加進叢集了。

4. 咱倆真的合適嗎?

真心大考驗之一

刪除mon的Pod模擬程序異常退出的故障,看叢集是否仍然正常。

Kubectl delete pod ceph-mon-xxxxx

發現新的pod又被建立了,同時檢視叢集狀態,仍然正常。

真心大考驗之二

將k8s叢集中執行mon元件Pod的node主機宕機,發現k8s在新的node上建立了新的mon Pod,ceph叢集狀態依然正常。

經過以上考驗之後,基本可以確定ceph與k8s的結合是合適的。下面接著把mds和rgw元件部署完成,使得ceph叢集能夠對外提供檔案介面、塊介面和物件介面。

Mds.yaml

apiVersion: v1
kind: ReplicationController
metadata:
name: ceph-mds
spec:
replicas: 1
selector:
name: ceph-mds
template:
metadata:
labels:
name: ceph-mds
spec:
containers:
– name: ceph-mon
image: docker.io/ceph/daemon:4k8s
imagePullPolicy: Never
env:
– name: CEPHFS_CREATE
value: “1”
args:
– mds
volumeMounts:
– mountPath: /etc/ceph
name: ceph-conf
– mountPath: /var/lib/ceph
name: ceph-data
volumes:
– name: ceph-conf
persistentVolumeClaim:
claimName: ceph-conf
– name: ceph-data
persistentVolumeClaim:
claimName: ceph-data

Rgw.yaml

apiVersion: v1
kind: ReplicationController
metadata:
name: ceph-rgw
spec:
replicas: 1
selector:
name: ceph-rgw
template:
metadata:
labels:
name: ceph-rgw
spec:
containers:
– name: ceph-rgw
image: docker.io/ceph/daemon:4k8s
imagePullPolicy: Never
args:
– rgw
volumeMounts:
– mountPath: /etc/ceph
name: ceph-conf
– mountPath: /var/lib/ceph
name: ceph-data
volumes:
– name: ceph-conf
persistentVolumeClaim:
claimName: ceph-conf
– name: ceph-data
persistentVolumeClaim:
claimName: ceph-data

kind: Service
apiVersion: v1
metadata:
labels:
app: ceph-rgw
name: ceph-rgw
namespace: default
spec:
type: NodePort
clusterIP: 11.11.1.2
ports:
– port: 80
targetPort: 80
selector:
app: ceph-rgw

4、小結

讓我們祝福這對新人能夠和諧相處,幸福美滿!如果出了問題,一定要原廠保修,不要自己修哦!