ceph分布式-》无需查表,算算就好-》算出的结果cluster map
cluster map
mon map
osd map
pg map
crush map
rados集群:
1、mon集群
负责:
1、监控全局状态-》
cluster map
1、osd daemon map
2、monitor map
3、pg map
4、crush map
2、负责管理集群内部状态(osd daemon挂掉,数据恢复等操作)
3、负责授权,
客端在访问时会先通过monitor验证操作权限
客户端需要根monitor要到cluster map
mon节点最少3个,不能挂掉超过半数
2、osd daemon集群
负责:
1、读写数据
2、数据拷贝与恢复
3、监控自己以及pg组员的状态
多对一 多对多
object-------hash算法-------》pg-------crush算法--------》osd daemon
保证数据可能地均匀
ceph适合存大文件,或者海量小文件
ps:pg与osd deamon的对应关系是在创建存储池就确定的,也就说客户端在读写数据前
这个关系就已经确定了,但是该关系不是固定死的,因为osd daemon有可能会宕掉
pg组内就会临时加入新的
一 ceph理论
pool存储池
创建存储池时,要设置两个东西
1、pg数目:决定了数据的均匀性
2、采用的crush规则:决定了ceph存取数据的检索过程
osd deamon上的pg数目
1、不能过小,过小则数据不均
2、不能过大,过大则一个osd daemon挂掉影响范围会很广,这会增大数据丢失的风险
osd daemon上的pg数目应该不大也不小,刚刚好,如何达到? 我们无法决定,是算法决定
但是我们可以决定的送给算法的参数,该参数指的就是在创建存储时指定存储池内所包含的
pg数目,只把该数目设置合理,算法自然会保证数据均匀
如何算出一个pool存储池内应该有多少个pg数?
osd daemon个数 < 5 128
5< osd daemon个数 < 10 512
10< osd daemon个数 < 50 4096
osd daemon个数 > 50 按照下述公式计算
准备条件:
1、你打算让一个osd daemon归属于多少个pg(官网建议100或200个)—》100个
2、osd daemon的总数—》9
3、当前存储池占总可用空间的百分比—》30G/3000G =>0.01
4、3
100 * 9 * 0.01 / 3 -> 3个
pg
unkown:表示pg不知道与哪些osd daemon对应
问题出在,指定的crush规则错误了
如果有三个osd物理节点,它们都放在同一个机柜里,故障域应该设置为host
最好是三个不同的机柜里,然后故障域设置为rack
hammer:
存储引擎filestore:osd daemon->xfs文件系统->磁盘
luminous
存储引擎bluestore:osd daemon->裸磁盘
通常的做法如下,为何要这么做???
osd daemon->lvm->裸磁盘
如果ceph集群即将用满了应该扩容,如何扩容?
osd daemon->裸磁盘下的扩容方式
新增一块磁盘,然后用osd daemon管理它
但问题是,新增一个osd daemon,ceph会在该
osd daemon上创建pg,说白了就是把该osd daemon
划分到一些pg组里
但凡一块osd daemon被分配到了pg里,会发生数据迁移
ps:线上环境,pg数能不动则不动
osd daemon->lvm->裸磁盘下的扩容方式
从vg组里划分更多的空间给lvm,不必新增osd daemon
总结:如果集群考虑到日后要扩容,那么推荐使用方案:osd daemon->lvm->裸磁盘
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
目录
一 ceph介绍
1.1、ceph是什么
1.2、什么是块存储、文件存储、对象存储
1.2.1 储备知识:块级与文件级
1.2.2 块存储、文件存储、对象存储
1.3 为何要用ceph
二 Ceph系统的层次结构
三 基础存储系统RADOS
3.1 引入
3.2 RADOS的子集群
3.3 rados的网络结构
四 Ceph集群的逻辑结构
4.1 核心逻辑概念总览
4.2 pool
4.2.1 ceph pool介绍
4.2.2 ceph的pool有四大属性
4.2.3 ceph的pool有两种类型
4.2.4 ceph的pool提供如下能力
4.3 pg
4.3.1 pg的概念
4.3.2 pg的特点
4.3.3 PG的创建过程
4.3.4 PG 数目的确定(非常非常非常重要!!!)
4.3.5 PG 的状态也是不断变化的
4.3.6 Ceph 以 PG 为单位进行数据清理 scrubbing
4.3.7 PG 设计带来的一些运维问题
4.4 Ceph结构和状态地图cluster map
4.4.1 cluster map介绍
4.4.2 Cluster map的内容
4.4.3 Monitor map:Mon集群的状态图
4.4.4 OSD Map:当前所有 Pool 的状态和所有 OSD 的状态
4.4.5 PG Map(Placement Group)
4.4.6 CRUSH Map:Controlled Replication under Scalable Hashing
4.5 crush算法与写入流程
五 高层应用接口详解
5.1 块设备存储接口
5.2 文件存储接口
5.3 对象存储接口
5.4 总结
六 块存储接口rbd的写入
6.1 块存储接口rbd的写入过程
6.2 储备知识:常见的write cache种类
6.3 RBD块存储缓存
6.4 Cache tiering (缓存分层)
6.5 RBD Cache 和 Cache Tiering 的区别
七 存储引擎
7.1 存储引擎介绍介绍
7.2 Bluefs中的DB和WAL分区
7.3 基于bluestore管理osd
7.4 基于filestore管理osd八 ceph版本
分布式存储Ceph
一 ceph介绍
1.1、ceph是什么
ceph一个统一的、分布式的存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。
“统一的”:意味着我们可以仅凭ceph这一套存储系统,同时提供对象存储、块存储和文件系统存储三种功能,这极大地简化了不同应用需求下的部署和运维工作。
“分布式”:ceph实现了真正的去中心化,理论上可以无限扩展集群系统的规模
致敬作者:
Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的后端存储。
1.2、什么是块存储、文件存储、对象存储
1.2.1 储备知识:块级与文件级
我们来了解一下块级与文件级,然后再介绍块存储与文件存储、对象存储,你就能很好地理解他们内部的原理
1、块级
磁盘的最小读写单位为扇区,1个或多个连续的扇区组成一个block块,也叫物理块。
可以通过下述命令查看block块大小
blockdev --getbsz /dev/sda1
2、文件级
文件是文件系统提供的功能,单个文件可能由于一个或多个逻辑块组成,且逻辑块之间是不连续分布。逻辑块大于或等于物理块整数倍,
物理块与文件系统之间的映射关系为:扇区→物理块→逻辑块→文件系统,详见下图
注意:这么多层转换,肯定是需要耗费效率的,如果操作的是对象,则可以直接省去这么多层映射关系,效率自然是高
1.2.2 块存储、文件存储、对象存储
(1)简述块存储、文件存储、对象存储
如果存储设备提供给你的是一块裸盘,需要你自己分区格式化制作文件系统,则称之为块存储
如果存储设备提供给你的是一个文件夹,你自己直接操作文件,则称之为文件存储
如果你只需要提供文件的元数据与真实数据,存储设备负责帮你生成文件,然后存到硬盘中,这就称之为对象存储,你操作的内容都称之为对象
(2)块存储、文件存储、对象存储的关系
块存储是最低级,最直接的,如果多个客户端共用一个块存储,客户端会把数据先缓存在本地,然后再写入块存储(详见6.3),这就会导致多个客户端数据不一致的问题,所以,通常一个块存储只给一个客户端用
为了让多个客户端共享数据、并保证一致,于是诞生了文件存储,例如nfs,客户端挂载的都是服务端的同一个文件夹,数据是完全一致的,但是随着客户端数量越来越多,nfs服务器检索文件信息的压力会越来越大,最后不堪重负,一旦挂掉,则影响整个集群的工作,所以nfs严重影响了集群的扩展
为了能够满足无限扩展的需求,诞生了对象存储,客户端无需操作文件,而是只需要提供文件相关的各部分信息即可,这些信息称之为一个个的对象,存储设备接收到对象后负责完成后续操作
(3)细说块存储、文件存储、对象存储
块存储:
1、客户端主要操作对象是磁盘,客户端可以自己格式化制作文件系统,
2、块存储设备中划分出的是一块裸磁盘空间映射给客户端主机使用
3、例如SCSI
以 SCSI 为例,主要接口有 Read/Write/Read Capacity/Inquiry 等等。FC,iSCSI,也是块存储协议。和文件存储相比,没有文件和目录树的概念,一般协议也不会定义磁盘的创建和删除操作。协议更注重传输控制。
文件存储:
1、客户端主要操作的是文件和文件夹,客户端无法格式化制作自己的文件系统,使用的是现成的文件系统。
2、文件存储中已经做好了文件系统然后共享给客户端主机使用
3、例如NFS
文件存储支持 POSIX 协议,以 NFS 为例,文件相关的接口包括:LOOKUP/ACCESS/READ/WRITE/CREATE/REMOVE/RENAME 等等,文件夹相关的接口包括:MKDIR/RMDIR/READDIR 等等。同时也会有 FSSTAT/FSINFO 等接口用于提供文件系统级别的信息。POSIX,SAMBA 等也是文件存储协议。协议更注重接口的灵活,以及访问权限控制。
对象存储:
1、客户端主要操作对象是对象(Object)
2、对象存储使用一个统一的底层存储系统,把文件和底层介质的组织结构都管理好,然后给每个文件一个唯一的标识,客户端需要访问某个文件,直接提供文件的标识就可以了。此时存储系统可以用更高效的数据组织方式来管理这些标识以及其对应的存储介质上的块。
当然,对于不同的软件系统来说,一次访问需要获取的不一定是单个我们传统意义上的文件,根据不同的需要可能只是一个/组值,某个文件的一部分,也可能是多个文件的组合,甚至是某个块设备,统称为对象。这就是对象存储。
3、例如S3
以 S3 为例,主要接口有 PUT/GET/DELETE 等。和文件和对象存储相比,没有随机读写的接口。和文件存储相比,没有目录树的概念。协议更注重简洁。
总结 块存储: 是和主机打交道的, 如插一块硬盘 文件存储: NAS, 网络存储, 用于多主机共享数据 对象存储: 跟你自己开发的应用程序打交道, 如网盘 它们的层级是越来越高的
关于ceph的块存储、文件存储、对象存储
Block(块):支持精简配置、快照、克隆。
File(文件系统):Posix接口,支持快照。
Object(对象):有原生的API,而且也兼容Swift和S3的API。
1.3 为何要用ceph
Ceph本身确实具有较为突出的优势,ceph追求用最廉价的设备做最牛逼的存储。
其先进的核心设计思想,概括为八个字—“无需查表,算算就好”。
详细地讲,可以总结为以下四点
1、高性能 a. 摒弃了传统的集中式存储元数据寻址的方案,采用CRUSH算法,数据分布均衡,并行度高。 b.考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨机房、机架感知等。 c. 能够支持上千个存储节点的规模,支持TB到PB级的数据。
2、高可用性 a. 副本数可以灵活控制。 b. 支持故障域分隔,数据强一致性。 c. 多种故障场景自动进行修复自愈。 d. 没有单点故障,自动管理。 高可扩展性
3、去中心化。 b. 扩展灵活。 c. 随着节点增加而线性增长。
4、特性丰富 a. 支持三种存储接口:块存储、文件存储、对象存储。 b. 支持自定义接口,支持多种语言驱动。
二 Ceph系统的层次结构
自下向上,可以将Ceph系统分为四个层次:
基础存储系统RADOS(Reliable, Autonomic, Distributed Object Store,即可靠的、自动化的、分布式的对象存储)
基础库LIBRADOS
高层应用接口:包括了三个部分
1、对象存储接口:RADOS GW(RADOS Gateway)
2、块存储接口: RBD(Reliable Block Device)
3、文件存储接口:Ceph FS(Ceph File System)
应用层:基于高层接口或者基础库librados开发出来的各种APP,或者主机、VM等诸多客户端
提示
rados集群是ceph的服务端,依据高层接口封装的应用则是客户端。
三 基础存储系统RADOS
3.1 引入
为了更好地理解RADOS的组成,我们从单块盘说起
单块硬盘的指标
1、IO速度
2、容量
单块硬盘的限制,单块硬盘就好像是一个矿泉水瓶
1、IO速度受限与瓶口,容量受限与瓶体
2、把长江的水倒入瓶子,首先瓶口太窄io太慢,其次容量不够空间太小装不下长江水
解决方案:
纵向扩展—>不靠谱
横向扩展—>
n盘做raid,相当于一块大盘,在本机使用,但是单台机器可插硬盘的总数也是有限的,仍然会受到
限制
如果能通过网络通信,那么就可以打破单台机器的限制:一堆硬盘+软件控制起来
做成硬盘的集群,相当于一个大的网络raid,这就是分布式存储,比如ceph
3.2 RADOS的子集群
Ceph的底层是Rados,而RADOS由多个子集群构成
1、若干个数据盘:一个Ceph 存储节点上可以有一个或者多个数据盘,在老版本的ceph比如hammer中每个数据盘上部署有特定的文件系统,比如 xfs,ext4 或者 btrfs,但是在最新的LTS版luminous中,数据盘是一块裸盘即可,无需制作文件系统(数据盘也可以由一块机械盘+一块固态盘的两个分部共同过程,详见第七章)。可以是一个分区当一个disk,可以是一个raid当一个disk,也可以是一整块盘当一个disk,但依据egon老师在公司中的实际架构经验看还是一整块盘当一个disk效率高更稳定。
btrfs 是个很新的文件系统(Oracel 在2014年8月发布第一个稳定版),它将会支持许多非常高大上的功能,比如 透明压缩( transparent compression)、可写的COW 快照(writable copy-on-write snapshots)、去重(deduplication )和加密(encryption )。因此,Ceph 建议用户在非关键应用上使用该文件系统。
xfs 和 btrfs 相比较ext3/4而言,在高伸缩性数据存储方面具有优势。
2、OSD (Object Storage Device)集群:一个做好文件系统的disk由一个OSD Daemon管理,OSD Daemon负责
1、负责控制数据盘上的文件读写操作,与client通信完成各种数据对象操作等等。
2、负责数据的拷贝和恢复
3、每个 OSD 守护进程监视它自己的状态,以及别的 OSD 的状态,并且报告给 Monitor
在一个服务器上,一个数据盘对应一个 OSD Daemon,而一个服务器上可以有多块数据盘,所以仅一台服务器就会运行多个OSD Daemon,该服务称之为OSD节点,一个CEPH集群中有n个OSD节点,综合算下来,OSD集群由一定数目的(从几十个到几万个) OSD Daemon 组成。
3、MON(Montior)集群:MON 集群由少量的、数目为奇数个的 Monitor 守护进程(Daemon)组成,负责ceph所有集群中所有OSD状态的发现与记录。理论上来讲,一个 MON 就可以完成这个任务,之所以需要一个多个守护进程组成的集群的原因是保证高可靠性。每个 Ceph node 上最多只能有一个 Monitor Daemon。
4、要使用 CephFS,还需要 MDS 集群,用于保存 CephFS 的元数据
5、要使用对象存储接口,还需要 RADOS Gateway, 它对外提供REST接口,兼容S3和Swift的API。
问题1:monitor集群如何实现对ceph所有集群的状态检测和维护的
OSD集群和monitor集群之间相互传输节点状态信息,共同得出系统的总体工作状态,并形成一个记录ceph系统全局状态数据结构,即所谓的cluster map。
cluster map与RADOS提供的特定算法相配合,便实现了Ceph“无需查表,算算就好”的核心机制以及若干优秀特性,保证了数据的安全性
Cluster map包括,各部分意识稍后我会详细讲解 1、mon map 2、osd map 3、pg map 4、crush map
问题2:monitor为何为奇数个—>paxos算法
需知:集群状态是不断变化的,所以cluster map也是不断变化的
为了标记最新的cluster map,monitor持有的每个cluster map都有一个视图版本号(Epoch),并且Epoch是单调递增的、伴随着cluster map的更新而更新,随着集群的运行,一些monitor节点的epoch可能会出现周期性落后的情况,那如何保持集群中所有monitor节点持有的cluster map是一致的呢,这就用到了paxos分布式强一致性算法(详解:https://www.cnblogs.com/linhaifeng/articles/14685438.html)。
Paxos算法下所有monitor分为三种角色,通常应为奇数个
1、leader:mon集群通过paxos算法选取出的主节点,主节点拥有最新版本号
2、provider:正常的mon节点会找leader同步最新的版本号
3、requester:请求者,down掉的mon节点,准备恢复中。(找leader同步信息,但是leader会交给provider处理)
简单地讲就一句话:mon集群会依据paxos算法互相通信发现有大的epoch存在,便会更新自己的视图版本
问题3:monitor与OSD daemon是否可以在同一个节点上
可以,但不好,最好还是分布式,杜绝集中式
并且需要再次强调一点:一个节点只能有一个monitor进程,但可以有多个OSD daemon
问题4:monitor节点的个数应该为多少?如果有3个,挂掉2个,集群还能工作吗?
一般来说,在实际运行中,ceph monitor的个数是2n+1(n>=0)个,在线上至少3个,只要正常的节点数>=n+1,ceph的paxos算法能保证系统的正常运行。所以,对于3个节点,同时只能挂掉一个。一般来说,同时挂掉2个节点的概率比较小,但是万一挂掉2个呢?
如果ceph的monitor节点超过半数挂掉,paxos算法就无法正常进行仲裁(quorum),此时,ceph集群会阻塞对集群的操作,直到超过半数的monitor节点恢复。
3.3 rados的网络结构
rados作为ceph最核心的部分,是整个ceph的大后端,应该如何架设呢???
首先:Ceph 使用以太网连接内部各存储节点以及连接 client 和rados集群。
然后:Ceph 推荐使用两个网络,这么做,主要是从性能(OSD 节点之间会有大量的数据拷贝操作)和安全性(两网分离)考虑。
前端(北向)网络( a public (front-side) network)连接客户端和集群
后端/东西向网络 (a cluster (back-side) network)来连接 Ceph 各存储节点
你可以在 Ceph 配置文件的 [global] 部分配置两个网络:
public network = {public-network/netmask}
cluster network = {cluster-network/netmask}
提示
与客户通信的数据流为纵向,所以称之为北向网络,或称南北网络。
集群内通信的数据流为横向,所以称之为东西网络。
南北的含义是数据可以往外走,客户端是集群外的节点,其余为集群内节点
东西的含义是数据流是横向的,数据流会在集群内节点通信,与外界无关
四 Ceph集群的逻辑结构
4.1 核心逻辑概念总览
rados构建完毕后,为客户端提供存储服务,需要
1、创建存储池pool,存储池中包含100个pg
ceph osd pool create rbdtest 100
2、设置pool池的副本数,即一个pg包含多少个osd daemon,往某一个pg中存的数据会在其包含的osd中都保存一份
ceph osd pool set rbdtest size 3
3、在存储池rdbtest中创建一个镜像给客户端用,一个image用的是存储池中的pg(并非指定的pg,而是只要是存在与pool中的pg都可能会用到),相当于一个配额
rbd create -p rdbtest --size 10000 egon # image名为egon,大小为10000M
在客户端文件会被以4M为单位切成3块,每块对应一个object
object 多对一 pg
pg多对多osd daemon
一个pool中有多个pg
从pool中划分出image给用户用,image只是一个配额
写入数据流程大致如下:
librbd crush算法
file—————————> object—————-—> pool中划分出来的image(一堆pg)———————------> osd daemon
ceph存储小文件效率不高
底层osd daemon越多,存大文件效率越高
ceph是伪数据平衡,如果只有一个PG,一个PG里副本数为3,永远只有一块盘被用到
ceph的逻辑结构与lvm有点像
pv -> osd
vg -> pool
lv -> image
4.2 pool
4.2.1 ceph pool介绍
在rados集群构建完毕后、使用ceph时,需要用到诸多逻辑概念/结构,我们才能理解一个文件到底是如何写入到ceph中。ceph集群的逻辑结构主要由Pool与PG(Placement Group)来定义,本节我们先来介绍一下Pool。
对比LVM逻辑卷
pv:把一系列的盘都做好标记,由LVM管理起来
vg:是把一系列的pv给归类到一起,相当于一块大磁盘
lv:相当于从vg这个”大磁盘“中分出的一个”分区“
ceph的逻辑结构与lvm有点像,其对应关系如下
LVM Ceph
4.2.2 ceph的pool有四大属性
1、所有性和访问权限
2、对象副本数目,默认pool池中的一个pg只包含两个osd daemon,即一份数据交给pg后会存下2个副本,生产环境推荐设置为3个副本
3、PG 数目,PG是pool的存储单位,pool的存储空间就由pg组成
4、CRUSH 规则集合
4.2.3 ceph的pool有两种类型
Replicated pool(默认):
拷贝型 pool,通过生成对象的多份拷贝
默认的存储池类型,把每个存入的对象(Object)存储为多个副本,其中分为主副本和从副本,从副本相当于备份副本,从而确保在部分 OSD 丢失的情况下数据不丢失。这种类型的 pool 需要更多的裸存储空间,但是它支持所有的 pool 操作。
如果客户端在上传对象的时候不指定副本数,默认为3个副本。在开始存数据之前会计算出该对象存储的主副本与从副本的位置,首先会将数据存入到主副本,然后主副本再将数据分别同步到从副本。主副本与从副本同步完毕后会通知主副本,这时候主副本再响应客户端,并表示数据上传成功。所以如果客户端收到存储成功的请求后,说明数据已经完成了所有副本的存储。
Erasure-coded pool:
此类型会将数据存储为K+M,其中K数据块数量。每个对象存储到Ceph集群的时候会分成多个数据块分开进行存储。而M为为编码块,也代表最多容忍可坏的数据块数量。类似于磁盘阵列RAID5,在最大化利用空间的同时,还能保证数据丢失可恢复性,相比副本池更节约磁盘的空间。 因为副本池很浪费存储空间,如果Ceph集群总容量为100T,如果使用副本池,那么实际可用空间按3个副本算,那么只有30T出头。而使用纠删码池就可以更大化的利用空间,但纠删码池更浪费计算资源。 如存储一个100M的资源,如果使用副本池,按3副本计算实际上要使用300M的空间。而使用纠删码池,如果将100M资源分为25块,如果将M指定为2,那么总共只需要108M空间即可,计算公式为100+100/25*2。 注意:如果存储RBD镜像,那么不支持纠删码池。关于此类型存储池使用不多,不做过多介绍。
4.2.4 ceph的pool提供如下能力
Resilience(弹力):即在确保数据不丢失的情况允许一定的 OSD 失败,这个数目取决于对象的拷贝(copy/replica)份数或称副本数。对拷贝型 pool 来说,Ceph 中默认的拷贝份数是2,这意味着除了对象自身外,它还有一个另外的备份。你可以自己决定一个 Pool 中的对象的拷贝份数,生产环境推荐为3,副本数越多数据越安全、真正可以空间越少
PG(Placement Groups,放置组):ceph用pg把存放相同副本的osd daemon归为一组。
客户端的文件会被切成多个object然后交给ceph存储,ceph中真正负责存储的是osd daemon守护进程,在存储时,ceph需要找到n个osd daemon、归类好哪些osd daemon存放的是同一个副本、然后把object交给它们,为了降低查找与归类成本,与是引入了pg的概念,将存放相同副本的osd daemon归为一个pg组
CRUSH Rules (CRUSH 规则):数据映射的策略。系统默认提供 “replicated_ruleset"。用户可以自定义策略来灵活地设置 object 存放的区域。比如可以指定 pool1中所有objecst放置在机架1上,所有objects的第1个副本放置在机架1上的服务器A上,第2个副本分布在机架1上的服务器B上。 pool2中所有的object分布在机架2、3、4上,所有Object的第1个副本分布在机架2的服务器上,第2个副本分布在机架3的服 器上,第3个副本分布在机架4的服务器上。后续egon会详细介绍crush rules。
Snapshots(快照):你可以对 pool 做快照。
Set Ownership:设置 pool 的 owner 的用户 ID。
Ceph 集群创建后,默认创建了 data,metadata 和 rbd 三个存储池。
4.3 pg
4.3.1 pg的概念
PG英文全称 Placement Group,中文称之为归置组。
PG的作用:PG相当于一个虚拟组件,出于集群伸缩,性能方面的考虑。Ceph将每个存储池分为多个PG,如果存储池为副本池类型,并会给该存储池每个PG分配一个主OSD和多个从OSD,当数据量大的时候PG将均衡的分布行不通集群中的每个OSD上面。
PG 概念非常复杂,主要有如下几点:
PG 也是对象的逻辑集合。pool中的副本数设置为3,则一个pg中包含3个osd daemon,同一个PG 接收到的所有object在这3个osd daemon上被复制。
Epoch:PG map 的版本号,它是一个单调递增的序列。
Peering:见下文的状态描述。
Acting set:支持一个 PG 的所有 osd daemon 的有序列表,其中第一个 OSD 是主OSD,其余为次。acting set 是 CRUSH 算法分配的,但是不一定已经生效了。
Up set:某一个 PG map 历史版本的 acting set。在大多数情况下,acting set 和 up set 是一致的,除非出现了 pg_temp。
Current Interval or Past Interval:若干个连续的版本号,这些版本中 acting 和 up set 保持不变。
PG temp:
一个PG组里有三个组员/OSD daemon,三个组员第一个是组长,组长负责对外提供服务,组员负责备份,一旦组长挂掉后,相当于公司中一个部门的项目经理挂了,公司会招聘一个新的项目经理,但新的项目经理刚来的时候还什么都不知道(即新加进来的osd daemon是没有任何组内数据的),此时公司会让某个组员先临时接替一下组长的职务、对外提供服务,一旦新来的组长了解了业务(即新加进来的osd daemon已经同步好数据了),那么就可以让新组长出山了,详解如下
在Ceph 正在往主 OSD 回填数据时,这个主OSD是不能提供数据服务的,这时候,它会向 MON 申请一个临时的 acting set,这就是 PG temp。举个例子,现在 acting set 是[0,1,2],出现了一点事情后,它变为 [3,1,2],此时 osd.3 还是空的因此它无法提供数据服务因此它还需要等待backfilling过程结束,因此,它会向 MON 申请一个临时的 set 比如 [1,2,3],此时将由 osd.1 提供数据服务。回填过程结束后,该临时 set 会被丢弃,重新由 osd.3 提供服务。
主 (primary) OSD:在 acting set 中的首个 OSD,负责接收客户端写入数据;默认情况下,提供数据读服务,但是该行为可以被修改。它还负责 peering 过程,以及在需要的时候申请 PG temp。
次 (replica)OSD:在 acting set 中的除了第一个以外的其余 OSD。
流浪 (stray) OSD:已经不是 acting set 中了,但是还没有被告知去删除数据 的 OSD。
PG 的 acting set 是由 CRUSH 算法根据 CRUSH Rules 动态地计算得出的。
4.3.2 pg的特点
一、基本特点
1)Ceph 引入 PG 的目的主要是为了减少直接将对象object映射到 OSD 的复杂度,即PG 确定了 pool 中的对象object和 OSD 之间的映射关系,一个 object 只会存在于一个 PG 中,但是多个object可以在同一个 PG 内。PG-Object-OSD 的关系如下图所示:
object与PG是多对一的关系
PG与OSD daemon是多对多的关系
OSD daemon与disk是一对一的关系
2)一个OSD上的PG则可达到数百个。事实上,PG数量的设置牵扯到数据分布的均匀性问题。PG 和 OSD 之间的映射关系由 CRUSH 决定,而它做决定的依据是 CRUSH 规则(rules)。CRUSH 将所有的存储设备(OSD)组织成一个分层结构,该结构能区分故障域(failure domain),该结构中每个节点都是一个 CRUSH bucket。详细情况后续介绍。
3)对象的副本数目,也就是被拷贝的次数,是在创建 Pool 时指定的。该分数决定了每个 PG 会在几个 OSD 上保存对象。如果一个拷贝型 Pool 的size(拷贝份数)为 2,它会包含指定数目的 PG,每个 PG 使用两个 OSD,其中,第一个为主 OSD (primary),其它的为从 OSD (secondary)。不同的 PG 可能会共享一个 OSD。
4)PG 也是Ceph 集群做清理(scrubbing)的基本单位,也就是说数据清理是一个一个PG来做的。
二、PG 和 OSD 的关系是动态的
librbd crush算法
file—————————> object—————-—> pool中划分出来的image(一堆pg)———————------> osd daemon
1)一开始在 PG 被创建的时候,MON 根据 CRUSH 算法计算出 PG 所在的 OSD。这是它们之间的初始关系。
2)Ceph 集群中 OSD 的状态是不断变化的,它会在如下状态之间做切换:
up:守护进程运行中,能够提供IO服务;
down:守护进程不在运行,无法提供IO服务;
in:包含数据;
out:不包含数据
3)部分 PG 和 OSD 的关系会随着 OSD 状态的变化而发生变化。
当新的 OSD 被加入集群后,已有OSD上部分PG将可能被挪到新OSD上;此时PG 和 OSD 的关系会发生改变。
当已有的某 OSD down 了并变为 out 后,其上的 PG 会被挪到其它已有的 OSD 上。
但是大部分的 PG 和 OSD 的关系将会保持不变,在状态变化时,Ceph 尽可能只挪动最少的数据。
4)客户端根据 Cluster map 以及 CRUSH Ruleset 使用 CRUSH 算法查找出某个 PG 所在的 OSD 列表。
4.3.3 PG的创建过程
Pool 的 PG 数目是创建 pool 时候指定的,Ceph 官方有推荐的计算方法。其值与 OSD 的总数的关系密切。当Ceph 集群扩展 OSD 增多时,根据需要,可以增加 pool 的 PG 数目。
1)MON 节点上有PGMonitotor,它发现有 pool 被创建后,判断该 pool 是否有 PG。如果有PG,则逐一判断这些 PG 是否已经存在,如果不存在,则开始下面的创建 PG 的过程。
2)创建过程的开始,设置PG 状态为 Creating,并将它加入待创建PG队列 creating_pgs,等待被处理。
3)开始处理后,使用 CRUSH 算法根据当前的 OSD map 找出来 up/acting set,确定哪些osd属于哪些pg,然后加入队列 creating_pgs_by_osd,等待被处理
4)队列处理函数将该 OSD 上需要创建的 PG 合并,生成消息MOSDPGCreate,通过消息通道发给 OSD。
5)OSD 收到消息字为 MSG_OSD_PG_CREATE 的消息,得到消息中待创建的 PG 信息,判断类型,并获取该PG的其它OSD,加入队列 creating_pgs (似乎是由主 OSD 负责发起创建次 OSD 上的PG),再创建具体的 PG。
6)PG 被创建出来以后,开始 Peering 过程。
4.3.4 PG 数目的确定(非常非常非常重要!!!)
创建 pool 时需要确定其 PG 的数目,在 pool 被创建后也可以调整该数字,但是增加池中的PG数是影响ceph集群的重大事件之一,生成环境中应该避免这么做,因为pool中pg的数目会影响到
1)数据的均匀分布性:CRUSH 算法会伪随机地保证 PG 被选中来存放客户端的数据,它还会尽可能地保证所有的 PG 均匀分布在所有的 OSD 上,即ceph是伪数据平衡,如果只有一个PG,一个PG里副本数为3,永远只有一块盘被用到
比方说,有10个OSD,但是只有一个 size 为 3 的 pool、它只有一个 PG,那么10个 OSD 中将只有三个 OSD 被用到。 CURSH 算法在计算的时候并不会考虑到OSD上已有数据的大小。如果10个OSD上存在1000个PG内,每个 OSD 上大概有400M 数据。再加进来一个400M的对象(假设它不会被分割),那么有三块 OSD 上将有 400M + 400M = 800 M 的数据,而其它七块 OSD 上只有 400M 数据。
2)资源消耗:PG 作为一个逻辑实体,它需要消耗一定的资源,包括内存,CPU 和带宽。太多 PG 的话,则占用资源会过多。
3)清理时间:Ceph 的清理工作是以 PG 为单位进行的。如果一个 PG 内的数据太多,则其清理时间会很长。
4)数据的持久性:Pool中的PG个数应该随着osd daemon的增多而增多,这样crush算法可以将pg与osd的对应关系尽量均匀一些、降低同一个osd属于很多很多个pg的几率,如果一个osd真的属于很多很多pg,这有可能会很糟糕
假设我们的pool副本size为3,则表示每个 PG 会将数据存放在 3 个 OSD 上,
一旦某个osd daemon挂掉,因为一个osd daemon很多很多pg,则此时会出现很多pg只有两个2副本的情况,数据开始进行recovery 恢复,如recovery结束前,因为数据量过大,又有一个osd daemon(也属于很多很多pg)扛不住压力也崩溃掉了,那么将会有一部分pg只有一个副本,recovery 过程继续,情况继续恶化,如果再有第三个osd daemon挂掉,那么就可能会出现部分数据丢失。
可见,每个 OSD 上的PG数目不宜过大,否则,会降低数据的持久性,可以肯定的一点是osd数越多,存储池中包含的pg的数目也应对应增加,这样每个osd上的pg数才会尽量均匀、不会过大。那如何确定一个Pool中有多少 PG?Ceph不会自己计算,而是给出了一些参考原则,让Ceph用户自己计算,
少于 5 个 OSD daemon, 建议将pool中的pg数设为 128
5 到 10 个 OSD daemon,建议将pool中的pg数设为 512
10 到 50 个 OSD daemon,建议将pool中的pg数设为 4096
50 个 OSD daemon 以上,就需要有更多的权衡来确定 PG 数目,你可以使用 pgcalc 工具https://ceph.com/pgcalc/,详解如下
https://old.ceph.com/pgcalc/
我们在创建存储池时
ceph osd pool create 存储池名 pg_num
如何设置存储中包含的pg_num,才能让crush算法尽可能保证pg在osd上分布均匀呢,官网的公式如下
Target PGs per OSD:crush为每个osd分配的pg数
osd# :通常为osd daemon的总数
%data:该存储池的空间占ceph集群整体存储空间的百分比
size:存储池中的副本数
提示:官方建议每个osd上的pg数(即Target PGs per OSD)应该为
如果在可预见的将来,集群中的osd数目不会增加,那么建议每个osd上分配的pg数为100个
如果在可预见的将来,集群中的osd数目会增加(如增加一倍),那么建议每个osd上分配的pg数为200个
按照上述公式得出结果后,还需要作出如下判断才能最终确定待创建的存储池中的pg数目
(1) 如果得出的值小于:osd总数 /size,那么值应该采用:osd 总数/size,这是为了通过为每个池的每个OSD分配至少一个主要或次要PG来确保均匀的负载/数据分布。
(2) 输出的值应该四舍五入到最接近的2次方,这利于crush算法的效率提升
(3) 如果最接近的2次方(比如为23)比得到原始值低25%以上,则使用下一个更高的2次方(应该取24)。
举例:我们ceph集群的总空间为100T,我们先分出一个1T的存储池
那么我们的存储池占总空间的百分比为0.01
假设我们总共100个osd
假设未来很长一段时间内我们的osd也不会再增加了,那么target PGS per OSD应该为100
加上存储池中的副本数为3
1001000.01 / 3 得到值 33.333333333333336
osd总数 /size 即 100 / 3 得33.333333333333336
与步骤二算出的值比较,取一个大值
最终选定33.333333333333336
33.333333333333336取最接近的2次方,2^5结果为32
于是我们创建
ceph osd pool create egon_test 32
官网举例,https://ceph.com/pgcalc/,在官网中往表格中输入对应内容即可得出pg个数,很方便
官网例中:创建了一堆存储池,每个存储池占用总空间的一定比例,即%Data,该值带入公式时,因为是百分比,所以需要除以100后才可以,所有存储池的%Data加在一起为100%
4.3.5 PG 的状态也是不断变化的
其主要状态包括:
1)Creating 创建中:PG 正在被创建。
2)Peering 对等互联(处于该状态的PG不能响应IO请求)
Peering就是一个 PG 的所有 OSD 都需要互相通信来就PG 的对象及其元数据的状态达成一致的过程。
Peering的过程其实就是pg状态从初始状态然后到active+clean的变化过程。
一个 OSD 启动之后,上面的pg开始工作,状态为initial,这时进行比对所有osd上的pglog和pg_info,对pg的所有信息进行同步,并选举primary osd和replica osd,peering过程结束,然后把peering的结果交给recovering,由recovering过程进行数据的恢复工作。
3)Active 活动的:Peering 过程完成后,PG 的状态就是 active 的。此状态下,在主次OSD 上的PG 数据都是可用的,即PG内主OSD和从OSD都处于就绪状态,可正常提供客户端请求。
4)Clean 洁净的:此状态下,主次 OSD 都已经被 peered 了、都处于就绪状态,每个副本都就绪了。
5)Down:PG 掉线了,因为存放其某些关键数据(比如 pglog 和 pginfo,它们也是保存在OSD上)的副本 down 了。
6)Degraded 降级的:某个 OSD daemon被发现停止服务 (down)了后,Ceph MON 将该 OSD 上的所有 PG 的状态设置为 degraded,即PG包含的osd数目不够,此时该 OSD 的 peer OSD 会继续提供数据服务。这时会有两种结果:
一是它会重新起来(比如重启机器时),需要再经过 peering 过程再到clean 状态,而且 Ceph 会发起 recovery (恢复)过程,使该 OSD 上过期的数据被恢复到最新状态;
二是 OSD 的 down 状态持续 300 秒后其状态被设置为 out踢出集群,Ceph 会启动自恢复操作,选择其它的 OSD 加入 acting set,并启动回填(backfilling)数据到新 OSD 的过程,使 PG 副本数恢复到规定的数目。 有时候某个OSD不可用,崩溃的时候也会处此此状态。详情可以参考 PG 的数据恢复过程。
7)Remapped 重映射:每当 PG 的 acting set 改变后,就会发生从旧 acting set 到新 acting set 的数据迁移。此过程结束前,旧 acting set 中的主 OSD 将继续提供服务。一旦该过程结束,Ceph 将使用新 acting set 中的主 OSD 来提供服务。
8)Stale 过期的:每个OSD daemon每隔 0.5 秒向 MON 报告其状态。如果因为任何原因,主 OSD 报告状态失败了,或者其它OSD已经报告其主 OSD down 了,Ceph MON 将会将它们的 PG 标记为 stale 状态。
9) Undersized:当PG中的副本数少于其存储池指定的个数的时候,就为此状态。
10)Scrubbing:各OSD还会周期性的检查其持有的数据对象的完性,以确保主和从的数据一致,这时候状态就为此状态。 另外PG偶尔还需要查检确保一个对象的OSD上能按位匹配,这时候状态为scrubbing+deep。
11)Recovering 恢复中(增量恢复):一个 OSD down 后,其上面的 PG 的内容的版本会比其它OSD上的 PG 副本的版本落后。在它重启之后(比如重启机器时),Ceph 会启动 recovery 过程来使其数据得到更新。
12)Backfilling 回填中(全量恢复):一个新 OSD 加入集群后,Ceph 会尝试级将部分其它 OSD 上的 PG 挪到该新 OSD 上,此过程被称为回填。与 recovery 相比,回填(backfill)是在零数据的情况下做全量拷贝,而恢复(recovery)是在已有数据的基础上做增量恢复。
13)PG 的所有的状态是一个类似树形的结构,每个状态可能存在子状态,子状态还可能存在子状态,如下图所示:
[root@ceph-mon ~]# ceph -s # 注意,只有当所有的 PG 都是 active + clean 状态时,集群的状态才是 HEALTH_OK 的。
cluster c5476875-2a04-41b7-a4e8-421133c69ac8
health HEALTH_WARN
28 pgs backfill #回填,有新的 OSD 被加入了?
79 pgs degraded #降级,有 OSD down 了?
10 pgs recovering #恢复中
42 pgs recovery_wait #等待恢复
80 pgs stuck unclean #有 80个 PG 一直处于 unclean 状态
27 pgs undersized #GP 的副本数小于pool size
recovery 4814/27835 objects degraded (17.295%)
recovery 2047/27835 objects misplaced (7.354%)
4.3.6 Ceph 以 PG 为单位进行数据清理 scrubbing
Ceph 以 PG 为单位进行数据清理 scrubbing,以保证数据的完整性,它的作用类似于文件系统的 fsck 工具。
1)Ceph 的 OSD daemon定期启动 scrub 线程来扫描部分对象,通过与其他osd daemon的副本比对来发现是否一致,如果存在不一致,抛出异常提示用户手动解决。管理员也可以手工发起。
2)在与其他osd daemon的副本进行比较时,有两种比较方式:
light scrubbing:比较对象的size和属性,一般每天进行
deep scrubbing:读取对象的数据,比较检验码,一般每周进行。
3)OSD daemon定期启动 的scrub 线程会以 PG 为单位,对于每一个PG,scrub 线程会分析该 PG 下所有的对象, 产生一个类似于元数据信息摘要的数据结构,如对象大小,属性等,叫scrubmap, 比较主与副scrubmap,来保证是不是有object 丢失或者不匹配。
4)Scrub 的工作方式分成两种, “classic Scrub” vs “chunky Scrub”。
Scrub 流程需要提取对象的校验信息然后跟其他副本的校验信息对比,这期间被校验对象的数据是不能被修改的,所以 write 请求会被 block. 由于 PG 可能包含成千上万 objects,
chunky Scrub 每一次的比较只取其中一部分 objects 来比较,这样只 block一小部分object的write请求。这是在ceph的Bobtail(v0.56 Jan 1 2013)引入的feature,称为chunky scrub。
Classic scrub 没有引入chunk, 会block所有的write请求。
5)该机制对保证数据的完整性非常重要,但是也会消耗大量的集群资源,block 住一部分对象的写入操作,降低集群的性能,特别是当一个OSD服务器上多个OSD同时进行深度清理的时候。这篇文章 Ceph Deep-Scrubbing Impact Study 说当有三个深度清理线程发生时,性能有明显的下降。
4.3.7 PG 设计带来的一些运维问题
引用 https://www.cnblogs.com/linhaifeng/articles/14690274.html
(1)扩容粒度
Ceph在实践中,扩容受“容错域”制约,一次只能扩一个“容错域”。容错域就是:副本隔离级别,即同一个replica的数据,放在不同的磁盘/机器/Rack/机房。默认是机器,通常设为机架。
Ceph扩容需要对PGs进行调整。正因为这个调整,导致Ceph受“容错域”制约。
例如:有一个PG,是3副本,Ceph集群有一个配置是PG要向外提供正常服务,至少有2个完整的副本。而当这个数据pool的容错域是host时,同时扩容2台机器,一些PG就有可能把3副本中的2个都映射到2台新机器上去。而这2个副本都是新副本,都没有完整的最新数据。剩下的一个副本,无法满足老机器至少有完整的2副本的要求,也就不能提供正常读写服务了。这就会导致这个PG里的所有对象,停止对外服务。
那在扩容时,一次只扩容一台机器时,是不是就安全了呢?这样就能保证所有PG都至少在老机器有2个完整的副本了。可是,即使是扩容一台机器,也还要面临扩容时老机器中有硬盘坏掉,导致PG的完整副本又下降为1的极端情况发生。
办法是,在开始规划Ceph集群时,设定好更大层次的“容错域”,比如Rack。 可以是真实的Rack,即使没有也可以是逻辑的Rack。这样扩容时,可以扩一个逻辑“容错域”,就可以打破扩一台机器的限制,扩一整个Rack,至少有好几台机器。
(2)扩容是 crushmap 变化带领的系统抖动
Ceph是根据crushmap去放置PG的物理位置的,倘若在扩容进行了一半时,又有硬盘坏掉了,那Ceph的crushmap就会改变,Ceph又会重新进行PG的re-hash,很多PG的位置又会重新计算。如果运气比较差,很可能一台机器的扩容进度被迫进行了很久才回到稳定的状态。
这个crushmap改变导致的Ceph重平衡,不单单在扩容时,几乎在任何时候,对一个大的存储集群都有些头疼。在建立一个新集群时,硬盘都比较新,因此故障率并不高。但是在运行了2-3年的大存储集群,坏盘真的是一个稀松平常的事情,1000台规模的集群一天坏个2-3块盘很正常。crushmap经常变动,对Ceph内部不稳定,影响真的很大。随之而来,可能是整体IO的下降(磁盘IO被反复的rebalance占满),甚至是某些数据暂时不可用。
(3)OSD 增加时候的PG数量调整
假设我们现在有10台机器,每台一块硬盘一共10块盘,有1024个PG,PG都是单副本,那么每个盘会存100个PG。此时这个设置非常健康,但当我们集群扩容到1000台机器,每台硬盘就只放一个PG了,这会导致伪随机造成的不平衡现象放大。因此,admin就要面临调整PG数量,这就带来了问题。调PG,基本也就意味着整个集群会进入一种严重不正常的状态。几乎50%的对象,涉及到调整后的PG都需要重新放置物理位置,这会引起服务质量的严重下降。
(4)盘满造成的系统不可访问
在集群整体使用率不高时,都没有问题。而在使用率达到70%后,就需要管理员介入了。因为方差大的盘,很有可能会触及95%这条红线。admin开始调低容量过高磁盘的reweight,但如果在这一批磁盘被调整reweight没有结束时,又有一些磁盘被写满了,那管理员就必须被迫在Ceph没有达到稳定状态前,又一次reweight过高的磁盘。 这就导致了crushmap的再一次变更,从而导致Ceph离稳定状态越来越远。而此时扩容又不及时的话,更是雪上加霜。而且之前的crushmap的中间状态,也会导致一些PG迁移了一半,这些“不完整的”PG并不会被马上删除,这给本来就紧张的磁盘空间又加重了负担。关于reweight 导致的 rebalance,可参考 https://ceph.com/geen-categorie/ceph-osd-reweight/。
一块磁盘满了,Ceph为什么就不可用了。Ceph还真的就是这样设计的,因为Ceph没法保证新的对象是否落在空盘而不落在满盘,所以Ceph选择在有盘满了时,就拒绝服务。基本上大家的Ceph集群都是在达到50%使用率时,就要开始准备扩容了。
4.4 Ceph结构和状态地图cluster map
4.4.1 cluster map介绍
在Ceph中有很多的运行图,比如Monitor运行图,OSD运行图,集群运行图,MDS运行图和CRUSH运行图,它们统称为cluster map
由若干个monitor共同负责整个Ceph集群中所有OSD状态的发现与记录,并且共同形成cluster map的master版本,然后扩散至全体OSD以及client。
OSD daemon使用cluster map进行数据的维护,而client使用cluster map进行数据的寻址。 monitor并不主动轮询各个OSD的当前状态。正相反,OSD需要向monitor上报状态信息。常见的上报有两种情况:
一是新的OSD被加入集群
二是某个OSD发现自身或者其他OSD发生异常。
在收到这些上报信息后,monitor将更新cluster map信息并加以扩散,举例
4.4.2 Cluster map的内容
1、Epoch,即版本号,为一个单调递增序列,Epoch越大,则cluster map版本越新。
2、Monitor Map:MON 集群的状态
3、OSD Map与PG Map:各个OSD的网络地址。各个OSD的状态。up或者down,表明OSD是否正常工作;in或者out,表明OSD是否在至少一个PG中。
4、Crush Map:CRUSH算法配置参数。表明了Ceph集群的物理层级关系(cluster hierarchy),位置映射规则(placement rules)。
4.4.3 Monitor map:Mon集群的状态图
4.4.4 OSD Map:当前所有 Pool 的状态和所有 OSD 的状态
4.4.5 PG Map(Placement Group)
包含PG 版本(version)、时间戳、最新的 OSD map epoch, full ratios, and 每个 PG 的详细信息比如 PG ID, Up Set, Acting Set, 状态 (e.g., active + clean), pool 的空间使用统计。可以通过ceph pg dump获得
ceph pg dump | awk ’
/^pg_stat/ { col=1; while($col!=“up”) {col++}; col++ }
/1+.[0-9a-f]+/ { match($0,/2+/); pool=substr( 0 , R S T A R T , R L E N G T H ) ; p o o l l i s t [ p o o l ] = 0 ; u p = 0, RSTART, RLENGTH); poollist[pool]=0; up= 0,RSTART,RLENGTH);poollist[pool]=0;up=col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
printf(“\n”);
printf(“pool :\t”); for (i in poollist) printf(“%s\t”,i); printf(“| SUM \n”);
for (i in poollist) printf(“--------”); printf(“----------------\n”);
for (i in osdlist) { printf(“osd.%i\t”, i); sum=0;
for (j in poollist) { printf(“%i\t”, array[i,j]); sum+=array[i,j]; poollist[j]+=array[i,j] }; printf(“| %i\n”,sum) }
for (i in poollist) printf(“--------”); printf(“----------------\n”);
printf(“SUM :\t”); for (i in poollist) printf(“%s\t”,poollist[i]); printf(“|\n”);
}’
其他脚本
ceph pg dump | awk ’
BEGIN { IGNORECASE = 1 }
/^PG_STAT/ { col=1; while($col!=“UP”) {col++}; col++ }
/3+.[0-9a-f]+/ { match($0,/4+/); pool=substr( 0 , R S T A R T , R L E N G T H ) ; p o o l l i s t [ p o o l ] = 0 ; u p = 0, RSTART, RLENGTH); poollist[pool]=0; up= 0,RSTART,RLENGTH);poollist[pool]=0;up=col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
printf(“\n”);
printf(“pool :\t”); for (i in poollist) printf(“%s\t”,i); printf(“| SUM \n”);
for (i in poollist) printf(“--------”); printf(“----------------\n”);
for (i in osdlist) { printf(“osd.%i\t”, i); sum=0;
for (j in poollist) { printf(“%i\t”, array[i,j]); sum+=array[i,j]; sumpool[j]+=array[i,j] }; printf(“| %i\n”,sum) }
for (i in poollist) printf(“--------”); printf(“----------------\n”);
printf(“SUM :\t”); for (i in poollist) printf(“%s\t”,sumpool[i]); printf(“|\n”);
}’
4.4.6 CRUSH Map:Controlled Replication under Scalable Hashing
1、什么是crush?
CRUSH是一种类似于一致性hash的算法,用于为RADOS存储集群控制数据分布,全称为:Controlled Replication Under Scalable Hashing
2、crush在ceph集群中的作用?
负责数据从PG到OSD的存取。
3、故障域
可以把故障域理解为一个单元,这个单元有大有小,成一个倒树。其中最小为OSD,OSD之上为具体的服务器,服务器通过是放置在机架上,所以再者是机架,机排(一排机架),一个配电单元,机房,数据中心,根(root)。 正确的设置故障域可以降低数据丢失的风险,如果将故障域设置为OSD,那么同一条数据肯定将分布在不同OSD,有台服务器有可能会有多个OSD,有可能这条数据都在这台服务器上面,如果这台服务器宕机,有可能造成丢失。如果将故障域设置为host,那么一条数据肯定分布在不同的host,那么这时候如果有一台host宕机不会造成数据丢失(推荐)。 Ceph集群中默认的故障域有。
osd:硬盘
host:服务器
chassis:机箱
rack:机架(一个机架包含多个机箱)
row:机排
pdu:配电单元(有可能多个机排共用一个配电单元)
pod:多个机排
room:机房
datacenter:数据中心(有可能多个机房组成一个数据中心)
region:区域(华东1,华东2等)
root:最顶级,必须存在 注意:这些故障域也称之为Bucket,但有些Bucket非radowsgw里面的bucket。
CRUSH map 使用分层结构来组织集群中的所有存储设备:
4、故障域算法
每个故障域都自己的算法,比如可以对每个故障域内的对象设置权重,这时候数据将以权重的大小比例将数据均分。比如硬盘大些的可能权重会高些,而硬盘小些的权重将低些。这样才可以保证数据存放到每个OSD的比例都差不多,而不是占用空间大小差不多。通常这样的过程需要一个算法来支持,一般有下面的一些算法。
uniform
list
tree
straw
straw2:straw的升级版,也是现在默认使用的版本,也推荐使用这个,其它的作为了解即可。
5、crush rules与crush的算法流程
CRUSH rules 主要有三个作用:
指定从CRUSH Map 中的哪个节点开始查找
指定使用那个节点作为故障隔离域
指定定位副本的搜索模式(广度优先 or 深度优先)
例子:
rule egon_rule { # 规则集的命名,创建pool时可以指定rule集
id 1 # id设置为1
type replicated # 定义pool类型为replicated(还有esurecode模式)
min_size 1 # pool中最小指定的副本数量不能小1
max_size 10 # pool中最大指定的副本数量不能大于10
step take datacenter0 # 定义pg查找副本的入口点
# 这一步选择一个根节点,这个节点不一定是root
# 这个节点可以是任何一个故障域
# 从指定选择的这个节点开始执行。
step chooseleaf firstn 0 type rack # 深度优先、隔离默认为host,设置为rack
step emit # 结束,返回结果
}
PG 选择 OSD 的过程(详情可阅读 PG选择osd的过程(crush 算法)):
首先要知道在 rules 中指明从 CRUSH map 中哪个节点开始查找,入口点默认为 default 也就是 root 节点
然后隔离域为 host 节点(也就是同一个host下面不能选择两个子节点)。由 default 到3个host的选择过程,这里由default根据节点的bucket类型选择下一个子节点,由子节点再根据本身的类型继续选择,知道选择到host,然后在host下选择一个osd。
4.5 crush算法与写入流程
ceph存储小文件效率不高,底层osd daemon越多,存大文件效率越高,为何???
以rbd块存储客户端为例,客户端读写的都是rados中的对象object,读写object需要走完的流程是
File → (Pool, Object) → (Pool, PG) → OSD set → OSD/Disk
图解
步骤解析如下
五 高层应用接口详解
介绍完ceph的大核心rados之后,我们来聊一下上层的应用,在第二章我们提过rados之上封装的是librados,在librados之上封装了:对象存储接口rados gw、块存储接口rbd,以及文件存储接口Ceph FS,本章节我们就来详细介绍一下他们
5.1 块设备存储接口
首先,什么是块设备?
块设备是i/o设备中的一类,是将信息存储在固定大小的块中,每个块都有自己的地址,还可以在设备的任意位置读取一定长度的数据。看不懂?那就暂且认为块设备就是硬盘或虚拟硬盘吧。
查看下Linux环境中的设备:
root@egon:~$ ls /dev/
/dev/sda/ dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1 /dev/hda
/dev/rbd1 /dev/rbd2 …
上面的/dev/sda、/dev/sdb和/dev/hda都是块设备文件,这些文件是怎么出现的呢?
当给计算机连接块设备(硬盘)后,系统检测的有新的块设备,该类型块设备的驱动程序就在/dev/下创建个对应的块设备设备文件,用户就可以通过设备文件使用该块设备了。
它们怎么有的叫 sda?有的叫 sdb?有的叫 hda?
以sd开头的块设备文件对应的是SATA接口的硬盘,而以hd开头的块设备文件对应的是IDE接口的硬盘。那SATA接口的硬盘跟IDE接口的硬盘有啥区别?你只需要知道,IDE接口硬盘已经很少见到了,逐渐被淘汰中,而SATA接口的硬盘是目前的主流。而sda和sdb的区别呢?当系统检测到多个SATA硬盘时,会根据检测到的顺序对硬盘设备进行字母顺序的命名。PS:系统按检测顺序命名硬盘会导致了盘符漂移的问题。
怎么还有的叫 rbd1 和 rbd2 呢?
被你发现了,rbd就是我们压轴主角了。rbd就是由Ceph集群提供出来的块设备。可以这样理解,sda和hda都是通过数据线连接到了真实的硬盘,而rbd是通过网络连接到了Ceph集群中的一块存储区域,往rbd设备文件写入数据,最终会被存储到Ceph集群的这块区域中。
那么块设备怎么用呢?这里举个例子:
打个比方,一个块设备是一个粮仓,数据就是粮食。农民伯伯可以存粮食(写数据)了,需要存100斤玉米,粮仓(块设备)这么大放哪里呢,就挨着放(顺序写)吧。又需要存1000斤花生,还是挨着放吧。又需要存……
后来,农民伯伯来提粮食(读数据)了,他当时存了1000斤小麦,哎呀妈呀,粮仓这么大,小麦在哪里啊?仓库管理员找啊找,然后哭晕在了厕所……
新管理员到任后,想了个法子来解决这个问题,用油漆把仓库划分成了方格状,并且编了号,在仓库门口的方格那挂了个黑板,当农民伯伯来存粮食时,管理员在黑板记录,张三存了1000斤小麦在xx方格处。后来,农民伯伯张三来取粮食时,仓库管理员根据小黑板的记录很快提取了粮食。
故事到此为止了,没有方格和黑板的仓库(块设备)称为裸设备。由上例可见,裸设备对于用户使用是很不友好的,直接导致了旧仓库管理员的狗带。例子中划分方格和挂黑板的过程其实是在块设备上构建文件系统的过程,文件系统可以帮助块设备对存储空间进行条理的组织和管理,于是新管理员通过文件系统(格子和黑板)迅速找到了用户(农民伯伯张三)存储的数据(1000斤小麦)。针对多种多样的使用场景,衍生出了很多的文件系统。有的文件系统能够提供更好的读性能,有的文件系统能提供更好的写性能。我们平时常用的文件系统如xfs、ext4是读写性能等各方面比较均衡的通用文件系统。
能否直接使用不含有文件系统块设备呢?
可以的,xfs和ext4等通用的文件系统旨在满足大多数用户的存储需求,所以在数据存储的各方面的性能比较均衡。然而,很多应用往往并不需要这种均衡,而需要突出某一方面的性能,如小文件的存储性能。此时,xfs、ext4等通用文件系统如果不能满足应用的需求,应用往往会在裸设备上实现自己的数据组织和管理方式。简单的说,就是应用为了强化某种存储特性而实现自己定制的数据组织和管理方式,而不使用通用的文件系统。
Ceph块设备接口怎么使用?
在Ceph集群中创建块设备:
// 保证/etc/ceph目录下有Ceph集群的配置文件ceph.conf和ceph.client.admin.keyring
rbd create -s 1G egonrbd
在用户机上挂载该Ceph块设备,可以理解为往用户机上插入硬盘:
rbdmap egonrbd
// 输出:
/dev/rbd1
将Ceph块设备格式化成文件系统并挂载:
mkfs.xfs /dev/rbd1
mkdir -p /mnt/ceph_rbd
mount /dev/rbd1 /mnt/ceph_rbd
通过/mnt/ceph_rbd读写数据,都是在读写Ceph集群中该块设备对应的存储区域
总结一下,块设备可理解成一块硬盘,用户可以直接使用不含文件系统的块设备,也可以将其格式化成特定的文件系统,由文件系统来组织管理存储空间,从而为用户提供丰富而友好的数据操作支持。
5.2 文件存储接口
什么是Ceph的文件系统接口?
还记得上面说的块设备上的文件系统吗,用户可以在块设备上创建xfs文件系统,也可以创建ext4等其他文件系统。如图1,Ceph集群实现了自己的文件系统来组织管理集群的存储空间,用户可以直接将Ceph集群的文件系统挂载到用户机上使用。
Ceph有了块设备接口,在块设备上完全可以构建一个文件系统,那么Ceph为什么还需要文件系统接口呢?
主要是因为应用场景的不同,Ceph的块设备具有优异的读写性能,但不能多处挂载同时读写,目前主要用在OpenStack上作为虚拟磁盘,而Ceph的文件系统接口读写性能较块设备接口差,但具有优异的共享性。PS:想了解更多?快去查查SAN和NAS。
为什么Ceph的块设备接口不具有共享性,而Ceph的文件系统接口具有呢?
对于Ceph的块设备接口,如图2,文件系统的结构状态是维护在各用户机内存中的,假设Ceph块设备同时挂载到了用户机1和用户机2,当在用户机1上的文件系统中写入数据后,更新了用户机1的内存中文件系统状态,最终数据存储到了Ceph集群中,但是此时用户机2内存中的文件系统并不能得知底层Ceph集群数据已经变化而维持数据结构不变,因此用户无法从用户机2上读取用户机1上新写入的数据。
对于Ceph的文件系统接口,如图3,文件系统的结构状态是维护在远端Ceph集群中的,Ceph文件系统同时挂载到了用户机1和用户机2,当往用户机1的挂载点写入数据后,远端Ceph集群中的文件系统状态结构随之更新,当从用户机2的挂载点访问数据时会去远端Ceph集群取数据,由于远端Ceph集群已更新,所有用户机2能够获取最新的数据。
Ceph的文件系统接口使用方式?
将Ceph的文件系统挂载到用户机目录
/* 保证/etc/ceph目录下有Ceph集群的配置文件ceph.conf和ceph.client.admin.keyring */
mkdir -p /mnt/ceph_fuse
ceph-fuse /mnt/ceph_fuse
大功告成,在/mnt/ceph_fuse下读写数据,都是读写远程Ceph集群
总结一下,Ceph的文件系统接口弥补了Ceph的块设备接口在共享性方面的不足,Ceph的文件系统接口符合POSIX标准,用户可以像使用本地存储目录一样使用Ceph的文件系统的挂载目录。还是不懂?这样理解吧,无需修改你的程序,就可以将程序的底层存储换成空间无限并可多处共享读写的Ceph集群文件系统。
5.3 对象存储接口
首先,通过图4来看下对象存储接口是怎么用的?
简单了说,使用方式就是通过http协议上传下载删除对象(文件即对象)。
老问题来了,有了块设备接口存储和文件系统接口存储,为什么还整个对象存储呢?
往简单了说,Ceph的块设备存储具有优异的存储性能但不具有共享性,而Ceph的文件系统具有共享性然而性能较块设备存储差,为什么不权衡一下存储性能和共享性,整个具有共享性而存储性能好于文件系统存储的存储呢,对象存储就这样出现了。
对象存储为什么性能会比文件系统好?
原因是多方面的,主要原因是对象存储组织数据的方式相对简单,只有bucket和对象两个层次(对象存储在bucket中),对对象的操作也相对简单。而文件系统存储具有复杂的数据组织方式,目录和文件层次可具有无限深度,对目录和文件的操作也复杂的多,因此文件系统存储在维护文件系统的结构数据时会更加繁杂,从而导致文件系统的存储性能偏低。
Ceph的对象存储接口怎么用呢?
Ceph的对象接口符合亚马逊S3接口标准和OpenStack的Swift接口标准,可以自行学习这两种接口。
总结一下,文件系统存储具有复杂的数据组织结构,能够提供给用户更加丰富的数据操作接口,而对象存储精简了数据组织结构,提供给用户有限的数据操作接口,以换取更好的存储性能。对象接口提供了REST API,非常适用于作为web应用的存储。
5.4 总结
概括一下,块设备速度快,对存储的数据没有进行组织管理,但在大多数场景下,用户数据读写不方便(以块设备位置offset + 数据的length来记录数据位置,读写数据)。而在块设备上构建了文件系统后,文件系统帮助块设备组织管理数据,数据存储对用户更加友好(以文件名来读写数据)。Ceph文件系统接口解决了“Ceph块设备+本地文件系统”不支持多客户端共享读写的问题,但由于文件系统结构的复杂性导致了存储性能较Ceph块设备差。对象存储接口是一种折中,保证一定的存储性能,同时支持多客户端共享读写。
六 块存储接口rbd的写入
6.1 块存储接口rbd的写入过程
客户端写入数据以块存储rbd为例,一般有两种方法:
第一种 是 Kernel rbd。就是创建了rbd设备后,把rbd设备map到内核中,形成一个虚拟的块设备,这时这个块设备同其他通用块设备一样,一般的设备文件为/dev/rbd0,后续直接使用这个块设备文件就可以了,可以把 /dev/rbd0 格式化后 mount 到某个目录,也可以直接作为裸设备使用。这时对rbd设备的操作都通过kernel rbd操作方法进行的。
第二种是 librbd 方式。就是创建了rbd设备后,这时可以使用librbd、librados库进行访问管理块设备。这种方式不会map到内核,直接调用librbd提供的接口,可以实现对rbd设备的访问和管理,但是不会在客户端产生块设备文件。
应用写入rbd块设备的过程(假设后端存储引擎为filestore)
应用调用 librbd 接口或者对linux 内核虚拟块设备写入二进制块。下面以 librbd 为例。
librbd 对二进制块进行分块,默认块大小为 4M,每一块都有名字,成为一个对象
librbd 调用 librados 将对象写入 Ceph 集群
librados 向主 OSD 写入分好块的二进制数据块 (先建立TCP/IP连接,然后发送消息给 OSD,OSD 接收后写入其磁盘)
主 OSD 负责同时向一个或者多个次 OSD 写入副本。注意这里是写到日志(Journal)就返回,因此,使用SSD作为Journal的话,可以提高响应速度,做到服务器端对客户端的快速同步返回写结果(ack)。
当主次OSD都写入完成后,主 OSD 向客户端返回写入成功。
当一段时间(也许得几秒钟)后Journal 中的数据向磁盘写入成功后,Ceph通过事件通知客户端数据写入磁盘成功(commit),此时,客户端可以将写缓存中的数据彻底清除掉了。
默认地,Ceph 客户端会缓存写入的数据直到收到集群的commit通知。如果此阶段内(在写方法返回到收到commit通知之间)OSD 出故障导致数据写入文件系统失败,Ceph 将会允许客户端重做尚未提交的操作(replay)。因此,PG 有个状态叫 replay:“The placement group is waiting for clients to replay operations after an OSD crashed.”。
也就是,文件系统负责文件处理,librdb 负责块处理,librados 负责对象处理,OSD 负责将数据写入在Journal和磁盘中。
6.2 储备知识:常见的write cache种类
基于块存储接口rbd封装的块存储客户端具有写缓存机制,要了解它,我们先来了解一下write cache种类
缓存种类 说明 优劣势 适合场景
缓存的通常位置分类:
服务器(主机)上:RAID 卡或者 HBA 卡上做缓存。
VMM 内:在 Hypervisor 上做缓存。
客户机操作系统内:以 Windows 2012 为例,它提供 write-back 缓存机制。
6.3 RBD块存储缓存
默认情况下,Ceph RBD 是不使用缓存的,读和写直接到 Ceph 集群中的存储,写只有在所有 replication上写都完成后才给客户端返回写完成。Ceph 在较新的版本上陆续添加了 RBD 缓存支持:
从 0.46 版本开始,Ceph 支持 write-back 缓存,你可以在 ceph.conf 文件的 [client] 部分添加 rbd cache = true 来使得 write-back 缓存生效。这时候,写几乎是立即返回,但是数据只有在被 flushed 后才写入到实际存储。
从 0.47 版本开始,Ceph 支持 write-through 缓存机制。你只需要再添加配置项 rbd cache max dirty = 0 即可。
从 0.60 版本开始,Ceph 支持 rbd cache writethrough until flush 配置项。设置它为 true 时,会使得 write-through 机制变得更加安全,因为老的客户机操作系统(2.6.32 内核版本之前)可能不支持 flush 操作。因此,在设置了该配置项为 true 时,即使用户设置了使用 write-through 机制,Ceph 也会自动使用 write-back 机制,直到它收到第一个 flush 指令后才真正使用 write-through。
可见 RBD 缓存是在客户端做的,见如下图示:
6.4 Cache tiering (缓存分层)
Ceph 还支持在集群段做缓存分层。其原理是,在较快的磁盘比如 SSD 上建立一个 cache pool,在建立存储池(storage pool)和它之间的 cache 关系,设置一定的缓存策略,实现类似于在客户端缓存同样的效果。
6.5 RBD Cache 和 Cache Tiering 的区别
从上面的分析可以看出来,两者的区别在于缓存的位置不同:
sCache tiering 是 RADOS 层在 OSD 端进行数据缓存,也就是说不论是块存储、对象存储还是文件存储都可以使用tier来提高读写速度
RBD Cache是 rbd 层在客户端的缓存,也就是只支持块存储。
Rbd cache是 客户端的缓存,当多个客户端使用同个块设备时,存在客户端数据不一致的问题。举个例子,用户A向块设备写入数据后,数据停留在客户自己的缓存中,没有立即刷新到磁盘,所以其它用户读取不到A写入的数据。但是tier不存在这个问题,因为所有用户的数据都直接写入到 ssd,用户读取数据也是在ssd中读取的,所以不存在客户端数据不一致问题。
一般地,Tier 使用 SSD 做缓存,而 Rbd cache 只能使用内存做缓存。SSD和内存有两个方面的差别,一个是读写速度、另一个是掉电保护。掉电后内存中的数据就丢失了,而ssd中的数据不会丢失。
七 存储引擎
7.1 存储引擎介绍介绍
ceph后端支持多种存储引擎,以插件式的方式来进行管理使用,目前支持filestore,kvstore,memstore以及最新的bluestore。
在老版本的Ceph当中FileStore是默认的对象存储引擎,但FileStore是基于操作系统通用的文件系统层,例如Ext4和XFS等,这些都是日志文件系统,所以filestore在写数据前需要先写journal,会有写放大问题(即一次读写请求实际在低层磁盘发生的IO次数,再加上FileStore的日志双写,放大倍数成倍增加,推荐阅读https://blog.csdn.net/majianting/article/details/105517527),并且filestore一开始只是对于机械盘进行设计的,没有专门针对ssd做优化考虑,因此整体性能欠佳。
于是bluestore应运而生,BlueStore设计的初衷就是为了减少写放大,并针对ssd做优化,而且直接管理裸盘,抛弃了ext4/xfs等本地文件系统,从理论上进一步减少文件系统如ext4/xfs等部分的开销、效率更高。
luminous版默认的存储引擎为bluestore,结构图如下
直接使用一个原始分区,ceph对象将直接写在块设备上,不再需要任何的文件系统,和osd一起进来的元数据将存储在 一个 名为 RocksDB 的键值对 数据库;
RocksDB :存储 WAL 日志和元数据(omap)
BlueRocksEnv: 与RocksDB 交互的接口
BlueFS : 一个类似文件系统的 mini C++,使 rocksdb 生效,ENv 接口(存储 RocksDB 日志和 sst 文件);
因为rocksdb 一般跑在一个文件系统的上层,所以创建了 BlueFS。
对象的元数据
write-ahead 日志
ceph omap 数据
allocator metadata(元数据分配器):决定数据存放位置;此功能可插拔
第一个小分区(XFS或者ext4),包括ceph files
(init system descriptor,status,id,fsid,keyring 等)和RocksDB 文件
第二个分区是一个原始分区
每一部分都可以存放在不同的磁盘中,RocksDB WAL 和 DB 可以存放在不同的磁盘或者小分区中
可以查看帮助文档
[root@admin ceph]# ceph-deploy osd --help
For bluestore, optional devices can be used::
。。。
For filestore, the journal must be specified, as well as the objectstore::
ceph-deploy osd create {node} --filestore --data /path/to/data --journal /path/to/journal
https://ceph.com/community/new-luminous-bluestore/
https://baijiahao.baidu.com/s?id=1635414952916759127&wfr=spider&for=pc
7.2 Bluefs中的DB和WAL分区
https://www.cnblogs.com/linhaifeng/articles/14708563.html
7.3 基于bluestore管理osd
由于Luminous里默认使用Bluestore,直接在裸盘上进行操作即可,无需制作文件系统,所以压根不需要journal盘,但是需要block-db与block.wal,综合考虑
data盘我们使用sas口的机械硬盘,block-db与block.wal我们使用固态盘的两个分区(生产环境一块ssd磁盘会对应多块osd,所以我们需要把ssd多个分区),
需知底层都会做逻辑卷
ceph-volume 是在 Luminous 推出的全新 OSD 部署和管理介质的工具,用于替换之前使用很多年的 ceph-disk。目前 ceph-volume 使用 LVM 作为设备的管理实现,也就是说,在 Luminous 以后,社区会强制使用 LVM 作为所有 OSD 的设备管理工具。但是为了兼容 ceph-disk 原本管理的设备,ceph-volume 仍然支持对旧设备的简单管理。在 12.2.2 版本后,ceph-disk 会正式废弃。
Sage 在上周邮件列表宣布了这一变化,短期来看,lvm 会被强制使用,暂时没有支持其他插件的计划。背后主要也是维护多套设备管理成本太高,另外 Redhat 对于 DeviceMapper 这块有巨大投入,更愿意整合 LVM 而不是其他工具。
对于 LVM 方式来说,好处是带来了众多 LVM 本身的功能,比如 dmcache,加密等,另一方面,LVM 也是 Linux 管理员熟识的工具,方便用户直接管理。不过问题是 LVM 毕竟是一层不可忽视的逻辑,对性能特别是高速介质还是有一些损耗,这个对于一些用户来说是个顾虑。
不过对于未来来说,社区仍然希望有其他插件来跟 LVM 并存,目前从 12.2.2 版本开始,用户已经可以使用 ceph-volume 了。
7.4 基于filestore管理osd
需要先对硬盘制作文件系统,每个制作过文件系统的disk最好对应一块journal盘,journal盘无需制作文件系统。
在6.1小节egon就给大家提过,主 OSD 负责同时向一个或者多个次 OSD 写入副本。注意这里是写到日志(Journal)就返回,因此,使用SSD作为Journal的话,可以提高响应速度,做到服务器端对客户端的快速同步返回写结果(ack)。
journal的信息建议使用硬盘或SSD盘单独存放,所以我们需要为OSD节点上的每个disk配一个journal日志盘,最好为ssd盘,说到ssd盘,需要先了解一下它得写放大现象:https://www.cnblogs.com/linhaifeng/articles/14692472.html
egon之前在公司做ceph的时候版本为hammer,osd节点上总共有个16+8+2块盘,16块为disk,8块为ssd,2块为ssd做raid1当系统盘,8块ssd每块分两个分区(固态硬盘讲究少分区、小分区,但分成两个分区还是可以的,你要有钱,你买16块ssd那自然最好),于是分成了16个journal与16个disk对应,具体一个disk应该对应多大的journal盘呢,有一个计算公式
在ceph.conf中,日志大小osd journal size默认5120MB,即5G
注:如果是0表示整个块设备都用来存日志,建议初始设为1G
osd journal size至少为 2 * (expected throughput * filestore max sync interval)
其中throughput 为磁盘disk的转速和网络速率的最小值
filestore max sync interval最大的同步时间,默认为15s
请看egon老师的项目附件
磁盘disk的速率为6Gbps,而网络为10Gbps,选取最小的一个
2*(6Gbps*15)=180
180/8=30G,需要30G的日志盘,而我们一个ssd盘200G,分两个分区,每个分区100G,足足够了
监控硬盘的时候:
分区使用率70%警告,80%报警
提示
Gbps也称交换带宽,是衡量交换机总的数据交换能力的单位,以太网是IEEE802.3以太网标准的扩展,传输速度为每秒1000兆比特位(即1Gbps)。
为了创建一个一致的提交点(consistent commit point),filestore需要停止写操作来执行syncfs(),也就是从日志中同步数据到数据盘,然后清理日志。更加频繁地同步操作,可以减少存储在日志中的数据量。这种情况下,日志就能充分得到利用。配置一个越小的同步值,越有利于文件系统合并小量的写,提升性能。下面的参数定义了两次同步之间最小和最大的时间周期。
filestore_min_sync_interval = 10
filestore_max_sync_interval = 15
对于hammer版ceph,后端的存储引擎为了filestore,部署osd时需要执行下述命令
格式为: osd节点的ip地址:osd磁盘:日志盘
ceph-deploy --overwrite-conf osd create $host:sdb1:/dev/sdh1 $host:sdc1:/dev/sdh2 $host:sdd1:/dev/sdi1 $host:sde1:/dev/sdi2 $host:sdf1:/dev/sdj1 $host:sdg1:/dev/sdj2
八 ceph版本
[root@admin ceph]# ceph --version
ceph version 12.2.13 (584a20eb0237c657dc0567da126be145106aa47e) luminous (stable)
Luminous v12.2.x是一个LTS长期稳定版本,官方建议所有用户升级到此版本。
ceph版本
https://docs.ceph.com/en/latest/releases/
http://docs.ceph.org.cn/releases/
ceph-deploy版本:https://docs.ceph.com/en/latest/install/
ceph-deploy --version
2.0.1
ceph-deploye不再积极维护。它没有在比Nautilus新的Ceph版本上进行测试。它不支持RHEL8、CentOS 8或更新的操作系
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
目录
分布式存储ceph部署篇
1、安装完操作系统
2、配置完硬件
3、网络规划
4、每台机器均关闭selinux与防火墙
5、每台主机规范主机名
6、每台主机均开启yum缓存
7、每台机器升级操作系统并安装依赖包
8、每台机器均安装常用软件
9、每台机器均配置ceph源
10、每台机器均修改ssh配置
11、在管理节点添加hosts解析,地址为public_addr
12、在管理节点制作密钥登录所有其他节点
13、在管理节点把/etc/hosts发给其他节点
14、配置ntp服务,保证集群服务器时间统一
15、创建工作目录
16、在管理节点安装并配置ceph-deploy
17、在管理节点为其他节点安装ceph包
18、初始化集群
19、配置初始 monitor(s)、并收集所有密钥
20、部署admin节点
21、部署并激活osd节点
22、在admin节点修改配置文件
23、开启监控模块
分布式存储ceph部署篇
1、安装完操作系统
镜像:
centos7.6
镜像下载地址:
链接: https://pan.baidu.com/s/1IuJ5mL5H__4M8U-TlGaxkg 提取码: 56c7
2、配置完硬件
如果用的是真机部署线上环境
硬件配置请参考egon老师的附件:《附件1:DELL服务器配置》
ceph安装配置介绍与优化见:《附件2:ceph安装配置介绍与主机优化》
如果用的是虚拟机实验来进行测试,本机至少16G内存
admin节点:1.5G内存 2块网卡
mon01: 1.5G内存 2块网卡
mon02: 1.5G内存 2块网卡
mon03: 1.5G内存 2块网卡
osd01 2G内存 3块网卡 3块机械盘 3块固态盘
osd02 2G内存 3块网卡 3块机械盘 3块固态盘
osd03 2G内存 3块网卡 3块机械盘 3块固态盘
虚拟机实验环境请注意:
1、除了osd节点外,其他节点的硬盘盘不要挂太多,否则cpu占用过多导致虚拟机启动不了,因为都是虚拟出来的
2、虚拟磁盘空间为20G即可
3、把虚拟机无关的硬件都删掉,比如usb、声卡、打印机等
3、网络规划
主机 管理网络 public网络 cluster网络
注意:
若是生产环境,上述ip必须设置成固定ip
注意关闭NetworkManager
systemctl stop NetworkManager
systemctl disable NetworkManager
4、每台机器均关闭selinux与防火墙
sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/’ /etc/sysconfig/selinux
sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/’ /etc/selinux/config
setenforce 0
systemctl stop firewalld.service
systemctl disable firewalld.service
5、每台主机规范主机名
hostnamectl set-hostname admin
hostnamectl set-hostname mon01
hostnamectl set-hostname mon02
hostnamectl set-hostname mon03
hostnamectl set-hostname osd01
hostnamectl set-hostname osd02
hostnamectl set-hostname osd03
6、每台主机均开启yum缓存
sed -ri ‘2c cachedir=/soft’ /etc/yum.conf
sed -ri ‘3c keepcache=1’ /etc/yum.conf
mkdir /soft
注意注意注意:yum clean all会将缓存文件夹内缓存的rpm包都清理掉,需要特别注意的是
1、如果你打算采集rpm包,然后制作成自己的yum源,安装过程中不要手贱执行yum clean all
2、ceph-deploy在安装时会执行yum clean all命令,然后再按照,所以请在ceph-deploy install前将一些缓存的包备份好
Ps:关闭yum自动更新
默认不会安装yum-con,我们也无需关闭yum自动更新
但如果你自己安装了:yum install yum-cron -y,则会默认开启yum更新,请记得关闭
update_messages = no
download_updates = no
7、每台机器升级操作系统并安装依赖包
如果采用的不是官网源,而是自定义的yum源,那么
下述命令中就不需要执行yum install epel-release -y安装epel源了,切记
yum install epel-release -y && yum update -y && yum upgrade -y && reboot
升级后需要重启计算机才能加载新内核,注意,一定要重启计算机
系统:CentOS Linux release 7.6.1810 (Core)
内核:3.10.0-957.el7.x86_64
系统:CentOS Linux release 7.9.2009 (Core)
内核:3.10.0-1160.24.1.el7.x86_64 # 升级后
8、每台机器均安装常用软件
yum -y install python-setuptools python-pip gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel
zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel zip unzip ncurses ncurses-devel curl curl-devel e2fsprogs
e2fsprogs-devel krb5-devel libidn libidn-devel openssl openssh openssl-devel nss_ldap openldap openldap-devel openldap-clients
openldap-servers libxslt-devel libevent-devel ntp libtool-ltdl bison libtool vim-enhanced python wget lsof iptraf strace lrzsz
kernel-devel kernel-headers pam-devel tcl tk cmake ncurses-devel bison setuptool popt-devel net-snmp screen perl-devel
pcre-devel net-snmp screen tcpdump rsync sysstat man iptables sudo libconfig git bind-utils
tmux elinks numactl iftop bwm-ng net-tools expect
9、每台机器均配置ceph源
如果用的是自己的yum源,则无需下述操作
wget https://download.ceph.com/rpm-luminous/el7/noarch/ceph-release-1-1.el7.noarch.rpm
rpm -ivh ceph-release-1-1.el7.noarch.rpm
mv ceph-release-1-1.el7.noarch.rpm /soft
了解
https://download.ceph.com/
https://download.ceph.com/rpm-luminous/el7/x86_64/
所以我们如果没有安装ceph-release-1-1.el7.noarch.rpm,也可以以自己配置源
[ceph]
name=ceph
baseurl=https://download.ceph.com/rpm-luminous/el7/x86_64/
enabled=1
gpgcheck=0
http://mirrors.aliyun.com/ceph/rpm-luminous/el7/x86_64
如果想用egon制作ceph源头,请下载
链接: https://pan.baidu.com/s/1IuJ5mL5H__4M8U-TlGaxkg 提取码: 56c7
然后参照《07 部署自己的ceph源》
10、每台机器均修改ssh配置
加快远程链接速度,可选,但建议做
sed -ri ‘/#UseDNS yes/c UseDNS no’ /etc/ssh/sshd_config
systemctl restart sshd
11、在管理节点添加hosts解析,地址为public_addr
!!!注意地址为public_addr
!!!注意地址为public_addr
!!!注意地址为public_addr
cat >> /etc/hosts << EOF
1.1.1.200 admin
1.1.1.5 mon01
1.1.1.4 mon02
1.1.1.9 mon03
1.1.1.7 osd01
1.1.1.6 osd02
1.1.1.8 osd03
EOF
12、在管理节点制作密钥登录所有其他节点
制作秘钥对
ssh-keygen
在管理节点执行下述脚本(前提:目标主机的root密码均为1)
记得安装yum install expect -y
#!/bin/bash
for i in ‘admin’ ‘mon01’ ‘mon02’ ‘mon03’ ‘osd01’ ‘osd02’ ‘osd03’
do
expect -c "
spawn ssh-copy-id -i root@KaTeX parse error: Expected group as argument to '\"' at position 32: … \"(yes/no)\" ̲{send \"yes\r\"…i:/etc/hosts
done
14、配置ntp服务,保证集群服务器时间统一
统一时间非常重要,必须要做
大前提:chrony服务端客户端配置完后,重启chronyd服务即可快速完成时间同步,在这之后就不要再手动去修改时间了,一切让时间服务器自己去同步
chrony服务端:admin节点
yum -y install chrony
mv /etc/chrony.conf /etc/chrony.conf.bak
cat > /etc/chrony.conf << EOF
server ntp1.aliyun.com iburst minpoll 4 maxpoll 10
server ntp2.aliyun.com iburst minpoll 4 maxpoll 10
server ntp3.aliyun.com iburst minpoll 4 maxpoll 10
server ntp4.aliyun.com iburst minpoll 4 maxpoll 10
server ntp5.aliyun.com iburst minpoll 4 maxpoll 10
server ntp6.aliyun.com iburst minpoll 4 maxpoll 10
server ntp7.aliyun.com iburst minpoll 4 maxpoll 10
driftfile /var/lib/chrony/drift
makestep 10 3
rtcsync
allow 0.0.0.0/0
local stratum 10
keyfile /etc/chrony.keys
logdir /var/log/chrony
stratumweight 0.05
noclientlog
logchange 0.5
EOF
systemctl restart chronyd.service # 最好重启,这样无论原来是否启动都可以重新加载配置
systemctl enable chronyd.service
systemctl status chronyd.service
chrony客户端:其他节点,完全一样的配置与操作
yum -y install chrony
mv /etc/chrony.conf /etc/chrony.conf.bak
cat > /etc/chrony.conf << EOF
server admin iburst
driftfile /var/lib/chrony/drift
makestep 10 3
rtcsync
local stratum 10
keyfile /etc/chrony.key
logdir /var/log/chrony
stratumweight 0.05
noclientlog
logchange 0.5
EOF
systemctl restart chronyd.service
systemctl enable chronyd.service
systemctl status chronyd.service
若想了解时间服务器细节请点击:https://www.cnblogs.com/linhaifeng/articles/14699550.html
15、创建工作目录
为所有节点都创建一个ceph工作目录,后续的工作都在该目录下进行,在admin节点运行下述命令
#!/bin/bash
for host in ‘admin’ ‘mon01’ ‘mon02’ ‘mon03’ ‘osd01’ ‘osd02’ ‘osd03’
do
ssh root@$host mkdir -p /etc/ceph
[ KaTeX parse error: Expected 'EOF', got '&' at position 11: ? -eq 0 ] &̲& echo "host make directory ‘/etc/ceph’ successful"
done
16、在管理节点安装并配置ceph-deploy
管理节点安装并配置ceph-deploy,在/etc/ceph/目录下面进行,
cd /etc/ceph/
yum -y install ceph-deploy
ceph-deploy 2.0.1默认部署的是mimic版的ceph,若想安装其他版本的ceph,比如luminous,需要修改ceph-deploy的源,在管理节点运行下述命令
cat >> /etc/profile << EOF
export CEPH_DEPLOY_REPO_URL=http://download.ceph.com/rpm-luminous/el7/
export CEPH_DEPLOY_GPG_URL=https://download.ceph.com/keys/release.asc
EOF
source /etc/profile
17、在管理节点为其他节点安装ceph包
cd /etc/ceph
ceph-deploy install mon0{1…3} osd0{1…3}
ceph-deploy install admin
注意:所有主机都接入了管理网络,我们先通过管理网络部署完毕集群,部署成功后再修改ceph.conf配置文件指定public_addr网络与cluster_addr网络,然后推送给所有节点,重启服务即可
了解
1、ceph-deploy install本质就是在执行
yum clean all
yum -y install yum-plugin-priorities
yum -y -q install ceph ceph-release ceph-common ceph-radosgw
2、如果我们没有修改过源,也可以用—release手动指定版本
ceph-deploy install --release luminous mon0{1…3} osd0{1…3}
18、初始化集群
在管理节点运行下述命令,告诉ceph-deploy哪些是监控节点,命令成功后会在/etc/ceph下生成ceph.conf、ceph.log、ceph.mon.keyring文件
cd /etc/ceph
ceph-deploy new mon01 mon02 mon03
如果报错,首先看看主机名是否都按照规定设置,是否与hosts文件保持一致,然后在依次执行下述步骤
iptables -F
getenforce
setenforce 0
rm -rf /etc/ceph/*
rm -rf /var/lib/ceph//
rm -rf /var/log/ceph/*
rm -rf /var/run/ceph/*
cd /etc/ceph/
ceph-deploy new mon01 mon02 mon03
19、配置初始 monitor(s)、并收集所有密钥
在管理节点运行下述命令
cd /etc/ceph
ceph-deploy mon create mon01 mon02 mon03
ceph-deploy --overwrite-conf mon create-initial
ceph-deploy gatherkeys mon01
注意:只有在安装 Hammer 或更高版时才会创建 bootstrap-rgw 密钥环。
一旦这些密钥在本地目录中,您就可以设置新的osd等。
ceph.conf #ceph的配置文件
ceph-deploy-ceph.log #monitor的日志
ceph.mon.keyring # monitor的密钥环文件
20、部署admin节点
部署admin节点,以后可以在各个节点执行ceph命令,在管理节点运行下述命令
cd /etc/ceph
ceph-deploy admin admin mon01 mon02 mon03 osd01 osd02 osd03 # 第1个admin是选项,后续的都是主机名
21、部署并激活osd节点
因为我们例子中,每个osd节点三块机械盘当数据盘,三块固态盘每块分两个分区分别用做一个数据盘的–block-db和–block-wal
机械盘
/dev/sdb
/dev/sdc
/dev/sdd
固态盘
/dev/sde
/dev/sdf
/dev/sdg
在所有osd节点执行下述脚本,为固态盘分区
#!/bin/bash
SSDS=“e f g”
for i in S S D S ; d o p a r t e d − s / d e v / s d {SSDS}; do parted -s /dev/sd SSDS;doparted−s/dev/sd{i} mklabel gpt
parted -s /dev/sd i m k p a r t p r i m a r y 0 p a r t e d − s / d e v / s d {i} mkpart primary 0% 50% parted -s /dev/sd imkpartprimary0parted−s/dev/sd{i} mkpart primary 51% 100%
done
在管理节点执行下述脚本,部署并激活osd01、osd02、osd03上的所有osd
#!/bin/bash
cd /etc/ceph
for i in seq 1 3
do
ceph-deploy --overwrite-conf osd create osd0 i − − d a t a / d e v / s d b − − b l o c k − d b / d e v / s d e 1 − − b l o c k − w a l / d e v / s d e 2 c e p h − d e p l o y − − o v e r w r i t e − c o n f o s d c r e a t e o s d 0 {i} --data /dev/sdb --block-db /dev/sde1 --block-wal /dev/sde2 ceph-deploy --overwrite-conf osd create osd0 i−−data/dev/sdb−−block−db/dev/sde1−−block−wal/dev/sde2ceph−deploy−−overwrite−confosdcreateosd0{i} --data /dev/sdc --block-db /dev/sdf1 --block-wal /dev/sdf2
ceph-deploy --overwrite-conf osd create osd0${i} --data /dev/sdd --block-db /dev/sdg1 --block-wal /dev/sdg2
done
了解:
ceph-deploy osd create中的–data选项后面是作为数据盘的设备,–block-db选项后面是db分区,–block-wal选项后面是wal分区;db和wal通常部署在NVMe SSD上以提高写入性能,如果没有配置NVMe SSD或者直接使用NVMe SSD作为数据盘,则不需要–block-db和–block-wal,只需要–data指定数据盘即可。
ceph-deploy --overwrite-conf osd create osd01 --data vgb/lvb --block-db ssd_vgh1/ssd_lvh1 --block-wal ssd_vgh2/ssd_lvh2
ceph-deploy osd create node1 --data /dev/sdb
22、在admin节点修改配置文件
[root@admin ceph]# cat ceph.conf
[global]
fsid = cfd076f5-a4f1-4eca-9511-074371a21112
mon_initial_members = mon01, mon02, mon03
mon_host = 1.1.1.4,1.1.1.5,1.1.1.6
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
##如果有两块可以连通的网卡,配置public_network和cluster_network,如果是测试环境没有,就不配置
public_network = 1.1.1.0/24 #公共网络
cluster_network = 2.2.2.0/24 #集群网络
mon_pg_warn_max_per_osd = 1000
osd_pool_default_size = 3
osd_pool_default_min_size = 2
[mgr]
mgr modules = dashboard
[osd]
osd_max_write_size = 1024
osd_recovery_op_priority = 1
osd_recovery_max_active = 1
osd_recovery_max_single_start = 1
osd_recovery_max_chunk = 1048576
osd_recovery_threads = 1
osd_max_backfills = 1
osd_scrub_begin_hour = 22
osd_scrub_end_hour = 7
osd_recovery_sleep = 0
osd_crush_update_on_start = false ##如果初始化的时候,把该值设置为true,然后重启所有osd。不然创建完pool会提示:100.000% pgs unknown100.000% pgs unknown。所有osd都加入,集群ok后,再统一把该值设置为false, 然后重启所有osd
在管理节点把新的配置文件推送到其他节点
cd /etc/ceph
ceph-deploy --overwrite-conf config push mon01 mon02 mon03 osd01 osd03
去admin以外的其他节点重启服务,注意该有的pubic与cluster网络都需要提前配置好
方式1、重启ceph的所有守护进程
方式2、按类型启动守护进程
查看结果
ceph osd tree
ceph daemon /var/run/ceph/ceph-osd.5.asok config show | grep cluster_addr
ceph daemon /var/run/ceph/ceph-osd.5.asok config show | grep public_addr
23、开启监控模块
在L版本的Ceph中新增了manager daemon
在管理节点执行下述命令,把mon01做成mgr节点
ceph-deploy mgr create mon01
在mon01节点执行
ceph mgr moodule enable dashboard
浏览器输入:http://mon01的ip地址:7000
可以在mon01节点查看
ceph mgr dump # 查看集群支持的模块
ceph mgr services # 查看服务
systemctl status ceph-mgr.target
netstat -tulnp |grep 7000
提醒:目前 mgr 功能模块可能还存在选举问题,如果多mgr 节点都开启,可能会出现web页面取不到数据,建议只开启一个mgr节点服务,然后关闭其他节点mgr服务。
[cephadm@admin ceph-cluster]$ ceph mgr module enable dashboard
[cephadm@admin ceph-cluster]$ ceph config set mgr mgr/dashboard/ssl false
[cephadm@admin ceph-cluster]$ ceph config set mgr mgr/dashboard/mon02/server_addr 192.168.75.56
[cephadm@admin ceph-cluster]$ ceph config set mgr mgr/dashboard/mon02/server_port 9999
[root@mon02 ~]# systemctl restart [email protected]
在 deploy 节点上操作
1.创建 pass.txt 文件
[cephadm@admin ceph-cluster]$ touch pass.txt
[cephadm@admin ceph-cluster]$echo “123456” >> pass.txt
2.创建用户
ceph dashboard set-login-credentials uplooking 123456
[cephadm@admin ceph-cluster]$ ceph dashboard set-login-credentials zhang -i pass.txt
*** WARNING: this command is deprecated. ***
*** Please use the ac-user-* related commands to manage users. ***
Username and password updated
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ceph的fs使用:
启用文件系统(CephFS)接口
CephFS需要至少运行一个元数据服务器(MDS)守护进程(ceph-mds),此进程管理与CephFS上存储的文件相关
的元数据,并协调对Ceph存储集群的访问。因此,若要使用CephFS接口,需要在存储集群中至少部署一个MDS实
例。“ceph-deploy mds create {ceph-node}”命令可以完成此功能,例如,在stor01上启用MDS:
[cephadm@ceph-admin ceph-cluster]$ ceph-deploy mds create mon01
创建数据pool:
ceph osd pool create ceph_fsdata 128
创建matadata:
ceph osd pool create ceph_fsmetadata 128
启用pool
ceph fs new cephfs ceph_fsmetadata ceph_fsdata
查看cephfs
ceph fs ls
创建使用对象:
ceph fs authorize
示例:
ceph fs authorize cephfs client.oldliu / rw | tee /etc/ceph/oldliu.keyring
ceph fs authorize cephfs client.dyz /test r | tee /etc/ceph/dyz.keyring
(可以对多路径进行授权)
查看:
ceph auth list
删除:
ceph auth rm client.oldliu
获取信息:
ceph auth get client.oldliu
-o 导出到文件
客户端需要有ceph.cnf以及创建的用户密钥文件,以及ceph软件包
根据用户密钥文件生成密钥key
ceph-authtool -n client.oldliu -p oldliu.keyring > oldliu.key
客户端挂载:
方式1:
mount -t ceph mon1:6789,mon2:6789,mon3:6789:/ 本地路径 -o name=用户名, secret=密钥
或者
mount -t ceph mon1:6789,mon2:6789,mon3:6789:/ 本地路径 -o name=用户名, secretfile=密钥文件
方式2:
yum install ceph-fuse -y
ceph-fuse -n client.oldliu -m mon1:6789,mon2:6789,mon3:6789 本地路径(挂载点) -o nonempty
注意,挂载点必须为空,如果不为空,要么清理空,要么指定参数 -o nonempty
ceph的rbd块存储使用:
Ceph块设备接口(RBD)
Ceph块设备,也称为RADOS块设备(简称RBD),是一种基于RADOS存储系统支持超配(thin-provisioned)、可
伸缩的条带化数据存储系统,它通过librbd库与OSD进行交互。RBD为KVM等虚拟化技术和云OS(如OpenStack和
CloudStack)提供高性能和无限可扩展性的存储后端,这些系统依赖于libvirt和QEMU实用程序与RBD进行集成。
客户端基于librbd库即可将RADOS存储集群用作块设备,不过,用于rbd的存储池需要事先启用rbd功能并进行初始
化。例如,下面的命令创建一个名为rbddata的存储池,在启用rbd功能后对其进行初始化:
默认可用
创建存储池kvm指定pg与pgp都为32(pgp不用指定也可,默认与pg一样):
ceph osd pool create kvm 32 32
转换存储池为rbd模式:
ceph osd pool application enable kvm rbd
注:
如果自定义crush rule 请为pool指定rule
ceph osd pool set kvm crush_rule 规则名字(oldliu_rule)
初始化存储池
rbd pool init -p kvm
创建镜像:
rbd create --size 5G --pool
示例:
rbd create --size 1G --pool kvm img1
查看镜像:
rbd ls --pool kvm list
查看镜像详细信息:
rbd --image img1 --pool kvm info
可简写:rbd info kvm/img1
修改镜像大小:
rbd resize --pool kvm --image img1 --size 5G
减少(不建议操作):
rbd resize --pool kvm --image img1 --size 2G --allow-shrink
不建议直接删除镜像用以下方法(直接删除无法恢复)
rbd remove kvm/img1
推荐方法:
rbd trash move kvm/img1
rbd trash list --pool kvm
rbd trash restore kvm/id (id用list看) (恢复操作)
快照操作:
rbd snap create --pool --image --snap
示例(简约用法):
rbd snap create /@
rbd snap create kvm/img1@img1_snap1
查看指定镜像快照:
rbd snap list kvm/img1
还原快照:
rbd snap rollback kvm/img1@img1_snap1
限制镜像快照个数:
rbd snap limit set kvm/img1 --limit 3
解除限制:
rbd snap limit clear kvm/img1
删除快照:
rbd snap rm kvm/img1@img1_snap1
删除所有快照:
rbd snap purge kvm/img1
快照克隆:
1,将上游快照设置为保护模式
rbd snap protect kvm/img1@img1_snap1
2,克隆新快照:
rbd clone kvm/img1@img1_snap1 --dest kvm/img2
查看克隆快照:
rbd children kvm/img1@img1_snap1
一般来说父快照不可以删除,因为新镜像来自父快照。
如果想删除父快照保留克隆需要展平
1,展平子镜像
rbd flatten kvm/img2
2,取消父快照的保护
rbd snap unprotect kvm/img1@img1_snap1
3,删除父快照。
4,查看镜像
rbd ls --pool kvm -l
rbd使用:
安装ceph客户端包
创建一个可以访问rbd存储的用户
ceph auth get-or-create client.osd-mount osd “allow * pool=kvm” mon “allow r” > /etc/ceph/ceph.client.osd-mount.keyring
修改镜像特性,镜像默认只支持layering和striping特性。需关闭
rbd feature disable kvm/img1 object-map,fast-diff,deep-flatten
将ceph的配置文件以及密钥文件放到客户机(操作略)
在客户端安装ceph-common包
yum install ceph-common -y
执行客户端映射:
rbd map --pool kvm --image img1 --keyring /etc/ceph/ceph.client.osd-mount.keyring --user osd-mount
查看/断开映射
rbd showmapped
rbd unmap kvm/img1
格式化并挂载(略)
做快照还原注意:
1,卸载客户端断开映射
umount
rbd unmap kvm/img1
在服务端恢复快照
客户端重新映射
在线扩容
服务端:
1,rbd resize --pool kvm --image img1 --size 5G
客户端:
resize2fs /dev/rbd0 (ext4)
xfs_growfs /dev/rbd0 (xfs)
镜像导入导出:
导出:
rbd export kvm/img1 /tmp/kvm_img1_bak
导入:
rbd import /tmp/kvm_img1_bak kvm/img1
快照也可以导入导出,方法如上。
rgw对象存储:
三个方面:
1,用户 (user)
2,存储桶(bucket)
3,对象(object)
三者关系,user将object存储到存储系统的bucket上
存储桶属于某个用户并可以容纳对象,一个存储桶可以存储多个对象
同一个用户可以有多个存储桶,不同用户允许使用相同名字的存储桶,因此用户名可以作为存储桶的名称空间。
1,创建rgw守护进程,在任何节点创建。
ceph-deploy rgw create mon02 (在mon02上创建网关,注意单点故障问题。)
创建后会自动创建pool(如果定制rule则修改rule)
2,默认情况下,rgw监听7480端口,可以curl访问
更改rgw监听的端口:
打开ceph.cnf增加如下:
[client.rgw.mon02]
rgw_host = mon02
rgw_frontends = “civetweb port=8080 num_threads=500 request_timeout_ms=60000”
ceph-deploy --overwrite-conf config push mon01 mon02 mon03
重启服务:
systemctl restart ceph-radosgw.target
HTTPS配置
要在 civetweb 上启用 SSL ,首先你需要一个证书、它应该与提供 Ceph 对象网关服务的域名相对应。
下述操作均在rgw节点上进行
openssl genrsa -out civetweb.key 2048
openssl req -new -x509 -key civetweb.key -out civetweb.crt -days 3650 -subj “/CN=ip”
cat civetweb.key civetweb.crt > /etc/ceph/civetweb.pem
[client.rgw.mon02]
rgw_host = mon02
rgw_frontends = “civetweb port=80+443s ssl_certificate=/etc/ceph/civetweb.pem num_threads=500 request_timeout_ms=60000”
systemctl restart ceph-radosgw.target
netstat -an |grep 443
创建rgw的访问用户:
radosgw-admin user create --uid=“test” --display-name=“test user”
注意重要的是创建后生成的access_key 以及secret_key
“access_key”: “NX538HZTYL2BKS17G2Z9”,
“secret_key”: “0bFMErU1OjKXMLayi8PUVkxkecsAUWtNo8T4uSAl”
如果忘记,可用下面命令重新查看
radosgw-admin user info --uid=“test”
接口访问:
首先安装python模块:
pip install boto
脚本内容如下(感谢egon老师)
import ssl
import boto.s3.connection
from boto.s3.key import Key
try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
pass
else:
ssl._create_default_https_context = _create_unverified_https_context
access_key = “JNWYNAC82CJJLBPD9FHN”
secret_key = “syMOODODchFKX3IfpSpfFxLbq5ndukfDWUbHCNHT”
host = “ip”
port = 443 # 如果使用443端口,下述链接应设置is_secure=True
conn = boto.connect_s3(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
host=host,
port=port,
is_secure=True,
validate_certs=False,
calling_format=boto.s3.connection.OrdinaryCallingFormat()
)
conn.create_bucket(bucket_name=‘bucket01’)
conn.create_bucket(bucket_name=‘bucket02’)
bucket1 = conn.get_bucket(‘bucket01’)
bucket2 = conn.get_bucket(‘bucket02’)
exists = conn.lookup(‘bucket01’)
print(exists)
exists = conn.lookup(‘bucket02’)
print(exists)
print(list(bucket1.list()))
print(list(bucket2.list()))
bucket1 = conn.get_bucket(‘bucket01’)
key = Key(bucket=bucket1, name=‘myfile’) # name的值是数据的key
key.set_contents_from_filename(‘/tmp/egon.txt’)
print(key.get_contents_as_string()) # 读取s3中文件的内容,返回string即文件egon.txt的内容
bucket1 = conn.get_bucket(‘bucket01’) # 如果之前已经获取过对象,此处不需要重复获取
k = Key(bucket1)
k.key = ‘xxx’
k.set_contents_from_string(‘egon is happy’)
print(k.get_contents_as_string())
bucket1 = conn.get_bucket(‘bucket01’)
for key in bucket1:
key.delete()
bucket1.delete()
for bucket in conn:
for key in bucket:
print(key.name,key.get_contents_as_string())
bucket1 = conn.get_bucket(‘bucket01’)
res = bucket1.get_all_keys()
if len(res) > 0:
print(‘有文件’)
else:
print(‘为空’)
++++++++++++++++++++++++++++++++++++++++++++++++++++
分布式存储ceph之crush规则配置
目录
一 命令生成osd树形结构
二 crushmap信息介绍
三 修改 crushmap 信息
3.1 导出crush map
3.2 修改test.txt
3.3 把重新写的 ceph crush 导入 ceph 集群
3.4 修改现有存储池的crush_rule
3.5 查看集群状态
分布式存储ceph之crush规则配置
一 命令生成osd树形结构
ceph osd crush add-bucket datacenter0 datacenter
ceph osd crush add-bucket room0 room
ceph osd crush add-bucket rack0 rack
ceph osd crush add-bucket rack1 rack
ceph osd crush add-bucket rack2 rack
ceph osd crush move room0 datacenter=datacenter0
ceph osd crush move rack0 room=room0
ceph osd crush move rack1 room=room0
ceph osd crush move rack2 room=room0
ceph osd crush move osd01 datacenter=datacenter0 room=room0 rack=rack0
ceph osd crush move osd02 datacenter=datacenter0 room=room0 rack=rack1
ceph osd crush move osd03 datacenter=datacenter0 room=room0 rack=rack2
查看
[root@admin ~]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-9 0.17537 datacenter datacenter0
-10 0.17537 room room0
-11 0.05846 rack rack0
-3 0.05846 host osd01
0 hdd 0.01949 osd.0 up 1.00000 1.00000
1 hdd 0.01949 osd.1 up 1.00000 1.00000
2 hdd 0.01949 osd.2 up 1.00000 1.00000
-12 0.05846 rack rack1
-5 0.05846 host osd02
3 hdd 0.01949 osd.3 up 1.00000 1.00000
4 hdd 0.01949 osd.4 up 1.00000 1.00000
5 hdd 0.01949 osd.5 up 1.00000 1.00000
-13 0.05846 rack rack2
-7 0.05846 host osd03
6 hdd 0.01949 osd.6 up 1.00000 1.00000
7 hdd 0.01949 osd.7 up 1.00000 1.00000
8 hdd 0.01949 osd.8 up 1.00000 1.00000
-1 0 root default
二 crushmap信息介绍
我们可以通过命令导出集群当前的crushmap信息
ceph osd getcrushmap -o test.bin
crushtool -d test.bin -o test.txt
crushmap配置中最核心的当属rule了,crush rule决定了三点重要事项:
1、从OSDMap中的哪个节点开始查找
2、使用那个节点作为故障隔离域
3、定位副本的搜索模式(广度优先 or 深度优先)。
rule egon_ruleset #规则集的命名,创建pool时可以指定rule集
{
id 1 #rules集的编号,顺序编即可
type replicated #定义pool类型为replicated(还有esurecode模式)
min_size 1 #pool中最小指定的副本数量不能小于1
max_size 10 #pool中最大指定的副本数量不能大于10
step take default #定义pg查找副本的入口点
step chooseleaf firstn 0 type host #选叶子节点、深度优先、隔离host
step emit #结束
}
总结
pg 选择osd的过程,首先要知道在rules中 指明从osdmap中哪个节点开始查找,入口点默认为default也就是root节点,
然后隔离域为host节点(也就是同一个host下面不能选择两个子节点)。由default到3个host的选择过程,
这里由default根据节点的bucket类型选择下一个子节点,由子节点再根据本身的类型继续选择,直到选择到host,然后在host下选择一个osd。
三 修改 crushmap 信息
对于比较熟的 crush 配置比较熟悉的老手推荐使用, 线上业务集群慎用。
3.1 导出crush map
把 ceph 的二进制格式的 crush map 导出并转换为文本格式
ceph osd getcrushmap -o test.bin
crushtool -d test.bin -o test.txt
3.2 修改test.txt
以容量为指标,设置weight值:推荐以1TB为基数,设置weight值为1.0。这样500G的则为0.5,3TB则为3.0.
以性能为指标,设置weight值:比如性能好些的盘,weight设置为1.2,性能差些的weight设置为0.8,
bucket 节点Weight为下级items weight之和
参考设置
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 50
tunable chooseleaf_descend_once 1
tunable chooseleaf_vary_r 1
tunable chooseleaf_stable 1
tunable straw_calc_version 1
tunable allowed_bucket_algs 54
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd
device 3 osd.3 class hdd
device 4 osd.4 class hdd
device 5 osd.5 class hdd
device 6 osd.6 class hdd
device 7 osd.7 class hdd
device 8 osd.8 class hdd
type 0 osd # 硬盘
type 1 host # 服务器
type 2 chassis # 机箱
type 3 rack # 机架(一个机架包含多个机箱)
type 4 row # 机排
type 5 pdu # 配电单元(有可能多个机排共用一个配电单元)
type 6 pod # 多个机排
type 7 room # 机房
type 8 datacenter # 数据中心(有可能多个机房组成一个数据中心)
type 9 region # 区域(华东1,华东2等)
type 10 root # 最顶级,必须存在 注意:这些故障域也称之为Bucket,但有些Bucket非radowsgw里面的bucket。
root default {
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
# weight 0.000
alg straw2
hash 0 # rjenkins1
}
host osd01 {
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd.0 weight 1.000
item osd.1 weight 1.000
item osd.2 weight 1.000
}
host osd02 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd.3 weight 1.000
item osd.4 weight 1.000
item osd.5 weight 1.000
}
host osd03 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd.6 weight 1.000
item osd.7 weight 1.000
item osd.8 weight 1.000
}
rack rack0 {
id -11 # do not change unnecessarily
id -16 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd01 weight 3.000
}
rack rack1 {
id -12 # do not change unnecessarily
id -15 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd02 weight 3.000
}
rack rack2 {
id -13 # do not change unnecessarily
id -14 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd03 weight 3.000
}
room room0 {
id -10 # do not change unnecessarily
id -17 class hdd # do not change unnecessarily
# weight 0.175
alg straw2
hash 0 # rjenkins1
item rack0 weight 3.000
item rack1 weight 3.000
item rack2 weight 3.000
}
datacenter datacenter0 {
id -9 # do not change unnecessarily
id -18 class hdd # do not change unnecessarily
# weight 0.175
alg straw2
hash 0 # rjenkins1
item room0 weight 9.000
}
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}
rule egon_rule { # 规则集的命名,创建pool时可以指定rule集
id 1 # id设置为1
type replicated # 定义pool类型为replicated(还有esurecode模式)
min_size 1 # pool中最小指定的副本数量不能小1
max_size 10 # pool中最大指定的副本数量不能大于10
step take datacenter0 # 定义pg查找副本的入口点
step chooseleaf firstn 0 type host # 深度优先、隔离默认为host,设置为host
step emit # 结束
}
3.3 把重新写的 ceph crush 导入 ceph 集群
crushtool -c test.txt -o new.bin
ceph osd setcrushmap -i new.bin
3.4 修改现有存储池的crush_rule
重新导入集群后,需要把之前存在过的pool池的crush_rule都修一下,否则集群会出现unknown状态有无法达到activee+clean状态
ceph osd pool set cephfs_data crush_rule egon_rule
ceph osd pool set cephfs_metadata crush_rule egon_rule
ceph osd pool set egon_test crush_rule egon_rule
3.5 查看集群状态
ceph osd dump # 发现使用的crush_rule的id变为1
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
分布式存储ceph运维操作
一 统一节点上ceph.conf文件
二 ceph集群服务管理
2.1 方式一
2.2 方式二
三 服务平滑重启
3.1 tell子命令
3.2 daemon子命令
3.3 socket文件
四 维护集群常用命令
4.1 查看集群健康状况
4.2 检查集群的使用情况
4.3 mds相关
4.4 mon相关
4.5 auth相关
4.6 osd相关
4.7 pool相关
4.8 PG相关
4.9 rados命令相关
五 osd相关之osd故障模拟与恢复
5.1 模拟盘坏掉
5.2 将坏盘踢出集群
5.3 把原来坏掉的osd修复后重新加入集群
六 在物理节点上新增osd daemon
七 osd节点关机维护
八 升级ceph软件版本
九 扩容
十 Ceph monitor故障恢复
十一 Cephfs快照
分布式存储ceph运维操作
一 统一节点上ceph.conf文件
如果是在admin节点修改的ceph.conf,想推送到所有其他节点,则需要执行下述命令
ceph-deploy --overwrite-conf config push mon01 mon02 mon03 osd01 osd02 osd03
修改完毕配置文件后需要重启服务生效,请看下一小节
二 ceph集群服务管理
@@@!!!下述操作均需要在具体运行服务的那个节点上运行,而不是admin节点!!!@@@
2.1 方式一
在各具体节点执行下行命令,重启节点上的所有ceph守护进程
systemctl restart ceph.target
2.2 方式二
在各具体节点执行下行命令,按类型重启相应的守护进程
systemctl restart ceph-mgr.target
systemctl restart ceph-mds.target
systemctl restart ceph-radosgw.target
systemctl restart ceph-mon.target
登录到osd01节点上,该节点上运行有三个osd daemon进程osd.0、osd.l、osd.2
systemctl restart ceph-osd.target
systemctl restart ceph-osd@0
systemctl restart ceph-osd@1
systemctl restart ceph-osd@2
了解:也可以根据进程类型+主机名.service
systemctl { start | stop | restart} ceph-mon@{mon_instance}.service
例
systemctl restart [email protected]
systemctl { start | stop | restart} ceph-mgr@{mgr_instance}.service
systemctl { start | stop | restart} ceph-osd@{osd_instance}.service
systemctl { start | stop | restart} ceph-radosgw@{rgw_instance}.service
systemctl { start | stop | restart} ceph-mds@{mds_instance}.service
三 服务平滑重启
有时候需要更改服务的配置,但不想重启服务,或者是临时修改,此时我们就可以通过admin sockets直接与守护进程交互。如查看和修改守护进程的配置参数。
守护进程的socket文件一般是/var/run/ceph/ c l u s t e r − cluster- cluster−type.$id.asok
基于admin sockets的操作:
方式一:tell子命令
方式二:daemon子命令
ceph daemon t y p e . type. type.id command
方式三:通过socket文件
ceph --admin-daemon /var/run/ceph/ c l u s t e r − cluster- cluster−type.$id.asok command
常用command如下
help
config get parameter
config set parameter
config show
perf dump
3.1 tell子命令
命令使用格式如下,在管理节点执行即可
ceph tell {daemon-type}.{daemon id or } injectargs --{name}={value} [–{name}={value}]
daemon-type:为要操作的对象类型如osd、mon等。
daemon id:该对象的名称,osd通常为0、1等,mon为ceph -s显示的名称,这里可以输入表示全部。
injectargs:表示参数注入,后面必须跟一个参数,也可以跟多个。
例如
ceph tell mon.mon01 injectargs --mon_allow_pool_delete=true
ceph tell mon.* injectargs --mon_allow_pool_delete=true
mon_allow_pool_delete此选项的值默认为false,表示不允许删除pool,只有此选项打开后方可删除,记得改回去!!! 这里使用mon.ceph-monitor-1表示只对ceph-monitor-1设置,可以使用*
3.2 daemon子命令
命令格式如下,需要登录到守护进程所在的那台主机上执行
ceph daemon {daemon-type}.{id} config set {name}={value}
例。
ssh root@mon01
ceph daemon mon.mon01 config set mon_allow_pool_delete false
3.3 socket文件
ceph --admin-daemon /var/run/ceph/ceph-mds.mon01.asok help
ceph --admin-daemon /var/run/ceph/ceph-mds.mon01.asok config get mon_allow_pool_delete
ceph --admin-daemon /var/run/ceph/ceph-mds.mon01.asok config set mon_allow_pool_delete true
如果超过半数的monitor节点挂掉,此时通过网络访问ceph的所有操作都会被阻塞,但monitor的本地socket还是可以通信的。
ceph --admin-daemon /var/run/ceph/ceph-mon.mon03.asok quorum_status
四 维护集群常用命令
4.1 查看集群健康状况
ceph -s
ceph status
ceph health
ceph health detail
ceph -w
4.2 检查集群的使用情况
=命令1=
ceph df # 它和 Linux 上的 df 相似
展示了数据所占用集群存储空间的概要,详解如下
SIZE: 集群的总容量;
AVAIL: 集群的空闲空间总量;
RAW USED: 已用存储空间总量;
% RAW USED: 已用存储空间比率。用此值参照 full ratio 和 near full \ ratio 来确保不会用尽集群空间。 详情见存储容量。
展示了存储池列表及各存储池的大致使用率。没有副本、克隆品和快照占用情况。例如,如果你 把 1MB 的数据存储为对象,理论使用率将是 1MB ,但考虑到副本数、克隆数、和快照数,实际使用率可能是 2MB 或更多。
NAME: 存储池名字;
ID: 存储池唯一标识符;
USED: 大概数据量,单位为 B、KB、MB 或 GB ;
%USED: 各存储池的大概使用率;
Objects: 各存储池内的大概对象数。
=命令2=
ceph osd df # 可以详细列出集群每块磁盘的使用情况,包括大小、权重、使用多少空间、使用率等等
4.3 mds相关
1、查看mds状态
ceph mds stat
ceph mds dump
2、删除mds节点
ssh root@mon01 systemctl stop ceph-mds.target
ceph mds rm 0 # 删除一个不活跃的mds
3、关闭mds集群
ceph mds cluster_down
4、开启mds集群
ceph mds cluster_up
5、设置cephfs 文件系统存储方式最大单个文件尺寸
ceph mds set max_file_size 1024000000000
6、了解:清除mds文件系统
ceph mds fail 0
ceph fs rm cephfs --yes-i-really-mean-it
ceph osd pool delete cephfs_data cephfs_data --yes-i-really-really-mean-it
ceph osd pool delete cephfs_metadata cephfs_metadata --yes-i-really-really-mean-it
ceph mds rm 0
4.4 mon相关
1、查看mon状态
ceph mon stat
2、查看mon映射信息
ceph mon dump
3、检查Ceph monitor仲裁/选举状态
ceph quorum_status --format json-pretty
4、查看mon信息包括ip地址
获得一个正在运行的 mon map,并保存在 1.txt 文件中
ceph mon getmap -o 1.txt
monmaptool --print 1.txt
4.5 auth相关
一:认证与授权
Ceph使用cephx协议对客户端进行身份验证,集群中每一个Monitor节点都可以对客户端进行身份验证,所以不存在单点故障。cephx仅用于Ceph集群中的各组件,而不能用于非Ceph组件。它并不解决数据传输加密问题,但也可以提高访问控制安全性问题。
二:认证授权流程如下
1、客户端向Monitor请求创建用户。
2、Monitor返回用户共享密钥给客户端,并将此用户信息共享给MDS和OSD。
3、客户端使用此共享密钥向Monitor进行认证。
4、Monitor返回一个session key给客户端,并且此session key与对应客户端密钥进行加密。此session key过一段时间后就会失效,需要重新请求。
5、客户端对此session key进行解密,如果密钥不匹配无法解密,这时候认证失败。
6、如果认证成功,客户端向服务器申请访问的令牌。
7、服务端返回令牌给客户端。
8、这时候客户端就可以拿着令牌访问到MDS和OSD,并进行数据的交互。因为MDS和Monitor之间有共享此用户的信息,所以当客户端拿到令牌后就可以直接访问。
三:相关概念
1、用户
用户通常指定个人或某个应用
个人就是指定实际的人,比如管理员
而应用就是指客户端或Ceph集群中的某个组件,通过用户可以控制谁可以如何访问Ceph集群中的哪块数据。
Ceph支持多种类型的用户,个人与某应用都属于client类型。还有mds、osd、mgr一些专用类型。
2、用户标识
用户标识由“TYPE.ID”组成,通常ID也代表用户名,如client.admin、osd.1等。
3、使能caps
使能表示用户可以行使的能力,通俗点也可以理解为用户所拥有的权限。 对于不同的对象所能使用的权限也不一样,大致如下所示。
Monitor权限有:r、w、x和allow、profile、cap。
OSD权限有:r、w、x、class-read、class-wirte和profile osd。
另外OSD还可以指定单个存储池或者名称空间,如果不指定存储池,默认为整个存储池。
MDS权限有:allow或者留空。
allow:对mds表示rw的意思,其它的表示“允许”。
r:读取。
w:写入。
x:同时拥有读取和写入,相当于可以调用类方法,并且可以在monitor上面执行auth操作。
class-read:可以读取类方法,x的子集。
class-wirte:可以调用类方法,x的子集。
*:这个比较特殊,代表指定对象的所有权限。
profile:类似于Linux下sudo,比如profile osd表示授予用户以某个osd身份连接到其它OSD或者Monitor的权限。
profile bootstrap-osd表示授予用户引导OSD的权限,关于此处可查阅更多资料。
四 命令
1、查看 ceph 集群中的认证用户及相关的 key
ceph auth list # 简写:ceph auth ls
2、查看某一用户详细信息
ceph auth get client.admin
3、只查看用户的key信息
ceph auth print-key client.admin
4、创建用户,用户标识为client.test。指定该用户对mon有r的权限,对osd有rw的权限,osd没有指定存储池,所以是对所有存储池都有rw的权限。在创建用户的时候还会自动创建用户的密钥。
ceph auth add client.test mon “allow r” osd “allow rw”
5、修改用户权限
ceph auth caps client.test mon “allow r” osd “allow rw pool=kvm”
6、删除用户,用户名为osd.0
ceph auth del osd.0
7、keyring秘钥环文件
keyring文件是一个包含密码,key,证书等内容的一个集合。一个keyring文件可以包含多个用户的信息,也就是可以将多个用户信息存储到一个keyring文件。
keyring自动加载顺序
当访问Ceph集群时候默认会从以下四个地方加载keyring文件。
/etc/ceph/cluster-name.user-name.keyring:通过这种类型的文件用来保存单个用户信息,文件名格式固定:集群名.用户标识.keyring。如ceph.client.admin.keyring。这个代表ceph这个集群,这里的ceph是集群名,而client.admin为admin用户的标识。
/etc/ceph/cluster.keyring:通用来保存多个用户的keyring信息。
/etc/ceph/keyring:也用来保存多个用户的keyring信息。
/etc/ceph/keyring.bin:二进制keyring文件,也用来保存多个用户的keyring信息。
8、创建一个名为client.admin 的用户,设置好用户对mds、osd、mon的权限,然后把密钥导出到文件中
ceph auth get-or-create client.admin mds ‘allow *’ osd ‘allow *’ mon ‘allow *’ > /etc/ceph/ceph.client.admin.keyring1
ceph auth get-or-create client.admin mds ‘allow *’ osd ‘allow *’ mon ‘allow *’ -o /etc/ceph/ceph.client.admin.keyring1
9、创建一个名为osd.0 的用户,设置好用户对mon、osd的权限,然后把密钥导出到文件中
ceph auth get-or-create osd.0 mon ‘allow profile osd’ osd ‘allow *’ -o /var/lib/ceph/osd/ceph-0/keyring
10、创建一个名为mds.nc3 的用户,设置好用户对mon、osd、mds的权限,然后把密钥导出到文件中
ceph auth get-or-create mds.nc3 mon ‘allow rwx’ osd ‘allow *’ mds ‘allow *’ -o /var/lib/ceph/mds/ceph-cs1/keyring
4.6 osd相关
1、查看osd状态
ceph osd stat
2、查看osd树
ceph osd tree查看
ceph osd ls-tree rack1 # 查看osd tree中rack1下的osd编号
3、查看osd映射信息
ceph osd dump
4、查看数据延迟
ceph osd perf
5、查看CRUSH map
ceph osd crush dump
6、查看与设置最大 osd daemon 的个数
[root@admin ~]# ceph osd getmaxosd
max_osd = 12 in epoch 379
ceph osd setmaxosd 2048
7、设置 osd 的权重
ceph osd reweight 3 0.5 # 把osd.3的权重改为0.5
8、暂停 osd (暂停后整个ceph集群不再接收数据)
ceph osd pause # 暂停的是所有的osd
9、再次开启 osd (开启后再次接收数据)
ceph osd unpause
10、设置标志 flags ,不允许关闭 osd、解决网络不稳定,osd 状态不断切换的问题
ceph osd set nodown
取消设置
ceph osd unset nodown
4.7 pool相关
1、创建存储池
pool name:存储池名称,必须唯一。
pg num:存储池中的pg数量。
pgp num:用于归置的pg数量,默认与pg数量相等。
type:指定存储池的类型,有replicated和erasure, 默认为replicated。
ceph osd pool create egon_test 32 32 # 生路type,默认为replicated
2、修改存储池的pg数
注意:在更改pool的PG数量时,需同时更改PGP的数量。PGP是为了管理placement而存在的专门的PG,它和PG的数量应该保持一致。如果你增加pool的pg_num,就需要同时增加pgp_num,保持它们大小一致,这样集群才能正常rebalancing。
ceph osd pool set egon_test pg_num 60
ceph osd pool set egon_test pgp_num 60
3、查看存储池
ceph osd lspools
ceph osd pool ls
ceph osd pool ls detail
ceph osd pool stats
4、重命名
ceph osd pool rename
5、在集群中删除一个 pool,注意删除 poolpool 映射的 image 会直接被删除,线上操作要谨慎
存储池的名字需要重复两次
ceph osd pool delete tom_test tom_test --yes-i-really-really-mean-it
Error EPERM: pool deletion is disabled; you must first set the mon_allow_pool_delete config option to true before you can destroy a pool
这是由于没有配置mon节点的 mon_allow_pool_delete 字段所致,解决办法就是到mon节点进行相应的设置。
解决方案:
ceph tell mon.* injectargs --mon_allow_pool_delete=true
ceph osd pool delete tom_test tom_test --yes-i-really-really-mean-it
删除完成后最好把mon_allow_pool_delete改回去,降低误删的风险
如果是测试环境,想随意删除存储池,可以在配置文件中全局开启删除存储池的功能
在配置文件中添加如下内容:
[mon]
mon allow pool delete = true
ceph-deploy --overwrite-conf config push mon01 mon02 mon03 osd01 osd02 osd03
systemctl restart ceph-mon.target
6、为一个 ceph pool 配置配额、达到配额前集群会告警,达到上限后无法再写入数据
当我们有很多存储池的时候,有些作为公共存储池,这时候就有必要为这些存储池做一些配额,限制可存放的文件数,或者空间大小,以免无限的增大影响到集群的正常运行。 设置配额。
ceph osd pool get-quota {pool_name}
ceph osd pool set-quota {pool_name} max_objects {number}
ceph osd pool set-quota {pool_name} max_bytes {number}
ceph osd pool set-quota egon_test max_bytes 1000000000
7、配置参数
对于存储池的配置参数可以通过下面命令获取。
ceph osd pool get [key name]
如
ceph osd pool get size
如果不跟个key名称,会输出所有参数,但有个报错。
ceph osd pool set
如
ceph osd pool set egon_test min_size 1
ceph osd pool set egon_test size 2
常用的可用配置参数有。
size:存储池中的对象副本数
min_size:提供服务所需要的最小副本数,如果定义size为3,min_size也为3,坏掉一个OSD,如果pool池中有副本在此块OSD上面,那么此pool将不提供服务,如果将min_size定义为2,那么还可以提供服务,如果提供为1,表示只要有一块副本都提供服务。
pg_num:定义PG的数量
pgp_num:定义归置时使用的PG数量
crush_ruleset:设置crush算法规则
nodelete:控制是否可删除,默认可以
nopgchange:控制是否可更改存储池的pg num和pgp num
nosizechange:控制是否可以更改存储池的大小
noscrub和nodeep-scrub:控制是否整理或深层整理存储池,可临时解决高I/O问题
scrub_min_interval:集群负载较低时整理存储池的最小时间间隔
scrub_max_interval:整理存储池的最大时间间隔
8、快照
创建存储池快照需要大量的存储空间,取决于存储池的大小。 创建快照,以下两条命令都可以 。
ceph osd pool mksnap
rados -p mksnap
列出快照。
rados -p lssnap
回滚至存储池快照。
rados -p rollback # 只能回复某个对象
删除存储池快照,以下两条命令都可以删除。
ceph osd pool rmsnap
rados -p rmsnap
提示
Pool池的快照,相对来说是有局限性的,没办法直接恢复快照里边全部object对象文件,只能一个个来恢复,保存点密码文件应该还是可以的。这样的设计效果,猜测有可能是因为如果pool池直接整体恢复,会导致整个ceph集群数据混乱,毕竟集群中数据是分布式存放的!
pool存储池快照功能了解即可,感兴趣详见《附录5:》
9、压缩
如果使用bulestore存储引擎,默认提供数据压缩,以节约磁盘空间。 启用压缩。
ceph osd pool set compression_algorithm snappy
snappy:压缩使用的算法,还有有none、zlib、lz4、zstd和snappy等算法。默认为sanppy。zstd压缩比好,但消耗CPU,lz4和snappy对CPU占用较低,不建议使用zlib。
ceph osd pool set compression_mode aggressive
ceph osd pool set egon_test compression_mode aggressive
压缩的模式有none、aggressive、passive和force
默认none。表示不压缩
passive表示提示COMPRESSIBLE才压缩
aggressive表示提示INCOMPRESSIBLE不压缩,其它都压缩
force表示始终压缩。 压缩参数。
参数:
compression_max_blob_size:压缩对象的最大体积,超过此体积不压缩。默认为0。
compression_min_blob_size:压缩对象的最小体积,小于此体积不压缩。默认为0。 全局压缩选项,这些可以配置到ceph.conf配置文件,作用于所有存储池。
bluestore_compression_algorithm
bluestore_compression_mode
bluestore_compression_required_ratio
bluestore_compression_min_blob_size
bluestore_compression_max_blob_size
bluestore_compression_min_blob_size_ssd
bluestore_compression_max_blob_size_ssd
bluestore_compression_min_blob_size_hdd
bluestore_compression_max_blob_size_hdd
4.8 PG相关
1、查看pg组映射信息
ceph pg dump # 或 ceph pg ls
2、查看pg信息的脚本,第一个行为pool的id号
ceph pg dump | awk ’
BEGIN { IGNORECASE = 1 }
/^PG_STAT/ { col=1; while($col!=“UP”) {col++}; col++ }
/5+.[0-9a-f]+/ { match($0,/6+/); pool=substr( 0 , R S T A R T , R L E N G T H ) ; p o o l l i s t [ p o o l ] = 0 ; u p = 0, RSTART, RLENGTH); poollist[pool]=0; up= 0,RSTART,RLENGTH);poollist[pool]=0;up=col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
printf(“\n”);
printf(“pool :\t”); for (i in poollist) printf(“%s\t”,i); printf(“| SUM \n”);
for (i in poollist) printf(“--------”); printf(“----------------\n”);
for (i in osdlist) { printf(“osd.%i\t”, i); sum=0;
for (j in poollist) { printf(“%i\t”, array[i,j]); sum+=array[i,j]; sumpool[j]+=array[i,j] }; printf(“| %i\n”,sum) }
for (i in poollist) printf(“--------”); printf(“----------------\n”);
printf(“SUM :\t”); for (i in poollist) printf(“%s\t”,sumpool[i]); printf(“|\n”);
}’
3、查看pg状态
ceph pg stat
4、查看一个pg的map
ceph pg map 1.7b
5、查询一个pg的详细信息
ceph pg 1.7b query
6、清理一个pg组
ceph pg scrub 1.7b
7、查看pg中stuck(卡住)的状态
ceph pg dump_stuck unclean
ceph pg dump_stuck inactive
ceph pg dump_stuck stale
Unclean (不干净)
归置组含有复制数未达到期望数量的对象,它们应该在恢复中。
Inactive (不活跃) 归置组不能处理读写,因为它们在等待一个有最新数据的 OSD 复活且进入集群。
Stale (不新鲜)
归置组处于未知状态,即存储它们的 OSD 有段时间没向监视器报告了(由 mon_osd_report_timeout 配置)。 阀值定义的是,归置组被认为卡住前等待的最小时间(默认 300 秒)
8、显示一个集群中的所有的 pg 统计
ceph pg dump --format plain # 可用格式有 plain (默认)和 json 。
9、查看某个 PG 内分布的数据状态,具体状态可以使用选项过滤输出
ceph pg ls 17 clean # 17为pg的编号
10、查询 osd 包含 pg 的信息,过滤输出 pg 的状态信息
ceph pg ls-by-osd osd.5
11、查询 pool 包含 pg 的信息,过滤输出 pg 的状态信息
ceph pg ls-by-pool egon_test
12、查询某个 osd 状态为 primary pg ,可以根据需要过滤状态
ceph pg ls-by-primary osd.3 clean
13、恢复一个丢失的pg
如果集群丢了一个或多个对象,而且必须放弃搜索这些数据,你就要把未找到的对象标记为丢失( lost )。 如果所有可能的位置都查询过了,而仍找不到这些对象,你也许得放弃它们了。这可能是罕见的失败组合导致的, 集群在写入完成前,未能得知写入是否已执行。
当前只支持 revert 选项,它使得回滚到对象的前一个版本(如果它是新对象)或完全忽略它。要把 unfound 对象 标记为 lost ,执行命令:
ceph pg {pg-id} mark_unfound_lost revert|delete
4.9 rados命令相关
rados 是和 Ceph 的对象存储集群(RADOS),Ceph 的分布式文件系统的一部分进行交互是一种实用工具。
1、看 ceph 集群中有多少个 pool (只是查看 pool)
rados lspools # 同 ceph osd pool ls 输出结果一致
2、显示整个系统和被池毁掉的使用率统计,包括磁盘使用(字节)和对象计数
rados df
3、创建一个 pool
rados mkpool test
ceph osd pool set test crush_rule egon_rule # 修改crush_rule为egon_rule
4、创建一个对象
rados create test-object -p test # 创建时卡住了,看看新建的存储池的crush_rule是否正确
5、上传一个对象
rados -p test put xxx /tmp/egon.txt
6、查看 ceph pool 中的 ceph object (这里的 object 是以块形式存储的)
rados ls -p test
7、删除一个对象
rados rm test-object -p test
8 、删除存储池以及它包含的所有数据
rados rmpool test test --yes-i-really-really-mean-it
9、为存储池创建快照
rados -p test mksnap testsnap
10、列出给定池的快照
rados -p test lssnap
11、删除快照
rados -p test rmsnap testsnap
12、使用 rados 进行性能测试!!!!!!!!!!!!!!!!!!!
rados bench 600 write rand -t 100 -b 4K -p egon_test
选项解释:
测试时间 :600
支持测试类型:write/read ,加 rand 就是随机,不加就是顺序
并发数( -t 选项):100
pool 的名字是:egon_test
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
五 osd相关之osd故障模拟与恢复
5.1 模拟盘坏掉
如果ceph集群有上千个osd daemon,每天坏个2-3块盘太正常了,我们可以模拟down 掉一个 osd 硬盘
ssh root@osd01 systemctl stop ceph-osd@0
ceph osd down 0
5.2 将坏盘踢出集群
集群中坏掉一块盘后,我们需要将其踢出集群让集群恢复到active+clean状态
方法一=
ssh root@osd01 systemctl stop ceph-osd@0 # 一定要到具体的节点上关闭
ceph osd down 0
ceph osd out osd.0
ceph osd crush remove osd.0
ceph auth rm osd.0
ceph osd rm osd.0
方法二=
ssh root@osd02 systemctl stop ceph-osd@3 # 一定要到具体的节点上关闭
ceph osd out osd.3
ceph osd purge osd.3 --yes-i-really-mean-it # 综合这一步,就可以完成操作
5.3 把原来坏掉的osd修复后重新加入集群
ssh root@osd01
cd /etc/ceph
ceph osd create
ceph-authtool --create-keyring /etc/ceph/ceph.osd.0.keyring --gen-key -n osd.0 --cap mon ‘allow profile osd’ --cap mgr ‘allow profile osd’ --cap osd ‘allow *’
ceph auth import -i /etc/ceph/ceph.osd.0.keyring
ceph auth get-or-create osd.0 -o /var/lib/ceph/osd/ceph-0/keyring
ceph osd crush add osd.0 0.01900 host=osd01
ceph osd in osd.0
systemctl restart ceph-osd@0
ps:如果重启失败
报错:
Job for [email protected] failed because start of the service was attempted too often. See “systemctl status [email protected]” and “journalctl -xe” for details.
To force a start use “systemctl reset-failed [email protected]” followed by “systemctl start [email protected]” again.
systemctl reset-failed [email protected] systemctl start [email protected]
systemctl start ceph-osd@3
六 在物理节点上新增osd daemon
在osd01节点上添加新的osd daemon
parted -s /dev/sdi mklabel gpt
parted -s /dev/sdi mkpart primary 0% 50%
parted -s /dev/sdi mkpart primary 51% 100%
cd /etc/ceph
ceph-deploy --overwrite-conf osd create osd01 --data /dev/sdh --block-db /dev/sdi1 --block-wal /dev/sdi2
ceph osd crush add osd.9 0.01900 host=osd01
如果是在其他节点,例如mon03节点上添加osd daemon
!!!切记切记切记切记切记切记要为mon03节点添加一个cluster network!!!
parted -s /dev/sdc mklabel gpt
parted -s /dev/sdc mkpart primary 0% 50%
parted -s /dev/sdc mkpart primary 51% 100%
cd /etc/ceph
ceph-deploy --overwrite-conf osd create mon03 --data /dev/sdb --block-db /dev/sdc1 --block-wal /dev/sdc2
ceph osd crush add-bucket mon03 host
ceph osd crush add osd.10 0.01900 host=mon03
ceph osd crush move mon03 rack=rack1
ceph osd in osd.10
ps: 如果报错,磁盘发现gp信息
那么先清理磁盘
ceph-disk zap /dev/sdb # dd if=/dev/zero of=/dev/sdb bs=512 count=1
ceph-disk zap /dev/sdc
然后重新执行上述步骤
注意
在OSD添加或移除时,Ceph会重平衡PG。数据回填和恢复操作可能会产生大量的后端流量,影响集群性能。为避免性能降低,可对回填/恢复操作进行配置:
osd_recovery_op_priority # 值为1-63,默认为10,相对于客户端操作,恢复操作的优先级,默认客户端操作的优先级为63,参数为osd_client_op_priority
osd_recovery_max_active # 每个osd一次处理的活跃恢复请求数量,默认为15,增大此值可加速恢复,但会增加集群负载
osd_recovery_threads # 用于数据恢复时的线程数,默认为1
osd_max_backfills # 单个osd的最大回填操作数,默认为10
osd_backfill_scan_min # 回填操作时最小扫描对象数量,默认为64
osd_backfill_scan_max # 回填操作的最大扫描对象数量,默认为512
osd_backfill_full_ratio # osd的占满率达到多少时,拒绝接受回填请求,默认为0.85
osd_backfill_retry_interval # 回填重试的时间间隔
七 osd节点关机维护
你可能需要定期对集群中某个子网进行例行维护,或者要解决某个域内的问题。当你停止OSD时,默认情况下CRUSH机制会对集群自动重平衡,可将集群设为noout状态来关闭自动重平衡:
ceph osd set noout
ceph osd down 编号 # 分别把该节点上的osd设置为down状态
systemctl stop ceph-osd.target # stop该节点上的所有osd进程
shutdown -h now
当你对失败域中OSD维护时,其中的PG将会变为degraded状态。
systemctl start ceph-osd.target
ceph osd unset noout
八 升级ceph软件版本
在MON和OSD机器上升级安装指定的ceph版本的软件包
逐个重启MON进程
设置noout 避免在异常情况下触发集群数据重新平衡
ceph osd set noout
逐个重启OSD进程
ceph osd down {osd-number} #提前mark down, 减少slow request
systemctl restart ceph-osd@{osd-number} #用systemctl重启OSD进程
恢复noout 设置
ceph osd unset noout
九 扩容
如果副本数为2,PB级的集群的容量超过50%,就要考虑扩容了。 假如OSD主机的磁盘容量为48TB(12*4TB),则需要backfill的数据为24TB(48TB 50%) ,假设网卡为10Gb,则新加一个OSD时,集群大约需要19200s(24TB/(10Gb/8)) 约3小时完成backfill,而backfill后台数据填充将会涉及大量的IO读和网络传输,必将影响生产业务运行。 如果集群容量到80%再扩容会导致更长的backfill时间,近8个小时。
OSD对应的磁盘利用率如果超过50%,也需要尽快扩容。
在业务闲时扩容
十 Ceph monitor故障恢复
1 问题
一般来说,在实际运行中,ceph monitor的个数是2n+1(n>=0)个,在线上至少3个,只要正常的节点数>=n+1,ceph的paxos算法能保证系统的正常运行。所以,对于3个节点,同时只能挂掉一个。一般来说,同时挂掉2个节点的概率比较小,但是万一挂掉2个呢?
如果ceph的monitor节点超过半数挂掉,paxos算法就无法正常进行仲裁(quorum),此时,ceph集群会阻塞对集群的操作,直到超过半数的monitor节点恢复。
If there are not enough monitors to form a quorum, the ceph command will block trying to reach the cluster. In this situation, you need to get enough ceph-mon daemons running to form a quorum before doing anything else with the cluster.
所以,
(1)如果挂掉的2个节点至少有一个可以恢复,也就是monitor的元数据还是OK的,那么只需要重启ceph-mon进程即可。所以,对于monitor,最好运行在RAID的机器上。这样,即使机器出现故障,恢复也比较容易。
(2)如果挂掉的2个节点的元数据都损坏了呢?出现这种情况,说明人品不行,2台机器的RAID磁盘同时损坏,这得多背?肯定是管理员嫌工资太低,把机器砸了。如何恢复呢?
详见:https://www.cnblogs.com/linhaifeng/articles/14761126.html
十一 Cephfs快照
Cephfs的快照功能在官网都很少提及,因为即使开发了很多年,但是由于cephfs的复杂性,功能一直没能达到稳定,这里,只是介绍一下这个功能,怎么使用,并且建议不要在生产中使用,因为搞不好是会丢数据的
1、使能cephfs可以做快照:
ceph fs set ceph allow_new_snaps 1
2.在要做快照的目录下执行:
mkdir .snap/{snapname}
3、查看快照中的内容:
ls .snap/{snapname}
4、恢复:
cp -R .snap/{snapname}/* ./
0-9a-f ↩︎
0-9a-f ↩︎
0-9a-f ↩︎
0-9a-f ↩︎
0-9a-f ↩︎
0-9a-f ↩︎