返回 登录
0

有状态容器实践:k8s集成ceph分布式存储

阅读6235

图片描述

大家好,今天由我为大家介绍一下我们对于k8s与ceph集成的预研成果。对于k8s与ceph,我们也了解有限,有些理解不对的地方,还请大家指正。

图片描述

今天将基于以上6点内容来分享。如果大家有任何问题,也欢迎在微课堂之后在群中直接提出,大家共同探讨。

图片描述

总结了一下,产生存储痛点的原因大致有以下几个:

•默认情况下,容器产生的数据只存于内存中,容器一销毁,数据也随之丢失

•Docker可通过-v参数,将一个本地目录挂载至容器,但存在不能跨越主机的问题,无法在集群中应用•Docker还可以通过各种存储插件支持将各种类型的存储做为后端存储,但也存在无法跨主机集群应用的问题

•Docker+k8s一起的时候,存储的问题更突显。

k8s的Pod是不稳定的,随时可能会因为重新调度而在某台机器上销毁,而在另一台机器上新建,持久化存储必须跟得上这种调度,随时准备随容器一起进行迁移。

图片描述

图片描述

Torus是一种针对容器集群量身打造的存储系统,可以为通过Kubernetes编排和管理的容器集群提供可靠可扩展的存储。

这是继etcd、rkt、flannel,以及CoreOSLinux之后CoreOS发布的另一个开源产品。

Torus的产品特性:

1.扩展性:与etcd类似,Torus也是一种构建块,可以实现包括分布式块设备( Distributedblock device)或大型对象存储在内不同类型的存储。Torus使用Go语言编写并使用gRPC协议,用户可以方便地用任何语言创建Torus客户端。

2.易用性:专门针对集群和Kubernetes等集群流程平台(Clusterorchestrationplatform)设计的Torus可用简单的方法部署和运维,并可随时缩放。

3.准确性:Torus使用etcd分布式键值数据库存储并检索文件或对象元数据。etc d为必须快速可靠执行的分布式系统核心运作提供了一个坚实、经得起考验的基础。

4.缩放性:Torus目前可缩放至数百个节点,并可将多个共用磁盘以单一存储池 的方式使用。

虽然Torus的特性看起来很美,可以毕竟它还太年轻,成熟稳定需要一定的时间。目前我们只是保持持续的关注。

图片描述

第二种则是Flocker,目前也是很火热的个项目。Flocker提供了开源容器数据卷管理系统。它提供了数据迁移的工具,从而解决了有状态服务的容器化难题。尤其适用于数据库这样的容器。通常,容器的数据卷与单个server绑定,Flocker数据卷,则可以随容器迁移而迁移。Flocker为实现有状态的微服务提供了便利。上图是它的架构示意图,它要求每个节点上都必须要安装它的flockerplugin, 然后由flockercontrol进行统一调度,最终实现数据与容器同步迁移。

图片描述

如上图所示,展示了存储随容器迁移的过程:

1.当容器发生迁移时,flocker可以保证容器所挂载的数据卷也会跟着同步迁移。

2.迁移要求各个主机上都需要安装flockerplugin

3.原理其实是在其它主机上将容器启动的时候,将数据卷重新挂载其上。因此,单个容器迁移时,服务存在一定的中断,但这个过程一般很短。

flocker其实是我们比较心仪的方式。但是因为系统的限制,目前没有办法安装。我们同样对它保持着高度的关注。

图片描述

最后介绍的这第三种方案,则是比较常规的方案,基于k8s本身的能力以及第三方的插件来实现,当然还必须后端有对应的存储进行支持。k8s的pv可以向容器提供持久存储。它需要先于Pod创建,然后在pod创建的时候,绑定给它。也可以不使用pv, 直接在声明pod的时候,使用mountpoint属性声明需要使用的持久卷。pv与mountpoint都支持多种类型的存储,基本上涵盖了目前的主流方式。

图片描述

以上就是一个nfs类型的pv的声明文件,将它保存成yaml文件,使用kubectlcraete–fxxx.yaml 这种方式就可以创建一个pv。在pv中,可以定义它的名称,可以定义它的容量,也可以定义它的访问方式。

访问方式有三种: 单节点可读可写(ReadWriteOnce),多节点只读(ReadOnlyMany),多节点可读可写(ReadWriteMany)。也可以定义它们的回收策略,回收策略是指当容器销毁时,对其所挂载的卷的处理方式。处理方式目前也有三种:保持数据(Retain), 清除数据(Recycle), 删除卷(Delete).当前,只有NFS和HostPath的存储可以支持清除数据(Recycle),而删除卷一般需要有底层IAAS的支持才能实现。

图片描述

图片描述

我们最终选择了k8s+cephrbd的方式来构建我们的容器存储。这有一部分的原因是因为需要k8s必须跑在coreos上造成的。关于为什么我们的k8s集群必须跑在coreos之上,这个我们后面会有说明。

图片描述

•没有选择最新的Torus,因为它太年轻,不够成熟

•也没有选择flocker,因为无法在coreos系统上安装

•我们选择了比较保守的插件+对应后端存储的方案。

最终的选择:k8s+cephrbd。选择ceph,是因为它的稳定与高效,而且目前与k8s的集成也结合得比较好。

图片描述

图片描述

下面来介绍一下ceph,相信其实一大部分人都已经认识了它:

•Ceph是一种为优秀的性能、可靠性和可扩展性而设计的统一的分布式文件系统

•在2004年由Sage Weil开发,并于2006年基于开源协议开源了Ceph

•ceph同时支持文件存储,块存储,对象存储

•ceph具有高扩展性、高可靠性、高性能的优点,这三个特点也是企业级存储需要的

•Ceph其使用最多的是最成熟的Ceph RBD(块存储),其次是Ceph RADOS

•十年的历史,成千上万的用户,是现代云平台存储的首选

图片描述

CEPH整体架构:

•ceph的底层是自已开发的rados

•rados之上提供了librados与cephfs

•app可以直接使用librados(源码级集成)

•librados之上有radosgw与rbd

•radosgw对外提供restapi,封装librados的能力(api级集成)

•rbd则提供块存储能力

图片描述

ceph组成:

•Ceph Client 是 Ceph文件系统的用户

•Ceph Metadata Daemon 提供了元数据服务器

•Ceph Object Storage Daemon 提供了实际存储(对数据和元数据两者)

•Ceph Monitor 提供了集群管理

图片描述

ceph的概念:

•用户文件作为Object先映射到PG(Placement Group)

•再由PG映射到OSD set

•每个Pool有多个PG,每个Object通过计算hash值并取模得到它所对应的PG

•PG再映射到一组OSD,第一个OSD是Primary,剩下的都是Replicas

•从PG分配到OSD使用了一种伪随机算法CRUSH

图片描述

图片描述

安装规划:

•安装目标:搭建一套ceph块存储的功能验证环境

•ceph采用的版本是当前最新的 10.2.1

•共4个节点,1个专门用来安装(只安装ceph-deploy),其它3个均为ceph的工作节点(ceph-osd)。3个工作节点中选择1个做为ceph管理节点(ceph-monitor)。因为只需要搭建ceph块存储,不需要元数据服务节点(mds)

•节点底层系统为centos7.1

•节点均为虚拟机,配置为4c4G,配置80G硬盘

•节点均有两块网卡,内网(10.16.16.0/24),外网(10.15.15.0/24)

•ceph的client节点由k8s的工作节点充当

•如图所示,ceph-60为Ceploy-Deploy节点,ceph-61即是osd节点,也是monitor节点。cehp-62与ceph-63则为单纯的osd节点。

•61,62,63均是通过60进行远程安装

•61,62,63上的osd均受61的monitor管理

•外部的ceph-client通过61进行连接与api调用

图片描述

首先,我们需要将各节点的系统centos7的内核升级。因为centos7.1默认的内核版本为3.10.0-123,如果要用来安装ceph, 推荐内核至少升级到 3.18, 因为内核 3.18以后对krdb添加了一个重要特性: discard,这个特性可以根据块内文件的删除同步改变块的真实大小,从而节省磁盘空间。

同时,内核升级过程中,也可以把systemd的版本从218升级至219以上,避免执行cephminitor节点初始化的时候,出现的上述安装错误。

图片描述

centos7 内核升级具体步骤:

1.最新的内核可以在这里看到: https://www.kernel.org/

2.升级至指定版本内核,请自行下载对应版本的rpm包进行安装

3.自动升级至最新版本内核

    rpm--import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org。

    rpm-Uvhhttp://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

    yum--enablerepo=elrepo-kernel install kernel-ml-develkernel-ml –y

4.更新完成之后,查看当前内核版本: uname-r,会发现还是老内核,新内核需要重启之后才能生效

5.查看默认启动顺序:awk-F\’ ‘$1=="menuentry " {print $2}’ /etc/grub2.cfg

6.设置默认启动项: grub2-set-default 0

7.重启系统,切换至新的内核:reboot

导入证书的时候,可能会出现: curl: (60) Peer‘s Certificate has expired.这样的证书错误。解决办法:直接使用wgethttps://www.elrepo.org/RPM-GPG-KEY-elrepo.org 将证书文件下载到本地,然后在本地执行导入。由于wget也是由curl发出http请求,我们下载的时候要加上–no-check-certificate参数进行证书忽略。

图片描述

安装准备(所有节点)

在各个node节点创建ceph用户,并将它添加至sudo用户组,并修改各主机名

在各个node节点上安装openssh-server

在ceph-deploy节点上,生成ssh密钥,并将公钥发送至所有的node节点,使它可以免密码ssh登陆

在4个节点中添加ceph的安装源

[ceph-noarch]

name=Cephnoarch packages

baseurl=http://ceph.com/rpm-infernalis/el7/noarch

enabled=1

gpgcheck=0

type=rpm-md

gpgkey=https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc

在4个节点中修改 /etc/hosts

10.15.15.60ceph-60

10.15.15.61ceph-61

10.15.15.62ceph-62

10.15.15.63ceph-63

生成ssh密钥,并将公钥发送至所有的node节点,可以使用ssh-keygen与 ssh-copy-id工具。让deploy节点与其它节点建立互信,是为了减少在安装过程中密码的输入。

图片描述

安装ceph:

1.安装 ceph-deploy: yum update && yum install ceph-deploy

2.创建ceph的cluster, 并设置ceph-61为ceph的 monitor: sudoceph-deploy new ceph-61

3.修改ceph.conf文件,添加clueter network与public network

cluster network =10.16.16.0/24

public network =10.15.15.0/24

4.在60上生成一个 ~/.ssh/config文件,内容如下

Host ceph-61

Hostname ceph-61

User ceph

Host ceph-62

Hostname ceph-62

User ceph

Host ceph-63

Hostname ceph-63

User ceph

5.在60上为61,62,63安装cpeh

sudoceph-deploy install ceph-61 ceph-62 ceph-63

6.在60上执行cephmon的初始化,并设置61为cephmonitor节点

ceph-deploy –overwrite-confmon create-initial

sudoceph-deploy admin ceph-61

图片描述

创建OSD节点

1.在三个节点上分别创建目录,例如在61上创建两个目录: sudomkdir -p /opt/ceph/osd61-1 /opt/ceph/osd61-2,三节点两个两个目录,总共创建6个目录

2.为这些目录设置所有权,所有权归 ceph:ceph: chown -R ceph:ceph /opt/ceph/osd61-1 /opt/ceph/osd61-23.创建osd: sudo ceph-deploy osdprepare ceph-61:/opt/ceph/osd61-1 ceph-61:/opt/ceph/osd61-24.激活osd: sudo ceph-deploy osdactivate ceph-61:/opt/ceph/osd61-1 ceph-61:/opt/ceph/osd61-25.查看 ceph的状态

上图中是我们安装好之后,运行cephosddump显示的结果。

可以看出,我们一共创建了6个osd,每个osd的权重都是一样的。

图片描述

上面可以看到,我们的ceph状态是正常的,有6个osd,6个都是启用的,处于pg中。这样,我们的ceph块存储就安装好了。

我们总共有三个节点,我在每个节点上创建了两个目录作为osd的数据存储目录,共有6个osd。

ceph中因为有了ceph-deploy这个工具,安装起来还是很轻松的。

图片描述

图片描述

CoreOS是一个基于Linux,systemd和Docker的小型操作系统。它借鉴了Google的Chrome OS,特别是其对数千服务器的分布式管理,CoreOS项目是Google ChromeOS代码的一个fork版本,目前已成为一个超级精简的服务器操作系统,进化速度堪比ChromeOS。

我们没有使用传统的centos,redhat 或 ubuntu之类的操作系统,而是大胆地采用了coreos做为kubernetes底层的操作系统,是因为它有如下优点:

占用内存少。比典型的服务器版本Linux少占40%的内存,资源利用率高

可靠,高速,及时的补丁更新,可以系统双分区滚动整体更新

所有应用都安装在容器中,对系统依赖低

默认支持docker

专为大规模部署设计,轻量稳定且高效

多个云平台支持,支持目前EC2、Rackspace、GCE等云服务提供商

但是同样,有得就有失,它也有一些不足与限制:

没有包管理

没有编译器,也没有python,perl之类的解释器

很多目录都是只读的,不能像传统linux系统那样来修改配置

总体比较而言,coreos系统还是利大于弊。它的轻量,低污染,系统双分区滚动升级等都是我们最看重的特性。

图片描述

要想执行ceph的块存储挂载,必须加载必要的内核模块。krbd是cephrbd依赖的一个内核模块,它默认已经安装在coreos系统之中了,但是默认是不启用的。

我们需要把它加载进系统:

modproberbd

再看一下加载的结果:

core@ck68 ~ $ lsmod |greprbd
rbd 65536
libceph 204800 1 rbd

自动开始加载krbd:

创建文件/etc/modules-load.d/rbd.conf,文件内容只需要写上需要加载的模块名称即可:
rbd

下次重启之后,系统就会自动将rbd模块加载进来了

图片描述

要想kubernates可以正常执行rbd挂载,必要的条件就是要在系统中有可以正常执行的rbd命令

这在其它系统上很好解决,coentos7上执行yum install ceph-common就行,在其它系统上问题也不大

但在coreos中,这是个比较大的问题。因为coreos上没有包管理器,也没有gcc之类的编译器,要想直接安装在coreos上是没可能的

通过查阅大量的国外资料,我们最终找到了办法:用容器来实现这个命令

制作 common-ceph的 image,将ceph-common安装在容器内部,这里我们的镜像名称就叫 ceph-common

在k8s的各个工作节点上,创建/opt/bin/rbd文件,内容如下:

图片描述

上面示例了一个的含有rbd卷的rc声明文件。在创建这个rc之前,必须要先在ceph中创建对应的块,还有必须要把ceph的证书文件拷贝至cephclient节点的对应位置。

证书还有另外一方式可以避免拷贝文件,那需要先在k8s中创建对应的secret, 然后在rc中声明使用这个secret。在使用 kubectl创建rc的时候,会出一个警告,这只是客户端对文件的一个校验,确定文件没有问题的话,可以添加–validate=false 来忽略这个警告,直接创建rc

图片描述

rc创建成功了,但是pod却迟迟没有running。查看pod对应节点的kubelet的日志,发现了rbd: map failed executable file notfound in $PATH 的问题:

不是在系统的/opt/bin目录下放了rbd的可执行脚本吗?为什么会找不到呢?在coreos系统中,默认帮我们扩展了PATH的目录,将/opt/bin自动添加至了PATH中。

这样,直接放在/opt/bin之下的可执行文件是可以直接调用的。

rbd可以不加路径,在终端中的任何目录下直接被调用,添加正确的参数,可以手动成功对rbd进行挂载。

经过多天的排查,最终找到了原因所在,问题出在systemd上。所有通过systemd启动的服务,使用的PATH环境变量不是系统中通过传统方式声明的。它的PATH环境变量,必须通过systemd的方式进行指定。

解决办法:

修改/etc/systemd/system.conf文件,在最后添加如下内容:

  DefaultEnvironment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin"

然后执行配置重新加载,并重启kubelet服务

systemctl daemon-reload
systemctl restart kubelet

经验证,配置添加之后,问题解决,可随着pod的创建与删除正常挂载与卸载对应的rbd块存储.
目前,我们还仅对coreos上的k8s与ceph的分布式块存储进了预研与验证,还缺少对其性能的严格测试。而且目前据我们的验证来看,ceph块存储还不太合适用来做为容器的共享存储使用,还需要进一步验证,或寻找其它的方案。数据的安全也是需要考虑的方面。期待与大家一起来共同探讨这些方面的问题,共同进步。

普元云计算专区:http://primeton.csdn.net/m/zone/primeton/index#

普元公众号:
图片描述

评论