Ceph转角遇见k8s:记分布式系统界一对名角的浪漫牵手

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、小结

让我们祝福这对新人能够和谐相处,幸福美满!如果出了问题,一定要原厂保修,不要自己修哦!

K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址