分布式存储之Ceph使用指南--部署篇(未完待续)
一、前言
Ceph是一个可靠、自动重均衡、自动恢复的分布式存储系统,其性能卓越、安全可靠,专门面向对象、块与文件存储,提供一个统一的存储服务,支持统一的接口和先进的架构;它可以将多台服务器组成一个超大集群,把这些机器中的磁盘资源整合到一块儿,形成一个大的存储资源池(支持PB级别),然后按需分配给客户端应用使用。而红帽® Ceph® 存储是专为私有云架构设计的软件定义存储平台,现在作为与 OpenShift® 上的红帽 OpenStack 服务组合的解决方案独家提供(现在由IBM来维护),这也是我们最初了解ceph作为openstack家族成员的初始印象。 ceph发展已非常成熟,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack一般与Ceph整合以支持虚拟机镜像的后端存储。
相关资源:ceph官网、ceph文档、ceph-backlog、Redhat ceph、openstack部署手册
二、产品特性和选用标准
Ceph的核心优势在于其去中心化架构和高度可扩展性。通过基于RADOS(可靠自动分布式对象存储)的底层设计,Ceph无需依赖单一主节点,避免了单点故障。其数据分布采用CRUSH
算法,动态计算数据位置而非依赖中心化元数据表,性能随节点增加线性提升。另外ceph一大特点还是其的经济性(现实应用的数据增长量级已经是企业成本的重要考量),这体现在使用普通硬件即可构建PB级存储,支持混合部署(SSD+HDD);再者。ceph的统一存储特性允许同一集群同时提供块(RBD)、文件(CephFS)、对象(S3/Swift)三种接口,从而简化了多云环境管理。
特性与技术对比:
- 与GlusterFS对比:Ceph的强一致性模型(基于PG和OSD机制)适合数据库等关键负载,而GlusterFS的最终一致性更适配大文件吞吐场景。
- 与MinIO对比:MinIO专注对象存储且轻量,但Ceph的多协议支持更适合混合工作负载。
- 与Lustre对比:Lustre在HPC场景下性能更高,但Ceph的自我修复和自动化管理能力更优。
关键差异点:Ceph的CRUSH
算法实现数据均匀分布,而其他系统多依赖静态哈希或目录服务。
Ceph的优势:
- 高性能
- 摒弃了传统的集中式存储元数据寻址的方案,采用
CRUSH
算法,数据均衡分布,并行度高- 考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨机房、机架感知等
- 能够支持上千个存储节点的规模。支持TB到PB级的数据
- 高可用
- 副本数可以灵活控制
- 支持故障域分隔,
数据强一致性
- 多种故障场景自动修复自愈
- 无单点故障,自动管理
- 高扩展性
- 去中心化
- 扩展灵活
- 随着节点增加,性能线性增长
- 特性丰富
- 支持三种存储接口:对象存储,块设备存储,文件存储
- 支持自定义接口,支持多种语言驱动
选用ceph的标准:
1、适用场景:需要统一存储接口、EB级扩展或强一致性要求的场景(如OpenStack云平台)。
2、规避场景:超低延迟(<1ms)需求或小规模非结构化数据(如NAS替代)。
3、硬件建议:每OSD节点至少16核CPU、64GB内存、10Gbps网络,SSD作Journal盘可提升IOPS。
基础概念:
- 对象:它是Ceph最底层的存储单元,每个Object包含元数据和原始数据。
- PG(Placement Groups)是一个逻辑的概念,一个PG包含多个OSD。引入PG这一层其实是为了更好的分配数据和定位数据。
- Librados:是RADOS提供的库。因为RADOS很难直接访问,因此上层的RBD、RGW和CephFS都是通过Librados访问的。
- CRUSH:是Ceph使用的数据分布算法,让数据分配到预期的地方。
- RBD全称RADOS block device,是Ceph对外提供的块设备服务。
- RGW全称RADOS GateWay,是Ceph对外提供的对象存储服务,接口与S3、Swift兼容。
- CephFS全称Ceph File System,是Ceph对外提供的文件系统服务。
三、架构及原理
如上图架构所示,ceph工作原理简述如下:
- RADOS层:核心分布式对象存储,包含OSD(数据存储)和Monitor(集群状态管理),是Ceph集群的精华,帮用户实现数据分配、Failover等集群操作。Ceph所有的存储功能都是
基于RADOS实现
的。RADOS(Reliable Autonomic Distributed Object Store)采用**C++**开发,所提供的原生Librados API
包括C和C++两种。Ceph的上层应用调用本机上的librados API
,再由后者通过socket与RADOS集群中的其他节点通信并完成各种操作。- 数据写入流程:客户端→MON获取Cluster Map→CRUSH计算PG和OSD位置→主OSD协调副本写入。
- RADOS GateWay、RBD其作用是在librados库的基础上提供抽象层次更高、更便于应用或客户端使用的上层接口。其中RADOS GW是一个提供与Amazon S3和Swift兼容的
RESTful API
的gateway,以供相应的对象存储应用开发使用。Ceph的底层是RADOS,RADOS本身也是分布式存储系统;- RBD则提供了一个标准的块设备接口,常用于在虚拟化的场景下为虚拟机创建volume。目前,RedHat已经将RBD驱动集成在KVM/QEMU中,以提供虚拟机访问性能。以上两种方式目前在云计算中应用的比较多。
- CephFS则提供了
POSIX接口
,用户可直接通过客户端挂载使用。它是内核态的程序,所以无需调用用户空间的librados库。它通过内核中的net模块
来与RADOS进行交互。- PG(Placement Group):逻辑数据分片单元,通过PG数平衡负载与恢复效率。由于Object的数量很多,所以Ceph引入了PG的概念用于管理Object,每个Object最后都会通过CRUSH计算映射到某个PG中,一个PG可以包含多个Object。Ceph条带化之后,将获得N个带有唯一OID(即Object的id)。Object id是进行线性映射生成的,即有file的元数据、Ceph条带化产生的Object的序号连缀而成。此时object需要映射到PG中,该映射包括两部分:
- 有Ceph集群指定的静态Hash函数计算Object的OID,获取到其Hash值
- 将该Hash值与mask进行操作,从而获得PG ID
根据RADOS的设计,假定集群中设定的PG总数为M(M一般为2的整数幂),则mask的值为M-1,由此,Hash值计算之后,进行按位与操作是想从所有PG中近似均匀地随机选择。基于该原理以及概率论的相关原理,当用于数据量庞大的Object以及PG时,获得到的PG ID是近似均匀的。
- EC(纠删码):可降低存储开销(如4+2配置容忍2节点故障,空间利用率仅1.5倍)。
- Mon节点:监控着整个Ceph集群的状态信息,监听于tcp的
6789
端口。每个Ceph集群中至少要有一个Mon节点,官方推荐每个集群至少部署三台
。Mon节点中保存了最新的版本集群数据分布图(Cluster Map
)的主副本。客户端在使用时,需要挂载Mon节点的6789端口,下载最新的Cluster Map,通过CRUSH算法获得集群中各OSD的IP地址,然后再与OSD节点直接建立连接来传输数据。因此对于Ceph来说,并不需要有集中式的主节点用于计算与寻址,客户端分摊了这部分工作。而且客户端也可以直接和OSD通信,省去了中间代理服务器的额外开销。而Mon节点之间使用Paxos算法来保持各节点Cluster Map的一致性;各Mon节点的功能总体是一样的,相互间的关系可以被简单理解为主备关系。如果主Mon节点损坏,其他Mon存活节点超过半数时,集群还可以正常运行。当故障Mon节点恢复时,会主动从其他Mon节点拉取最新的Cluster Map。
- Mon节点并不会主动轮询各个OSD的当前状态,相反,OSD只有在一些特殊情况下才会上报自己的信息,平常只会简单的发送心跳。特殊情况包括:1)新的OSD被加入集群;2)某个OSD发现自身或其他OSD发生异常。Mon节点在收到这些上报信息时,则会更新Cluster Map信息并加以扩缩。Cluster Map信息是以异步且lazy的形式扩散的。Monitor并不会在每一次Cluster Map版本更新后都将新版广播至全体OSD,而是有OSD向自己上报信息时,将更新回复给对方。类似的,各个OSD也是在和其他OSD通信时,如果发现对方的OSD中持有的Cluster Map版本较低,则把自己更新的版本发送给对方。
Ceph主要有三个基本进程:
- OSD:实际的存储层
用于集群中所有数据与对象的存储。处理集群数据的复制、恢复、回填、再均衡。并向其他osd守护进程
发送心跳,然后向Mon提供一些监控信息。当Ceph存储集群设定的数据有两个副本时(一共存两份),则至少需要两个OSD守护进程,即两个OSD节点,集群才能到达active+clean
状态。OSD是强一致性的分布式存储。- MDS(可选)
它为Ceph文件系统提供元数据计算、缓存与同步。在Ceph中,元数据也是存储在osd节点中的,mds类似于元数据的代理缓存服务器。MDS进程并不是必须的进程,只有需要使用CephFS
时,才需要配置MDS节点。Mds虽然是元数据服务器,但是它不负责存储元数据,元数据也是被切成对象存在各个OSD节点中。在创建CephFS时,应至少创建两个Pool,一个用于存储数据,另一个用于存放元数据。Mds只是负责接收用户的元数据查询请求,然后从OSD中把数据取出来映射进自己的内存中供客户访问。所以Mds其实类似一个代理缓存服务器,替OSD分担了用户的访问压力。
- Monitor
用于监控整个集群的状态,维护集群的cluster MAP二进制表,保证集群数据的一致性。ClusterMAP描述了对象块存储的物理位置,以及一个将设备聚合到物理位置的桶列表。
公式示例:CRUSH算法权重计算
wi=disksizeTB1TB×10kRPM7.2kRPMw_i = \frac{disk_size_TB}{1TB} \times \frac{10k_RPM}{7.2k_RPM} wi=1TBdisksizeTB×7.2kRPM10kRPM
Ceph数据的存储过程:
无论使用ceph哪种存储方式(对象、块、文件系统),存储的数据都会被切分成对象(Objects)。Objects size大小可以由管理员调整,通常为2M或者4M。每个对象都会有一个唯一的
OID
,有ino
和ono
生成:ino是文件的File ID,用于全局唯一标示每一个文件,而ono是分片的编号。例如,一个文件FileID是A,它被切成两个对象,一个编号为0,另一个编号为1,那么这两个对象的OID则为A0和A1。OID的好处是可以唯一标示每一个不同的对象,并且存储了对象与文件的从属关系。由于Ceph的所有数据都虚拟成了整齐划一的对象,所以在读写时效率都会比较高。
另外rados里使用了pool的概念来管理pg与对象;Pool是管理员自定义的命名空间,像其他的命名空间一样,用来隔离对象与PG。我们在调用API存储,即使用对象存储时,需要指定对象要存储进哪一个POOL中。除了隔离数据,我们也可以分别对不同的POOL设置不同的优化策略,比如副本数、数据清洗次数、数据块及对象大小等。
但是对象并不会直接存储进OSD中,因为对象的size很小,在一个大规模的集群中可能有几百到几千万个对象。如此多的对象只是遍历寻址速度都会很缓慢;而如果将对象直接通过某种固定映射的哈希算法映射到osd上,当这个osd损坏时,对象无法自动迁移到其他osd上面(因为映射函数不允许)。为了解决这些问题,Ceph引入了归置组的概念,即
PG
。
PG是一个逻辑概念,你会在Linux系统中可以直接看到对象,但是无法直接看到PG。它在数据寻址时类似于数据库中的索引:每个对象都会固定映射进一个PG中,所以当我们寻找一个对象时,只需要先找到对象所属的PG,然后遍历这个PG就可以了,无需遍历所有对象。而且在数据迁移时,也是以PG作为基本单位进行迁移,Ceph不会直接操作对象。
那对象是如何映射进PG的?首先使用静态hash函数对OID做hash取出特征码,用特征码与PG的数量取模,得到的序号就是
PGID
。由于这种设计,PG的数量多寡直接决定了数据分布的均匀性,所以合理设置的PG数量
可以很好地提升Ceph集群的性能并使数据均匀分布。最后PG会根据管理员设置的副本数量进行复制,然后通过CRUSH算法
存储到不同的OSD节点上(其实是把PG中的所有对象存储到节点上),第一个osd节点即为主节点,其余均为从节点。
OSD的读写流程:
Ceph的读写操作采用主从模型,客户端要读写数据时,只能向对象所对应的的
主OSD节点
发起请求。主节点在接受写请求时,会同步的向从OSD中写入数据。当所有的OSD节点都写入完成后,主节点才会向客户端报告写入完成的信息,因此保证了主从节点数据的高度一致性。而读取的时候,客户端也只会向主OSD节点发送读请求,并不会有类似数据库中读写分离的情况出现,这也是处于强一致性的考虑。由于所有写操作都要交给主OSD节点来处理,所以在数据量很大的时候,性能可能会比较慢,为了克服这个问题以及让Ceph能支持事务,每个OSD节点都包含一个journal文件,默认大小为5G,这个值是可以调整的,具体大小要依据OSD的总大小而定。Journal的作用类似于MySQL innodb引擎中的事务日志系统。当有突发的大量写入操作时,Ceph可以先把一些零散的,随机的IO请求保存到缓存中进行合并,然后在统一向内核发起IO请求。这样做效率会比较高,但是一旦OSD节点崩溃,缓存中的数据就会丢失,所以数据在还未写进硬盘时,都会记录到journal中,当OSD崩溃后重新启东市,会自动尝试从journal恢复因崩溃而丢失的缓存数据。因此journal的IO是非常密集的,而且由于一个数据IO两次
,很大程度上也损耗了硬件的IO性能,所以通常在生产环境中,建议使用ssd来单独存储journal文件以提高Ceph的读写性能。;
在Ceph中,每一个OSD进程都可以称作是一个OSD节点,也就是说,每台存储服务器可靠包含了众多的OSD节点,每个OSD节点监听不同的端口,类似于在同一台服务器上跑多个MySQL或Redis。每个OSD节点可以设置一个目录作为实际存储区域,也可以是一个分区、一整块硬盘。多个osd进程分别用于接收客户请求、传输数据、发送心跳、同步数据等操作。osd节点默认监听tcp的6800到6803端口,不够时依次后排。在生产环境中OSD最少可能都有上百个,所以每个OSD都有一个全局的编号,类似OSD0、OSD1、OSD2等等,序号根据OSD诞生的顺序排列,并且是全局唯一的。存储了相同PG的OSD节点除了向Mon节点发送心跳外,还会互相发送心跳信息以检测PG数据副本是否正常。
OS与ceph交互:
KVM虚拟机中直接使用ceph块设备:
CEPH对象存储与应用的结合:
四、部署和配置使用
- 网络规划:建议为Ceph配置3个独立的网络,一个管理网,一个用于客户端读写传输数据的业务网,另一个用于各OSD节点之间同步数据和发送心跳信息等的应用内网。这样做的好处是可以分担网卡的IO压力。
4.1、基础集群部署
cephadm bootstrap --mon-ip 192.168.1.100
ceph orch apply osd --all-available-devices
实验环境搭建:使用ceph-deploy或MicroCeph快速部署单节点集群。
核心概念速记:PG≈数据库分片,OSD≈磁盘管理器,Monitor≈集群仲裁者。
渐进式实践:从RBD挂载开始,逐步尝试CephFS多客户端挂载和S3桶策略配置。
4.2、高可用
Monitor节点数≥3且跨机架分布
设置osd_crush_update_on_start=false防止自动重平衡引发震荡
使用RBD Mirroring实现跨集群异步复制
4.3、ceph+kubernetes
4.4、OpenStack Ceph集群部署
#安装ceph部署工具cephadm
dnf install -y cephadm#安装ceph命令:
dnf install -y ceph-common#使用cephadm安装ceph,记录admin密码信息以登录ceph页面使用
cephadm bootstrap --mon-ip 192.168.10.0 --allow-overwrite --cluster-network 192.168.20.0/24#设置集群间免密登陆
ssh-keygen -t rsa
ssh-copy-id Ceph21
ssh-copy-id Ceph22
ssh-copy-id Ceph23
ssh-copy-id -f -i /etc/ceph/ceph.pub root@Ceph21
ssh-copy-id -f -i /etc/ceph/ceph.pub root@Ceph22
ssh-copy-id -f -i /etc/ceph/ceph.pub root@Ceph23#添加Ceph节点
ceph orch host add Ceph21 192.168.10.11 mon
ceph orch host add Ceph22 192.168.10.12 mon
ceph orch host add Ceph23 192.168.10.13#开启自动添加osd
ceph orch apply osd --all-available-devices#节点没添加成功的话,执行:
ceph orch daemon reconfig node-exporter. Ceph23#将ceph.conf配置文件复制到OpenStack部署机的目录下ssh kolladmin sudo tee /etc/kolla/config/ceph.conf </etc/ceph/ceph.conf #注意调整ceph.conf文件的格式,开头不能有tab和空格,在末尾追加三条配置auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx#创建glance、cinder的keyring认证文件ceph auth get-or-create client.glance mon 'profile rbd' osd 'profile rbd pool=images' mgr 'profile rbd pool=images' -o /etc/ceph/ceph.client.glance.keyringceph auth get-or-create client.cinder mon 'profile rbd' osd 'profile rbd pool=volumes, profile rbd pool=vms, profile rbd-read-only pool=images' mgr 'profile rbd pool=volumes, profile rbd pool=vms' -o /etc/ceph/ceph.client.cinder.keyringceph auth get-or-create client.cinder-backup mon 'profile rbd' osd 'profile rbd pool=backups' mgr 'profile rbd pool=backups' -o /etc/ceph/ceph.client.cinder-backup.keyring#将认证文件同步到部署机的对应目录下(部署机)
ceph auth get-or-create client.glance | ssh kolladmin sudo tee /etc/kolla/config/glance/ceph.client.glance.keyringceph auth get-or-create client.cinder | ssh kolladmin sudo tee /etc/kolla/config/cinder/cinder-volume/ceph.client.cinder.keyringceph auth get-or-create client.cinder | ssh kolladmin sudo tee /etc/kolla/config/nova/ceph.client.cinder.keyringceph auth get-or-create client.cinder | ssh kolladmin sudo tee /etc/kolla/config/cinder/cinder-backup/ceph.client.cinder.keyringceph auth get-or-create client.cinder-backup | ssh kolladmin sudo tee /etc/kolla/config/cinder/cinder-backup/ceph.client.cinder-backup.keyring
五、维护和优化
5.1、性能调优
[osd]
osd_op_num_threads_per_shard = 4 # 提升并发IO
bluestore_cache_size_hdd = 4GB # HDD缓存配置
5.2、维护
ceph osd getcrushmap -o crushmap.txt # 导出CRUSH规则
ceph osd reweight-by-utilization # 自动平衡数据分布
日常监控:通过ceph -s关注HEALTH_WARN,使用Prometheus+Grafana采集osd_utilization等指标。
故障处理:OSD宕机时优先检查网络分区,使用ceph osd lost标记需人工介入的场景。
扩容步骤:新节点安装相同系统→ceph orch host add new-node→自动部署OSD。
六、行业应用
金融行业:采用全闪存池+3副本,延迟敏感业务设置osd_client_op_priority=63。
医疗影像:使用EC(8+3)降低存储成本,结合CephFS快照实现数据版本控制。
云原生:通过Rook算子将Ceph融入K8s,动态供给PVC。
七、附录
1)openstack cinder
2)kolla-ansible
kolla-ansible是指用于自动化部署OpenStack的工具。它通过Ansible剧本和Kolla容器镜像来实现OpenStack服务的快速部署和管理。具体来说,kolla-ansible提供了一套自动化脚本,能够简化OpenStack的配置和安装过程,使用户能够更高效地搭建和维护OpenStack云环境。这个工具特别适合需要大规模部署和管理的场景,因为它利用容器技术来确保服务的稳定性和隔离性,同时通过Ansible的模块化设计,使得配置和扩展变得简单直观。
3)Calamari
Calamari是管理和监控Ceph集群的工具,并且提供REST api。
git clone https://github.com/ceph/calamari.git
git clone https://github.com/ceph/calamari-clients.git
git clone https://github.com/ceph/Diamond
#编译安装
yum install gcc gcc-c++ postgresql-libs python-virtualenv
cd calamari && ./build-rpm.sh
yum localinstall ../rpmbuild/RPMS/x86_64/calamari-server-<version>.rpm
yum install postgresql-server salt-master salt-minion supervisor
rpm -ivh ../rpmbuild/RPMS/x86_64/calamari-server-<version>.rpm #或
yum install npm ruby rubygems
npm install -g grunt grunt-cli bower grunt-contrib-compass
gem update --sytem && gem install compass
cd calamari-clients
make build-real
make dist #在上级目录生成calamari-client的压缩包
mkdir -p opt/calamari/webapp
for dir in manage admin login dashboard
>do
>mkdir -p ../opt/calamari/webapp/content/"$dir"
>cp -pr "$dir"/dist/* ../opt/calamari/webapp/content/"$dir"/
>done
rpmbuild -bb --define "_topdir /xxx/calamari-clients/../rpmbuild" --define "version 1.2" --define "revision rc2_49_g3e3686d" --define "tarname /xxx/rpmbuild/SOURCES/calamari-clients_product_1.2.tar.gz" SPECS/clients.spec
#安装calamari-clients
yum localinstall RPMS/x86_64/calamari-clients-1.2-rc2_49_g3e3686d.el6.x86_64.rpm
#初始化calamari
calamari-ctl initialize
cd ../Diamond
git checkout origin/calamari
make rpm #生成diamond安装包
#将diamond-<version>.noarch.rpm复制到所有的ceph服务器。使用yum localinstall安装,或者yum install python-configobj然后使用rpm -ivh安装;在所有的ceph服务器上安装salt-minion,创建/etc/salt/minion.d/calamari.conf,内容为:
master: {fqdn} #{fqdn}对应calamari服务器的域名。#启动salt-minion服务:
service salt-minion restart#在Calamari服务器上配置防火墙和saltstack认证 ;防火墙(允许ceph服务器访问salt-master和carbon)
# salt-master
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4505 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4506 -j ACCEPT
#carbon
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 2003 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 2004 -j ACCEPT#saltstack认证:当ceph服务器上的salt-minion服务启动之后,会自动向salt-master请求认证。
#在Calamari服务器上可以通过下面的命令查看salt-minion密钥的列表:
salt-key -L #刚刚启动salt-minion服务的ceph服务器会出现在Unaccepted Keys列表之后,要使得Calamari能够通过saltstack管理ceph服务器,需要对这些密钥进行认证:
salt-key -A #部署完成之后,可以访问calamari#FAQ
## SELinux导致500错误: 由于SELinux的限制,访问页面时会出现500错误,原因是httpd_t对于anon_inodefs_t没有写入权限,可以根据审计日志生成SELinux模块:
ausearch -m avc -c httpd -se httpd_t -o anon_inodefs_t | audit2allow -R -M httpd_anon_inodefs
semodule -i httpd_anon_inodefs.pp #生成的SELinux模块规则如下:require {type httpd_t;
}#============= httpd_t ==============
fs_rw_anon_inodefs_files(httpd_t)#2、打开Manage --> Logs页面无内容,查看日志,发现是访问http://xxx.xxx.xxx.xxx/api/v2/cluster/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/log发生503错误,还是SELinux的限制,通过ausearch配合audit2allow生成相应的模块,可以解决问题。
#生成的SELinux模块的规则如下:require {type var_run_t;type httpd_t;class sock_file { write getattr };
}#============= httpd_t ==============
allow httpd_t var_run_t:sock_file { write getattr };
files_read_var_files(httpd_t)
init_stream_connect_script(httpd_t)
## 3、打开graphite/dashboard/页面出现HTTP 500错误 ,日志中提示找不到graphite的模板,在calamari的bug列表中找到对应的说明——issue 8669
#解决方法是:
#在/opt/calamari/venv/lib/python2.6/site-packages下找到calamari_web的egg文件,解压缩之后手动修改calamari_web/settings.py,然后重新打包。重启apache之后可以访问graphite/dashboard/。