Ceph安装教程
本文最后更新于 435 天前,其中的信息可能已经有所发展或是发生改变。

Ceph笔记

0,架构介绍

注意本资料来源于这个地址:https://docs.ceph.com/en/latest/start/intro/

0.1 Ceph 架构

img

0.1.1 Ceph 接口

Ceph 支持三种接口:

Object:有原生的API,而且也兼容 Swift 和 S3 的 API
Block:支持精简配置、快照、克隆
File:Posix 接口,支持快照

0.1.2 名词介绍

Ceph 核心组件及概念介绍

Monitor:一个 Ceph 集群需要多个 Monitor 组成的小集群,它们通过 Paxos 同步数据,用来保存 OSD 的元数据。
OSD:OSD 全称 Object Storage Device,也就是负责响应客户端请求返回具体数据的进程,一个Ceph集群一般有很多个OSD。
CRUSH:CRUSH 是 Ceph 使用的数据分布算法,类似一致性哈希,让数据分配到预期的位置。
PG:PG全称 Placement Groups,是一个逻辑的概念,一个PG 包含多个 OSD 。引入 PG 这一层其实是为了更好的分配数据和定位数据。
Object:Ceph 最底层的存储单元是 Object对象,每个 Object 包含元数据和原始数据。
RADOS:实现数据分配、Failover 等集群操作。
Libradio:Libradio 是RADOS提供库,因为 RADOS 是协议,很难直接访问,因此上层的 RBD、RGW和CephFS都是通过libradios访问的,目前提供 PHP、Ruby、Java、Python、C 和 C++的支持。
MDS:MDS全称Ceph Metadata Server,是CephFS服务依赖的元数据服务。
RBD:RBD全称 RADOS Block Device,是 Ceph 对外提供的块设备服务。
RGW:RGW全称RADOS gateway,是Ceph对外提供的对象存储服务,接口与S3和Swift兼容。
CephFS:CephFS全称Ceph File System,是Ceph对外提供的文件系统服务。
 

0.2 存储

0.2.1 三种存储类型

块设备:主要是将裸磁盘空间映射给主机使用,类似于SAN存储,使用场景主要是文件存储,日志存储,虚拟化镜像文件等。

文件存储:典型代表:FTP 、NFS 为了克服块存储无法共享的问题,所以有了文件存储。

对象存储:具备块存储的读写高速和文件存储的共享等特性并且通过 Restful API 访问,通常适合图片、流媒体存储。

0.2.2 IO流程及数据分布

img

img

步骤


client 创建cluster handler。
client 读取配置文件。
client 连接上monitor,获取集群map信息。
client 读写io 根据crushmap 算法请求对应的主osd数据节点。
主osd数据节点同时写入另外两个副本节点数据。
等待主节点以及另外两个副本节点写完数据状态。
主节点及副本节点写入状态都成功后,返回给client,io写入完成。

0.2.3 新主IO流程图

如果新加入的OSD1取代了原有的 OSD4成为 Primary OSD, 由于 OSD1 上未创建 PG , 不存在数据,那么 PG 上的 I/O 无法进行,怎样工作的呢?

img

步骤


(1)client连接monitor获取集群map信息。

(2)同时新主osd1由于没有pg数据会主动上报monitor告知让osd2临时接替为主。

(3)临时主osd2会把数据全量同步给新主osd1。

(4)client IO读写直接连接临时主osd2进行读写。

(5)osd2收到读写io,同时写入另外两副本节点。

(6)等待osd2以及另外两副本写入成功。

(7)osd2三份数据都写入成功返回给client, 此时client io读写完毕。

(8)如果osd1数据同步完毕,临时主osd2会交出主角色。

(9)osd1成为主节点,osd2变成副本。

0.2.4 Ceph存储过程

*****************************************************************************************************************************

首先,要明确Ceph的一个规定:在Ceph中,一切皆对象。

不论是视频,文本,照片等一切格式的数据,Ceph统一将其看作是对象,因为追其根源,所有的数据都是二进制数据保存于磁盘上,所以每一份二进制数据都看成一个对象,不以它们的格式来区分他们。

那么用什么来区分两个对象呢?对象名。也就是说,每个不同的对象都有不一样的对象名。

*****************************************************************************************************************************

Ceph为了保存一个对象,对上构建了一个逻辑层,也就是池(pool),用于保存对象,这个池的翻译很好的解释了pool的特征,如果把pool比喻成一个中国象棋棋盘,那么保存一个对象的过程就类似于把一粒芝麻放置到棋盘上。

Pool再一次进行了细分,即将一个pool划分为若干的PG(归置组 Placement Group),这类似于棋盘上的方格,所有的方格构成了整个棋盘,也就是说所有的PG构成了一个pool。

现在需要解决的问题是,对象怎么知道要保存到哪个PG上,假定这里我们的pool名叫rbd,共有256个PG,给每个PG编个号分别叫做0x0, 0x1, ...0xF, 0x10, 0x11... 0xFE, 0xFF。

要解决这个问题,我们先看看我们拥有什么,1,不同的对象名。2,不同的PG编号。这里就可以引入Ceph的计算方法了 : HASH。

对于对象名分别为bar和foo的两个对象,对他们的对象名进行计算即:

    HASH(‘bar’) = 0x3E0A4162
    HASH(‘foo’) = 0x7FE391A0
    HASH(‘bar’) = 0x3E0A4162
对对象名进行HASH后,得到了一串十六进制输出值,也就是说通过HASH我们将一个对象名转化成了一串数字,那么上面的第一行和第三行是一样的有什么意义? 意义就是对于一个同样的对象名,计算出来的结果永远都是一样的,但是HASH算法的确将对象名计算得出了一个随机数。

有了这个输出,我们使用小学就会的方法:求余数!用随机数除以PG的总数256,得到的余数一定会落在[0x0, 0xFF]之间,也就是这256个PG中的某一个:

    0x3E0A4162 % 0xFF ===> 0x62
    0x7FE391A0 % 0xFF ===> 0xA0
于是乎,对象bar保存到编号为0x62的PG中,对象foo保存到编号为0xA0的PG中。对象bar永远都会保存到PG 0x62中! 对象foo永远都会保存到PG 0xA0中!

现在又来了一亿个对象,他们也想知道自己会保存到哪个PG中,Ceph说:“自己算”。于是这一亿个对象,各自对自己对象名进行HASH,得到输出后除以PG总数得到的余数就是要保存的PG。

求余的好处就是对象数量规模越大,每个PG分布的对象数量就越平均。

所以每个对象自有名字开始,他们要保存到的PG就已经确定了。

那么爱思考的小明同学就会提出一个问题,难道不管对象的高矮胖瘦都是一样的使用这种方法计算PG吗,答案是,YES! 也就是说Ceph不区分对象的真实大小内容以及任何形式的格式,只认对象名。毕竟当对象数达到百万级时,对象的分布从宏观上来看还是平均的。

这里给出更Ceph一点的说明,实际上在Ceph中,存在着多个pool,每个pool里面存在着若干的PG,如果两个pool里面的PG编号相同,Ceph怎么区分呢? 于是乎,Ceph对每个pool进行了编号,比如刚刚的rbd池,给予编号0,再建一个pool就给予编号1,那么在Ceph里,PG的实际编号是由pool_id+.+PG_id组成的,也就是说,刚刚的bar对象会保存在0.62这个PG里,foo这个对象会保存在0.A0这个PG里。其他池里的PG名称可能为1.12f, 2.aa1,10.aa1等。

*****************************************************************************************************************************

理解了刚刚的逻辑层,我们再看一下Ceph里的物理层,对下,也就是我们若干的服务器上的磁盘,通常,Ceph将一个磁盘看作一个OSD(实际上,OSD是管理一个磁盘的程序),于是物理层由若干的OSD组成,我们的最终目标是将对象保存到磁盘上,在逻辑层里,对象是保存到PG里面的,那么现在的任务就是打通PG和OSD之间的隧道。PG相当于一堆余数相同的对象的组合,PG把这一部分对象打了个包,现在我们需要把很多的包平均的安放在各个OSD上,这就是CRUSH算法所要做的事情:CRUSH计算PG->OSD的映射关系。

加上刚刚的对象映射到PG的方法,我们将开篇的两步表示成如下的两个计算公式:

    池ID + HASH(‘对象名’) % pg_num ===> PG_ID
    CRUSH(PG_ID) ===> OSD
  

*****************************************************************************************************************************

在讨论CRUSH算法之前,我们来做一点思考,可以发现,上面两个计算公式有点类似,为何我们不把

CRUSH(PG_ID) ===> OSD
改为
HASH(PG_ID) %OSD_num ===> OSD
我可以如下几个由此假设带来的副作用:

如果挂掉一个OSD,OSD_num-1,于是所有的PG % OSD_num的余数都会变化,也就是说这个PG保存的磁盘发生了变化,对这最简单的解释就是,这个PG上的数据要从一个磁盘全部迁移到另一个磁盘上去,一个优秀的存储架构应当在磁盘损坏时使得数据迁移量降到最低,CRUSH可以做到。

如果保存多个副本,我们希望得到多个OSD结果的输出,HASH只能获得一个,但是CRUSH可以获得任意多个。

如果增加OSD的数量,OSD_num增大了,同样会导致PG在OSD之间的胡乱迁移,但是CRUSH可以保证数据向新增机器均匀的扩散。

所以HASH只适用于一对一的映射关系计算,并且两个映射组合(对象名和PG总数)不能变化,因此这里的假设不适用于PG->OSD的映射计算。因此,这里开始引入CRUSH算法。


*****************************************************************************************************************************

千呼万唤始出来,终于开始讲CRUSH算法了,如果直接讲Sage的博士论文或者crush.c的代码的话,可能会十分苦涩难懂,所以我决定尝试大话一把CRUSH,希望能让没有接触过CRUSH的同学也能对其有所理解。

首先来看我们要做什么:

	把已有的PG_ID映射到OSD上,有了映射关系就可以把一个PG保存到一个磁盘上。
	
	如果我们想保存三个副本,可以把一个PG映射到三个不同的OSD上,这三个OSD上保存着一模一样的PG内容。
	
再来看我们有了什么:

	互不相同的PG_ID。
	
	如果给OSD也编个号,那么就有了互不相同的OSD_ID。
	
	每个OSD最大的不同的就是它们的容量,即4T还是800G的容量,我们将每个OSD的容量又称为OSD的权重(weight),规定4T权重为4,800G为0.8,也就是以T为单位的值。
	现在问题转化为:如何将PG_ID映射到有各自权重的OSD上。这里我直接使用CRUSH里面采取的Straw算法,翻译过来就是抽签,说白了就是挑个最长的签,这里的签指的是OSD的权重。

那么问题就来了,总不至于每次都挑容量最大的OSD吧,这不分分钟都把数据存满那个最大的 OSD了吗?是的,所以在挑之前先把这些OSD搓一搓,这里直接介绍CRUSH的方法,如下图

Alt text

	CRUSH_HASH( PG_ID, OSD_ID, r ) ===> draw
	( draw &0xffff ) * osd_weight ===> osd_straw
	pick up high_osd_straw
	
第一行,我们姑且把r当做一个常数,第一行实际上就做了搓一搓的事情:将PG_ID, OSD_ID和r一起当做CRUSH_HASH的输入,求出一个十六进制输出,这和HASH(对象名)完全类似,只是多了两个输入。所以需要强调的是,对于相同的三个输入,计算得出的draw的值是一定相同的。

这个draw到底有啥用?其实,CRUSH希望得到一个随机数,也就是这里的draw,然后拿这个随机数去乘以OSD的权重,这样把随机数和OSD的权重搓在一起,就得到了每个OSD的实际签长,而且每个签都不一样长(极大概率),就很容易从中挑一个最长的。

说白了,CRUSH希望随机挑一个OSD出来,但是还要满足权重越大的OSD被挑中的概率越大,为了达到随机的目的,它在挑之前让每个OSD都拿着自己的权重乘以一个随机数,再取乘积最大的那个。那么这里我们再定个小目标:挑个一亿次!从宏观来看,同样是乘以一个随机数,在样本容量足够大之后,这个随机数对挑中的结果不再有影响,起决定性影响的是OSD的权重,也就是说,OSD的权重越大,宏观来看被挑中的概率越大。

这里再说明下CRUSH造出来的随机数draw,前文可知,对于常量输入,一定会得到一样的输出,所以这并不是真正的随机,所以说,CRUSH是一个伪随机算法。

如果看到这里你已经被搅晕了,那让我再简单梳理下PG选择一个OSD时做的事情:

	给出一个PG_ID,作为CRUSH_HASH的输入。
	CRUSH_HASH(PG_ID, OSD_ID, r) 得出一个随机数(重点是随机数,不是HASH)。
	对于所有的OSD用他们的权重乘以每个OSD_ID对应的随机数,得到乘积。
	选出乘积最大的OSD。
	这个PG就会保存到这个OSD上。
现在趁热打铁,解决一个PG映射到多个OSD的问题,还记得那个常量r吗?我们把r+1,再求一遍随机数,再去乘以每个OSD的权重,再去选出乘积最大的OSD,如果和之前的OSD编号不一样,那么就选中它,如果和之前的OSD编号一样的话,那么再把r+2,再次选一次,直到选出我们需要的三个不一样编号的OSD为止!

当然实际选择过程还要稍微复杂一点,我这里只是用最简单的方法来解释CRUSH在选择OSD的时候所做的事情。

下面我们来举个例子,假定我们有6个OSD,需要从中选出三个副本:

osd_id		weight		CRUSH_HASH		(CRUSH_HASH & 0xffff)* weight
osd.0		  4			0xC35E90CB				0x2432C
osd.1		  4			0xA67DE680				0x39A00
osd.2		  4			0xF9B1B224				0x2C890
osd.3		  4			0x42454470				0x111C0
osd.4		  4			0xE950E2F9				0x38BE4
osd.5		  4			0x8A844538				0x114E0
这是r = 0的情况,这时候,我们选出(CRUSH_HASH & 0xFFFF) * weight的值最大的一个,也就是osd.1的0x39A00,这就是我们选出的第一个OSD。
然后,我们再让r = 1,再生成一组CRUSH_HASH的随机值,乘以OSD的weight,再取一个最大的得到第二个OSD,依此得到第三个OSD,如果在此过程中,选中了相同的OSD,那么将r再加一,生成一组随机值,再选一次,直到选中三个OSD为止。

*****************************************************************************************************************************

理解了上面CRUSH选择OSD的过程,我们就很容易进一步将CRUSH算法结合实际结构,这里给出Sage在他的博士论文中画的一个树状结构图:

Alt text

最下面的蓝色长条可以看成一个个主机,里面的灰色圆柱形可以看成一个个OSD,紫色的cabinet可以也就是一个个机柜, 绿色的row可以看成一排机柜,顶端的root是我们的根节点,没有实际意义,你可以把它看成一个数据中心的意思,也可以看成一个机房的意思,不过只是起到了一个树状结构的根节点的作用。

后续看不懂了,可以在这个链接下细看http://www.xuxiaopang.com/2016/11/08/easy-ceph-CRUSH/

0.3 版本介绍

Ceph版本来源介绍
Ceph 社区最新版本是 15,而 Ceph 12 是市面用的最广的稳定版本。
第一个 Ceph 版本是 0.1 ,要回溯到 2008 年 1 月。多年来,版本号方案一直没变,直到 2015 年 4 月 0.94.1 ( Hammer 的第一个修正版)发布后,为了避免 0.99 (以及 0.100 或 1.00 ?),制定了新策略。

x.0.z - 开发版(给早期测试者和勇士们)

x.1.z - 候选版(用于测试集群、高手们)

x.2.z - 稳定、修正版(给用户们)

x 将从 9 算起,它代表 Infernalis ( I 是第九个字母),这样第九个发布周期的第一个开发版就是 9.0.0 ;后续的开发版依次是 9.0.1 、 9.0.2 等等。
| 版本名称 			  | 版本号 			  | 发布时间 		   			 |
| ----------------- | ------------------  | ------------------			|
| Argonaut 			| 0.48版本(LTS)	 	 |   2012年6月3日 	 			|
| Bobtail 			| 0.56版本(LTS) 		 |  2013年5月7日      			|
| Cuttlefish 		| 0.61版本 			 |  2013年1月1日 	   			|
| Dumpling 			| 0.67版本(LTS) 		 |  2013年8月14日 	   			|
| Emperor 			| 0.72版本 			 |  2013年11月9  		         |
| Firefly 			| 0.80版本(LTS) 		 |  2014年5月        			 |
| Giant 			| Giant 			  |  October 2014 - April 2015 |
| Hammer 			| Hammer 			  |  April 2015 - November 2016|
| Infernalis 		| Infernalis 		  |  November 2015 - June 2016 |
| Jewel 			| 10.2.9 			  |  2016年4月        		  |
| Kraken 			| 11.2.1 			  |  2017年10月       		  |
| Luminous 			|12.2.12  			  |  2017年10月              	  |
| mimic 			| 13.2.7 			  |  2018年5月                  |
| nautilus 			| 14.2.5 		      |  2019年2月 				  |

1,准备工作

1.1 先准备五台虚拟机

192.168.182.130  cephmgr
192.168.182.132  cephstore2
192.168.182.133  cephstore3
192.168.182.134  cephstore4
192.168.182.135  cephstore5

小技巧 挂载额外硬盘(这里千万不要这样干)

#1,先新增一块硬盘 
#2,使用 df -h 命令 查看硬盘未找到,需要格式化 以及分区
#3,使用 fdisk -l 找到磁盘名  /dev/sdb
#4,使用 fdisk /dev/sdb 命令开始格式化分区
#5,依次输入 m n p 1 然后 w保存
#6,使用 fdisk -l 命令 即可看到 如下字样 

磁盘 /dev/sdb:5368 MB, 5368709120 字节,10485760 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1ae1d9ba

   设备 Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048    10485759     5241856   83  Linux

#7,使用 mkfs.xfs /dev/sdb1  // 如果设备内已经有了文件系统,则需要使用-f强制格式化
#8,创建创建挂载的目录 mkdir /ceph-data
#9,配置文件 vi /etc/fstab 
输入如下:/dev/sdb1 /ceph-data                    xfs    defaults        0 0
##注意 后面的两个 0  
#第一个0 表示内容的备份:1 表示备份 0表示不备份
#第二个0 表示检查硬盘  0 不检查 1 表示检查 /路径必须设置为1 ,其他的路径不能设置为1 ,其他的检查顺序按照数字从小到大开始
#10,使用 mount -a 来挂载 

1.3 创建用户

###########################################下面步骤是在####所有节点####上面执行的#################################################
#创建cephu用户
useradd cephu
#创建cephu用户密码
passwd cephu

#确保各 Ceph 节点上新创建的用户都有 sudo 权限
echo "cephu ALL = (root) NOPASSWD:ALL" | tee /etc/sudoers.d/cephu
chmod 0440 /etc/sudoers.d/cephu 

#修改/etc/hosts文件 在hosts文件里写入以下映射信息 添加主机名和IP对应解析
vi /etc/hosts
192.168.182.130   cephmgr
192.168.182.132   cephstore2
192.168.182.133   cephstore3
192.168.182.134   cephstore4
192.168.182.135   cephstore5

1.4 生成ssh-pub秘钥(主)

##########################################下面步骤是在####cephmgr####上面执行的################################################
ssh-keygen
ssh-copy-id cephu@cephmgr
ssh-copy-id cephu@cephstore2
ssh-copy-id cephu@cephstore3
ssh-copy-id cephu@cephstore4
ssh-copy-id cephu@cephstore5

1.5 配置各种源

###########################################下面步骤是在####所有节点####上面执行的#################################################
#安装 epel 安装wget
yum -y install epel-release wget
#配置epel源 
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
#配置 centos7的源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
#配置ceph的源 
cat << EOF > /etc/yum.repos.d/ceph.repo
[ceph]
name=ceph
baseurl=https://mirrors.aliyun.com/ceph/rpm-octopus/el7/x86_64/
gpgcheck=0
[ceph-noarch]
name=cephnoarch
baseurl=https://mirrors.aliyun.com/ceph/rpm-octopus/el7/noarch/
gpgcheck=0
EOF

#重新创建 本地仓库缓存
yum clean all && yum makecache 

1.6 配置NTP时间同步

##########################################下面步骤是在####cephmgr####上面执行的################################################
vi /etc/chrony.conf
#2,设置成如下 (后三个注掉,加#号)
server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

###########################################下面步骤是在####其他节点####上面执行的#################################################
vi /etc/chrony.conf
#4,设置成如下(四个都注掉,替换成mgr的主机地址)
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
server 192.168.182.130 iburst  

###########################################下面步骤是在####所有节点####上面执行的#################################################
#5,重启服务
systemctl restart chronyd.service

1.7 关闭防火墙、核心防护

###########################################下面步骤是在####所有节点####上面执行的#################################################
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i '7s/enforcing/disabled/' /etc/selinux/config

1.8 添加免密执行权限

###########################################下面步骤是在####所有节点####上面执行的#################################################
#在每个节点上添加ceph用户免密执行root权限
vim /etc/sudoers
 
cephu        ALL=(ALL)       NOPASSWD: ALL

2,开始搭建

2.1 配置文件

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点 安装ceph-deploy 和 pthhon相关 
yum install -y ceph-deploy python2-subprocess32 python36-werkzeug python-setuptools
pip3 install pecan -i https://pypi.douban.com/simple

#切换到cephu用户
    
 su - cephu

#--cluster-network 为集群内部地址,  --public-network 为外部可以调用地址
ceph-deploy new --cluster-network 192.168.182.130/24 --public-network 192.168.182.130/24 cephmgr

#修改ceph.conf配置
#在cephu用户家目录下修改ceph.conf配置文件
vi ceph.conf
 
[global]
fsid = 3ef172a8-147b-442d-a24a-1cd17ae2357e
public_network = 192.168.182.130/24
cluster_network = 192.168.182.130/24
mon_initial_members = cephstore2  #修改此处mon的主机名称
mon_host = 192.168.182.132           #修改此处mon的IP地址
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

注意

#注意,如果出现 
Traceback (most recent call last):
  File "/bin/ceph-deploy", line 18, in <module>
    from ceph_deploy.cli import main
ImportError: No module named ceph_deploy.cli

#解决办法:更改/usr/bin/ceph-deploy文件中   更改python2.6的部分为2.7(此处应当与系统python版本相同)   更改第一行文件#!/usr/bin/python2.7  重新执行ceph-deploy new即可
#为什么会出现这个错误:python 版本问题,注意检查系统的python版本,此处ceph-deploy实则为通过执行python脚本来实现安装;

注意:如果不小心卸载了 python 导致yum也不能用了

如果不小心卸载了 python 
#https://blog.csdn.net/weixin_43998608/article/details/108287625
#卸载python/删除所有残余文件/验证删除,返回无结果
rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps
whereis python |xargs rm -frv 
whereis python 
#删除yum/删除残留文件//验证删除,返回无结果
rpm -qa|grep yum|xargs rpm -ev --allmatches --nodeps 
whereis yum |xargs rm -frv
whereis yum 
#安装python
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-2.7.5-58.el7.x86_64.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-devel-2.7.5-58.el7.x86_64.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-iniparse-0.4-9.el7.noarch.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-libs-2.7.5-58.el7.x86_64.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-pycurl-7.19.0-19.el7.x86_64.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/python-urlgrabber-3.10-8.el7.noarch.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/rpm-python-4.11.3-25.el7.x86_64.rpm
#yum安装
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/yum-3.4.3-154.el7.centos.noarch.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/yum-metadata-parser-1.1.4-10.el7.x86_64.rpm
rpm -ivh --nodeps http://vault.centos.org/7.4.1708/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.31-42.el7.noarch.rpm

2.2 mon节点

###########################################下面步骤是在####cephstore2####上面执行的############################################

#在所有mon节点上安装ceph-mon服务 (这里只在cephstore2节点安装了,所以是在 cephstore2 节点执行这个命令 )
yum install -y ceph-mon

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点cephu用户下初始化ceph-mon主节点
#在mgr节点cephu用户下初始化mon节点
ceph-deploy mon create-initial

###########################################下面步骤是在####cephstore2####上面执行的############################################
#在cephstore2节点验证是否安装mon成功
 ps aux | grep mon

2.3 mgr节点

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点上执行安装ceph-mgr服务
 yum install -y ceph-mgr

#在mgr节点cephu用户下执行创建mgr
ceph-deploy mgr create cephmgr
 
#验证mgr是否安装成功
ps aux | grep mgr

2.4 osd节点

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点cephu用户下初始化每个storge节点
#在mgr节点cephu用户下执行初始化每个storge节点命令

ceph-deploy install --no-adjust-repos --nogpgcheck cephstore2
ceph-deploy install --no-adjust-repos --nogpgcheck cephstore3
ceph-deploy install --no-adjust-repos --nogpgcheck cephstore4

#在mgr节点cephu用户下依次执行擦除磁盘数据 
ceph-deploy disk zap cephstore2 /dev/sdb      # 节点名称   #磁盘名称
#ceph-deploy disk zap cephstore2 /dev/sdc
ceph-deploy disk zap cephstore3 /dev/sdb
#ceph-deploy disk zap cephstore3 /dev/sdc
ceph-deploy disk zap cephstore4 /dev/sdb
#ceph-deploy disk zap cephstore4 /dev/sdc


ceph-deploy osd create cephstore2 --data /dev/sdb
#ceph-deploy osd create cephstore2 --data /dev/sdc
ceph-deploy osd create cephstore3 --data /dev/sdb
#ceph-deploy osd create cephstore3 --data /dev/sdc
ceph-deploy osd create cephstore4 --data /dev/sdb
#ceph-deploy osd create cephstore4 --data /dev/sdc

3,查看集群

3.1 复制文件

##########################################下面步骤是在####cephmgr####上面执行的################################################
#把cephu用户下的ceph.client.admin.keyring 文件移动到/etc/ceph/ 目录下
cd home/cephu/
cp ./ceph.client.admin.keyring /etc/ceph/

#把 文件同步到所有机器上面 这样其他机器也可以 使用ceph -s 命令查看 ceph集群
ceph-deploy admin cephmgr cephstore2 cephstore3 cephstore4 cephstore5

#注意,如果不复制这个文件 直接执行 ceph -s 会报错的,, 

##推送修改的ceph.conf文件到所有节点(覆盖旧的ceph.conf)
ceph-deploy --overwrite-conf config push cephmgr cephstore2 cephstore3 cephstore4 cephstore5

3.2 查看信息

ceph -s

#会看到如下信息
[root@cephmgr ceph]# ceph -s
  cluster:
    id:     92906df7-8b76-4273-945a-a3e6dbe7d8fa
    health: HEALTH_WARN
            mon is allowing insecure global_id reclaim
 
  services:
    mon: 1 daemons, quorum cephstore2 (age 19m)
    mgr: cephmgr(active, since 12m)
    osd: 3 osds: 3 up (since 3m), 3 in (since 3m)
 
  data:
    pools:   1 pools, 1 pgs
    objects: 0 objects, 0 B
    usage:   3.0 GiB used, 12 GiB / 15 GiB avail
    pgs:     1 active+clean
 
[root@cephmgr ceph]# 

3.3 处理警告

##########################################下面步骤是在####cephmgr####上面执行的################################################
#处理 mon is allowing insecure global_id reclaim 警告

ceph config set mon auth_allow_insecure_global_id_reclaim false

4,集群扩展

4.1 扩展mon节点

###########################################下面步骤是在####cephstore3####上面执行的############################################

#在需要添加到ceph集群的mon节点上安装cepn-mon服务 比如 cephstore3 节点
yum install -y ceph-mon

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点cephu用户下把新增加的ceph-mon节点添加到ceph集群
#在mgr节点cephu用户下执行
ceph-deploy mon add cephstore3


#在mgr节点上切换到root用户下查看集群状态
#切换到root用户下查看集群状态
ceph -s

4.2 扩展mgr节点

###########################################下面步骤是在####cephstore2####上面执行的############################################

#在需要添加到ceph集群的mgr节点上安装cepn-mgr服务 比如 cephstore2 节点
#在cephstore2上安装ceph-mgr服务
yum install -y ceph-mgr 

##########################################下面步骤是在####cephmgr####上面执行的################################################
#在mgr节点cephu用户下把新增加的ceph-mgr节点添加到ceph集群
#在mgr节点cephu用户下执行
 
ceph-deploy mgr create cephstore2

#在mgr节点上切换到root用户下查看集群状态
#切换到root用户下查看集群状态
 
ceph -s

5,集群管理

5.1 存储池

创建存储池及存储池的管理
pool:存储池的大小取决于底层的存储空间。
pg:  抽象的逻辑概念,一个 pool 中有多少个 pg 可以通过公式计算。
pgp: 是每份数据备份组合
ceph 集群部署好之后 , 要先创建存储池才能向 ceph 写入数据,文件在向 ceph 保存之前要先进行文件大小的切割,通常切割为大小为4M的存储快,然后在进行一致性 hash 计算,计算后会把文件保存在某个对应的 pg 的osd上,此文件一定属于某个 pool 的一个 pg 。


5.1.1 创建

##########################################下面步骤是在####cephmgr####上面执行的################################################
##这块网上各种说法都有,我测试了,在任意节点执行结果都一样

ceph osd pool create mypool 32 32
 
#mypool 为存储池名称
#第一个32 为pg数量
#第二个32 为pgp数量

5.1.2 查看修改

##########################################下面步骤是在####cephmgr####上面执行的################################################
##这块网上各种说法都有,我测试了,在任意节点执行结果都一样

#查看存储池创建情况(验证pg和pgp)
ceph pg ls-by-pool  mypool | awk '{print $1, $2, $15}'

#PG:pg的 ID.NUM
#OBJECTS:
#ACTING: 一份数据 为一主两备 存贮的位置信息

#如何查看所有pool信息
ceph osd pool ls

#如何查看具体一个pool的详细信息
ceph osd pool stats mypool

#查看ceph存储池副本数配置
ceph osd pool get mypool size

#设置ceph存储池副本数
ceph osd pool set mypool size 2

#通过使用命令  ceph pg ls-by-pool  mypool | awk '{print $1, $2, $15}' 
#可以看到存储池副本数有3个变成了2个


5.1.3 删除

##########################################下面步骤是在####cephmgr####上面执行的################################################
#默认情况下ceph集群的存储池是不被允许删除的,要想删除存储池需要修改系统配置项,允许执行删除存储池操作。
# 告诉所有节点可以删除存储池
 
ceph tell mon.* injectargs --mon-allow-pool-delete=true
 
 
#执行删除操作
ceph osd pool delete mypool mypool --yes-i-really-really-mean-it  
#mypool为存储池名称
 
 
#删除后关闭允许删除存储池
ceph tell mon.* injectargs --mon-allow-pool-delete=false

5.2 OSD管理

5.2.1 常用命令

#列出osd信息
ceph osd stat

#列出osd更详细的信息
ceph osd dump

#列出osd的磁盘列表信息
ceph osd tree

5.2.2 停用OSD

##########################################下面步骤是在####cephmgr####上面执行的################################################
#停用某个osd  (这里我们停用cephstore2节点的osd) 让ID为0的osd down 掉,此时该 osd 不接受读写请求,但 osd 还是存活的,即对应down in状态
ceph osd out osd.0
# 使用 命令 ceph osd tree
#可以看到osd.0的权重为0 此时osd.0不会再有数据写入 

###########################################下面步骤是在####cephstore2####上面执行的############################################
#登录到cephstore2节点上,停止cephstore2节点上的osd.0进程
systemctl stop ceph-osd@0.service

##########################################下面步骤是在####cephmgr####上面执行的################################################
#移除OSD
#[id]为osd的ID
ceph osd purge [id] --yes-i-really-mean-it
#例如 ceph osd purge 0 --yes-i-really-mean-it

#使用 ceph -s 验证 

//参考 6.8.4 osd删除

5.2.3 重新挂载

###########################################下面步骤是在####cephstore2####上面执行的############################################
##因为我们刚才 停用的是 cephstore2节点 的 osd.0 所以登录到 cephstore2上面执行下面命令 
#重新挂载osd.0 
#登录到cephstore2节点上,
#执行命令移除 lsblk -l 的信息 
dmsetup remove_all

##########################################下面步骤是在####cephmgr####上面执行的################################################
#更换新的硬盘执行硬盘添加操作(此处演示还是老的磁盘)执行
#在mgr节点cephu用户下执行
ceph-deploy osd create cephstore2 --data /dev/sdb

##此时会报错:Failed to execute command: /usr/sbin/ceph-volume --cluster ceph lvm create --bluestore --data
##提示添加失败了,原因是磁盘里有数据我们要手动清理掉硬盘的分区表 (当然如果硬盘是全新的, 这里应该就成功了).

###########################################下面步骤是在####cephstore2####上面执行的############################################
#在 cephstore2上面 执行  
dd if=/dev/zero of=/dev/sdb bs=512K count=1

##########################################下面步骤是在####cephmgr####上面执行的################################################
#然后 在mgr节点cephu用户下再次执行
ceph-deploy osd create cephstore2 --data /dev/sdb

#验证
ceph -s
ceph osd tree

5.3 块存储rbd

5.3.1 创建

##########################################下面步骤是在####cephmgr####上面执行的################################################
#创建存储池myrdb1
ceph osd pool create myrdb1 32 32 
 
#查看已创建存储池的信息
ceph osd pool ls

#启用块存储
ceph osd pool application enable myrdb1 rbd

#对块存储进行初始化
rbd pool init -p myrdb1

#创建一个3G大小的磁盘镜像
rbd create myimg1 --size 3G --pool myrdb1 --image-format 2 --image-feature layering
# --image-feature为启用的磁盘镜像特性

# 列出创建的磁盘镜像信息
rbd --image myimg1 --pool myrdb1 info

##########################################下面步骤是在####cephstore5####上面执行的##############################################

#在新服务器上安装ceph-common
yum install ceph-common -y
 
#执行rbd磁盘挂载
rbd --user admin -p myrdb1 map myimg1 #-p 块myrdb1  #myimg1为镜像名称

##磁盘挂载需要有权限的用户才能挂载,本示例中采用admin最高权限用户,
##需要把mgr节点上的ceph.client.admin.keyring和ceph.conf 配置文件放置到的新节点/etc/ceph/ 下

#使用lsblk验证 一下  可以看到 
[root@cephstore5 /]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   20G  0 disk 
├─sda1            8:1    0  200M  0 part /boot
└─sda2            8:2    0 19.8G  0 part 
  ├─centos-root 253:0    0  7.8G  0 lvm  /
  ├─centos-swap 253:1    0    2G  0 lvm  [SWAP]
  └─centos-home 253:2    0   10G  0 lvm  /home
sdb               8:16   0    5G  0 disk 
└─sdb1            8:17   0    5G  0 part /ceph-data
sr0              11:0    1 1024M  0 rom  
rbd0            252:0    0    3G  0 disk   #这里已经 显示rbd0被挂载上去了

5.3.2 回收

# 删除之前先看下改rbd是否正在使用
#查看myimg1状态
 
rbd status --pool myrdb1 --image myimg1
 
# 镜像移动到回收站
rbd trash move --pool myrdb1 --image myimg1

#查看回收站镜像
rbd trash list --pool myrdb1
 
#从回收站删除镜像

#查看映射关系
rbd showmapped
 
#取消相应的映射
rbd unmap myrdb1/myimg1
 
#清除回收站
rbd trash remove  --pool myrdb1 11d06cc438b7

5.4 对象存储rgw

5.4.1 安装

###########################################下面步骤是在####cephstore2####上面执行的############################################
###########################################下面步骤是在####cephstore3####上面执行的############################################

#部署radosgw 并对rgw做高可用和监控  (这里我们 使用 cephstore2和 cephstore3)
#在需要安装radosgw服务器上安装rgw组件
yum install -y ceph-radosgw

###########################################下面步骤是在####cephmgr####上面执行的############################################
#添加ceph-rdaosgw到集群中
ceph-deploy rgw create cephstore2
ceph-deploy rgw create cephstore3

#使用 ceph -s 验证 发现多了两个rgw节点

5.4.2 添加nginx

epool调用过程

<img src=”v2-7ac8b45ead05cd4a73f11fe9d27ab4f9_720w.jpg” alt=”img” />

select调用过程

img

####这里插一句哈, nginx和 redis都使用了Linux的epoll模型 
#具体 详情 https://zhuanlan.zhihu.com/p/427512269

#什么是select
有的朋友可能对select也不是很了解啊,我这里稍微科普一下:网络连接,服务器也是通过文件描述符来管理这些连接上来的客户端,既然是供连接的服务器,那就免不了要接收来自客户端的消息。那么多台客户端,消息那么的多,要是漏了一条两条重要消息,那也不要用TCP了,那怎么办?

前辈们就是有办法,轮询,轮询每个客户端文件描述符,查看他们是否带着消息,如果带着,那就处理一下;如果没带着,那就一边等着去。这就是select,轮询,颇有点领导下基层的那种感觉哈。

但是这个select的轮询呐,会有个问题,明眼人一下就能想到,那即是耗费资源啊,耗费什么资源,时间呐,慢呐(其实也挺快了,不过相对epoll来说就是慢)。

再认真想一下,还浪费什么资源,系统资源。有的客户端呐,占着那啥玩意儿不干那啥事儿,这种客户端呐,还不少。这也怪不得人家,哪儿有客户端时时刻刻在发消息,要是有,那就要小心是不是恶意攻击了。那把这么一堆偶尔动一下的客户端的文件描述符一直攥手里,累不累?能一次攥多少个?就像一个老板,一直想着下去巡视,那他可以去当车间组长了哈哈哈。

#select缺点
(1)单进程可以打开fd有限制;
(2)对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低;
(3)用户空间和内核空间的复制非常消耗资源;

#什么是epoll
epoll接口是为解决Linux内核处理大量文件描述符而提出的方案。该接口属于Linux下多路I/O复用接口中select/poll的增强。其经常应用于Linux下高并发服务型程序,特别是在大量并发连接中只有少部分连接处于活跃下的情况 (通常是这种情况),在该情况下能显著的提高程序的CPU利用率。

前面说,select就像亲自下基层视察的老板,那么epoll这个老板就要显得精明的多了。他可不亲自下基层,他找了个美女秘书,他只要盯着他的秘书看就行了,呸,他只需要听取他的秘书的汇报就行了。汇报啥呢?基层有任何消息,跟秘书说,秘书汇总之后一次性交给老板来处理。这样老板的时间不就大大的提高了嘛。

#epoll设计思路简介
(1)epoll在Linux内核中构建了一个文件系统,该文件系统采用红黑树来构建,红黑树在增加和删除上面的效率极高,因此是epoll高效的原因之一。有兴趣可以百度红黑树了解,但在这里你只需知道其算法效率超高即可。

(2)epoll提供了两种触发模式,水平触发(LT)和边沿触发(ET)。当然,涉及到I/O操作也必然会有阻塞和非阻塞两种方案。目前效率相对较高的是 epoll+ET+非阻塞I/O 模型,在具体情况下应该合理选用当前情形中最优的搭配方案。

(3)epoll所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于1024,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以下面语句查看,一般来说这个数目和系统内存关系很大。

############################################################################################################################
####nginx的内容 简介 
https://juejin.cn/post/6844904129987526663

##linux安装 nginx  
####这里 nignx 安装在 192.168.182.130 上面了 
###########################################下面步骤是在####cephmgr####上面执行的############################################
1,http://nginx.org/en/download.html 下载 
2,使用工具拖到 linux里面 我存放在 /opt/ 下面
3,tar -zxvf nginx-1.20.2.tar.gz 解压到当前文件夹 
4,安装库 
yum -y install gcc gcc-c++ autoconf automake make openssl openssl-devel pcre pcre-devel zlib zlib-devel libtool 

5,配置configure

#进入 nginx目录里
cd nginx-1.20.2
# --prefix 代表安装的路径,--with-http_ssl_module 安装ssl,--with-http_stub_status_module查看nginx的客户端状态
./configure --prefix=/usr/local/nginx-1.20.2 --with-http_ssl_module --with-http_stub_status_module

配置成功会出现如下 字样 
      nginx path prefix: "/usr/local/nginx-1.20.2"
      nginx binary file: "/usr/local/nginx-1.20.2/sbin/nginx"
      nginx modules path: "/usr/local/nginx-1.20.2/modules"
      nginx configuration prefix: "/usr/local/nginx-1.20.2/conf"
      nginx configuration file: "/usr/local/nginx-1.20.2/conf/nginx.conf"
      nginx pid file: "/usr/local/nginx-1.20.2/logs/nginx.pid"
      nginx error log file: "/usr/local/nginx-1.20.2/logs/error.log"
      nginx http access log file: "/usr/local/nginx-1.20.2/logs/access.log"
      nginx http client request body temporary files: "client_body_temp"
      nginx http proxy temporary files: "proxy_temp"
      nginx http fastcgi temporary files: "fastcgi_temp"
      nginx http uwsgi temporary files: "uwsgi_temp"
      nginx http scgi temporary files: "scgi_temp"

6,编译安装 nginx
make & make install 
7,配置一下conf文件 
cd /usr/local/nginx-1.20.2 
vi nginx.conf -n 

    35       upstream custom_web {
    36          server 192.168.182.132:7480 weight=1;
    37          server 192.168.182.133:7480 weight=1; 
    38       }
    
    42          server_name  ws.cephrgw.com;
     
    49          location / {
    50              proxy_pass  http://custom_web;
    51          }
8,启动 进入 sbin文件夹
./nginx

关闭nginx:
./nginx -s stop

推荐使用:
./nginx -s quit

###########################################下面步骤是在####windows电脑####上面执行的############################################
9,配置完成后 在本地电脑上配置hosts解析:
打开 C:\Windows\System32\drivers\etc\
修改 hosts文件 在文件里加入一行 

192.168.182.130  ws.cephrgw.com

然后 在本地浏览器访问:http://ws.cephrgw.com/

5.4.3 创建用户

###########################################下面步骤是在####cephmgr####上面执行的############################################
#创建用户
radosgw-admin  user create --uid="wangs" --display-name="test user"
 
#--uid 为用户名字
#--display-name 为用户说明
#创建完用户后会自动输出次用户的access_key 和 secret_key 保存好这两个信息,后面上传文件时需要用到。
[root@cephmgr /]# radosgw-admin  user create --uid="user1" --display-name="test user1"
{
    "user_id": "user1",
    "display_name": "test user1",
    "email": "",
    "suspended": 0,
    "max_buckets": 1000,
    "subusers": [],
    "keys": [
        {
            "user": "user1",
            "access_key": "2OUG1HY3S6J2OQ3YVQCJ",
            "secret_key": "5trRZXW9go6mhpuGT0OonSf1ZqDEsbEKutisK6ab"
        }
    ],
    "swift_keys": [],
    "caps": [],
    "op_mask": "read, write, delete",
    "default_placement": "",
    "default_storage_class": "",
    "placement_tags": [],
    "bucket_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "user_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "temp_url_keys": [],
    "type": "rgw",
    "mfa_ids": []
}

5.4.4 安装s3cmd

###########################################下面步骤是在####cephmgr####上面执行的############################################
#安装s3cmd工具用于在命令行操作ceph
#安装s3cmd工具  
yum install -y s3cmd

#修改hosts文件
vi etc/hosts

127.0.0.1   ws.cephrgw.com

#生产s3cmd命令配置工具
s3cmd --configure

#输入 key  这个key 是 5.4.3里面创建user给的 
Access Key:2OUG1HY3S6J2OQ3YVQCJ
Secret Key:5trRZXW9go6mhpuGT0OonSf1ZqDEsbEKutisK6ab
S3 Endpoint [s3.amazonaws.com]:ws.cephrgw.com
DNS-style bucket+hostname:port template for accessing a bucket [ws.cephrgw.com/%(bucket)]:ws.cephrgw.com/%(bucket)
Use HTTPS protocol [Yes]:No

img

解决ERROR: S3 error: 403 (SignatureDoesNotMatch) 问题

vi /root/.s3cfg

把 signature_v2 = False 改为 signature_v2 = True

5.4.5 创建测试

#创建bucket
##切记 不能有下划线,只能是 数字,字母和 - 组成 
s3cmd mb s3://ws-test-bucket  

#查看 bucket 
s3cmd ls

#测试下文件上传 
1,进入 文件所在的路径下,, 比如 root目录下 有个 名字为 ceph_test_img.png的图片 
cd /root
2,上传文件
s3cmd put ceph_test_img.png s3://ws-test-bucket/img/

#查看对象
s3cmd ls s3://ws-test-bucket/img/

#通过get下载 
s3cmd get s3://ws-test-bucket/img/ceph_test_img.png /tmp/

#删除文件对象
s3cmd del s3://ws-test-bucket/img/ceph_test_img.png

#删除bucket
s3cmd rb s3://ws-test-bucket



5.5文件存储mds

###########################################下面步骤是在####cephstore2####上面执行的############################################
###########################################下面步骤是在####cephstore3####上面执行的############################################
###########################################下面步骤是在####cephstore4####上面执行的############################################
#选取节点安装ceph-mds
 
yum install -y ceph-mds

###########################################下面步骤是在####cephmgr####上面执行的############################################
#把mds节点加入cephmds集群
ceph-deploy mds create cephstore2
ceph-deploy mds create cephstore3
ceph-deploy mds create cephstore4
  
#查看
ceph -s 

#创建cephfs metadata 和 data 存储池
#创建元数据分区
ceph osd pool create cephfs-metadata 16 16
 
#创建数据
ceph osd pool create cephfs-data 32 32

#创建一个新的文件系统

#创建一个叫做mycephfs的文件系统
 
ceph fs new mycephfs cephfs-metadata cephfs-data

#查看文件系统信息 mycephfs 是刚创建的文件系统名字

ceph fs status mycephfs 



###########################################下面步骤是在####cephstore5####上面执行的############################################
#在业务服务器上挂载ceph-fs文件系统 

# 在业务服务器上安装ceph服务
yum install ceph
 
#执行ceph 文件系统挂载
mount -t ceph 192.168.182.132:6789,192.168.182.133:6789,192.168.182.134:6789:/ /mnt -o name=admin,secret=AQDXJ3FiY+iJORAAXcXoxgdEcA8YDbq23VjuXQ==
 
#此处的IP地址为mds节点IP地址可以为多个IP地址实现 后面screat为/etc/ceph/ceph.client.admin.keyring 里下key里的证书



###########################################下面步骤是在####cephmgr####上面执行的############################################
#ceph-mds 节点提升为双主一备状态配置
#设置ceph文件系统mds服务为双主一备
ceph fs set mycephfs max_mds 2

#查看 
ceph -s

6,运维操作

6.1 操作集群

#查看节点上所有自动启动的ceph服务,命令:
systemctl list-unit-files|grep enabled|grep ceph
#查看节点上所有启动的ceph服务,命令:
systemctl list-units --type=service|grep ceph

#开启、关闭 和 重启 所有 ceph 服务
systemctl { start | stop | restart} ceph.target 

#根据 进程 类型 开启、关闭 和 重启 ceph 服务
#mon 进程
systemctl { start | stop | restart} ceph-mon.target  
#mgr 进程
systemctl { start | stop | restart} ceph-mgr.target 
#osd 进程
systemctl { start | stop | restart} ceph-osd.target 
#rgw 进程
systemctl { start | stop | restart} ceph-radosgw.target    
#mds 进程
systemctl { start | stop | restart} ceph-mds.target 

#根据 进程 实例 开启、关闭 和 重启 所有 ceph 服务
#mon 实例
systemctl { start | stop | restart} ceph-mon@{mon_instance}.service 
#mgr 实例
systemctl { start | stop | restart} ceph-mgr@{mgr_instance}.service
#osd 实例
systemctl { start | stop | restart} ceph-osd@{osd_instance}.service
#rgw 实例
systemctl { start | stop | restart} ceph-radosgw@{rgw_instance}.service
#mds 实例
systemctl { start | stop | restart} ceph-mds@{mds_instance}.service

6.2 监控集群

6.2.1 交互模式

要在交互模式下运行 ceph ,不要带参数运行 ceph ,例如:
ceph
ceph> health
ceph> status
ceph> quorum_status
ceph> mon_status

6.2.2 检查状况

#####
#检查ceph的状态
ceph -s
ceph status
ceph health
ceph health detail
#实时观察集群健康状态
ceph -w

6.2.3 使用情况

#####检查集群的使用情况
=======================命令 1=======================
ceph df #它和Linux上的df相似
#GLOBAL段
展示了数据所占用集群存储空间的概要,详解如下
SIZE:集群的总容量;
AVAIL:集群的空闲空间总量;
RAW USED:已用存储空间总量;
% RAW USED:已用存储空间比率。用此值参照full ratio和near full \ ratio来确保不会用 尽集群空间。详情见存储容量。

#POOLS 段:
展示了存储池列表及各存储池的大致使用率。没有副本、克隆品和快照占用情况。例如,如果你把1MB 的数据存储为对象,理论使用率将是1MB,但考虑到副本数、克隆数、和快照数,实际使用率可能是 2 MB或更多。
NAME:存储池名字;
ID:存储池唯一标识符;
USED:大概数据量,单位为B、KB、MB或GB ;
%USED:各存储池的大概使用率; Objects:各存储池内的大概对象数。
=======================命令 2=======================
ceph osd df #可以详细列出集群每块磁盘的使用情况,包括大小、权重、使用多少空间、使用率等等

6.2.4 检查osd

0、概念:
	OSD:Object Storage Device,主要负责响应客户端请求返回具体数据的守护进程,一般一个集群会有多个OSD,每一块盘都会对应一个OSD。
	
1、查看osd状态
	ceph osd stat
	3 osds: 3 up (since 44m), 3 in (since 15h); epoch: e774
    #OSD状态说明:
        a. 集群内(in)
        b. 集群外(out)
        c. 活着且在运行(up)
        d. 挂了且不再运行(down)
        正常情况下OSD的状态是up in状态,如果down掉OSD,它的状态会变为down in,
        等待数据均衡完成后osd变为down out状态,Ceph 会把其归置组迁移到其他OSD, CRUSH 就不会再分配归置组给它。
2、查看osd树
    ceph osd tree 查看
    ceph osd ls-tree cephstore2 # 查看 osd tree 中 rack 1 下的 osd 编号

3、查看osd映射信息
	ceph osd dump

4、 查看数据延迟
	# 主要解决单块磁盘问题,如果有问题及时剔除OSD。统计的是平均值
	# commit_latency 表示从接收请求到设置commit状态的时间间隔
	# apply_latency 表示从接收请求到设置apply状态的时间间隔
	ceph osd perf
	[root@cephmgr /]# ceph osd perf
	osd  commit_latency(ms)  apply_latency(ms)
  	2                   0                  0
  	1                   0                  0
  	0                   0                  0

5、 查看 CRUSH map
	ceph osd crush dump

6、 查看与设置最大osd daemon的个数
    #查看
    ceph osd getmaxosd
    max_osd = 12 in epoch 379
    #设置最大的osd daemon的个数(当扩大osd daemon的时候必须扩大这个值)
    ceph osd setmaxosd 2048
    
7、 查看OSD参数: #查看osd.1的参数  //要在osd.1那台机器上看 
	 ceph daemon osd.1 config show

6.2.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,并保存在l.txt文件中
    ceph mon getmap -o 1.txt
    monmaptool --print 1.txt

6.2.5 检查mds

元数据服务器为 Ceph 文件系统提供元数据服务,不过在当前生产环境中并未部署 MDS 。元数据服务器有两种状态: up | down 和 active | inactive ,执行下面的命令查看元数据服务器状态为 up 且 active :

查看mds状态
    ceph mds stat
要展示元数据集群的详细状态,执行下面的命令:
    ceph mds dump  

6.2.6 pg相关

6.2.6.1 相关概念
CRUSH 算法把 PG 分配到 OSD 时,它会根据存储池的副本数设置,把 PG 分配到不同的 OSD 上。比如,如果存储池设置为 3 副本, CRUSH 可能把它们分别分配到 osd.1 、osd.2 、osd.3 。考虑到 CRUSH Map 中设定的故障域,实际上 CRUSH 找出的是伪随机位置,所以在大型集群中,很少能看到 PG 被分配到了相邻的 OSD 。我们把涉及某个特定 PG 副本的一组 OSD 称为 acting set 。在某些情况下,位于 acting set 中的一个 OSD down 了或者不能为 PG 内的对象提供服务,这些情形发生时无需惊慌,常见原因如下:

1,你增加或移除了某个 OSD 。然后 CRUSH 算法把 PG 重新分配到了其他 OSD ,因此改变了 Acting Set 的构成,并且引发了 “backfill” 过程来进行数据迁移。

2,某个 OSD down 了、重启了,而现在正在恢复( recovering )。

3,Acting Set 中的一个 OSD down 了,不能提供服务,另一个 OSD 临时接替其工作。

Ceph 靠 Up Set 处理客户端请求,它们是实际处理读写请求的 OSD 集合。大多数情况下 Up Set 和 Acting Set 是相同的。如果不同,说明可能 Ceph 正在迁移数据、某 OSD 在恢复、或者有别的问题。这种情况下, Ceph 通常表现为 “HEALTH WARN” 状态,还有 “stuck stale” 消息。
6.2.6.2 节点互联
写入数据前,PG 必须处于 active 、而且应该是 clean 状态。
假设某存储池的 PG 有 3 副本,为让 Ceph 确定 PG 的当前状态,PG 的主 OSD (即 acting set 内的第一个 OSD )会与第二和第三 OSD 建立连接、并就 PG 的当前状态达成一致意见。
6.2.6.3 pg状态
如果你执行了 ceph health 、 ceph -s 、或 ceph -w 命令,你也许注意到了集群并非总返回 HEALTH_OK 。检查完 OSD 是否在运行后,你还应该检查 PG 的状态。你应该明白,在 PG 建立连接时集群不会返回 HEALTH_OK :

1,刚刚创建了一个存储池,PG 还没达成一致。
2,PG 正在恢复。
3,刚刚增加或删除了一个 OSD 。
4,刚刚修改了 CRUSH Map,PG 正在迁移。
5,某一 PG 的副本间的数据不一致。
6,Ceph 正在洗刷一个 PG 的副本。
7,Ceph 没有足够可用容量来完成回填操作。

如果是前述原因之一导致了 Ceph 返回 HEALTH_WARN ,无需紧张。很多情况下,集群会自行恢复;有些时候你得采取些措施。归置 PG 的一件重要事情是保证集群启动并运行着,所有 PG 都处于 active 状态、并且最好是 clean 状态。用下列命令查看所有 PG 状态:
ceph pg stat

其结果会告诉你 PG map 的版本号( vNNNNNN )、PG 总数 x 、有多少 PG 处于某种特定状态,如 active+clean ( y )。

[root@cephmgr ~]# ceph pg stat
193 pgs: 193 active+clean; 9.8 KiB data, 135 MiB used, 12 GiB / 15 GiB avail

除了 PG 状态之外, Ceph 也会报告数据占据的空间( aa )、剩余可用空间( bb )和 PG 总容量。这些数字在某些情况下是很重要的:

集群快达到 near full ratio 或 full ratio 时。
由于 CRUSH 配置错误致使数据没能在集群内正确分布。
6.2.6.4 pg的id
PG IDs 由存储池号(不是存储池名字)、后面跟一个点( . )、再加一个 16 进制数字的 PG ID 。用 ceph osd lspools 可查看存储池号及其名字,例如,默认存储池 rbd 对应的存储池号是 0 。完整的 PG ID 格式如下:
{pool-num}.{pg-id}

比如 8.15 或者 2.1b
6.2.6.5 故障PG
如前所述,一个 PG 状态不是 active+clean 时未必有问题。一般来说,PG 卡住时 Ceph 的自修复功能可能会不起作用,卡住的状态细分为:

Unclean: PG 里有些对象的副本数未达到期望值,它们应该进行恢复。
Inactive: PG 不能处理读写请求,因为它们在等着一个持有最新数据的 OSD 回到 up 状态。
Stale: PG 处于一种未知状态,因为存储它们的 OSD 有一阵子没向 Mon 报告了(由参数 mon osd report timeout 配置)。
为找出卡住的归置组,执行:

ceph pg dump_stuck [unclean|inactive|stale|undersized|degraded]
6.2.6.6 定位对象
要把对象数据存入 Ceph 对象存储, Ceph 客户端必须:

设置对象名
指定存储池
Ceph 客户端索取最新集群 map、并用 CRUSH 算法计算对象到 PG 的映射,然后计算如何动态地把 PG 分配到 OSD 。要定位对象位置,只需要知道对象名和存储池名字:

ceph osd map {poolname} {object-name}
6.2.6.7 查看命令
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++ } /^[0-9a-f]+\.[0-9a-f]+/ { match($0,/^[0-9a-f]+/); pool=substr($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 {pg-id}

5、 查询一个pg的详细信息
	ceph pg {pg-id} 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 [<pool:int>] [<states>...] # 17为pool 的编号
	例如: ceph pg ls 17 clean

10、 查询osd包含pg的信息,过滤输出pg的状态信息
	ceph pg ls-by-osd osd.<osd id>

11、 查询pool包含pg的信息,过滤输出pg的状态信息
	ceph pg ls-by-pool <pool name>

12、 查询某个osd状态为primary pg,可以根据需要过滤状态
	ceph pg ls-by-primary osd.<osd id> clean

13、 恢复一个丢失的pg ,如果集群丢了一个或多个对象,而且必须放弃搜索这些数据,你就要把未找到的对象标记为丢失(lost )。如果所有可能的位置都查询过了,而仍找不到这些对象,你也许得放弃它们了。这可能是罕见的失 败组合导致的,集群在写入完成前,未能得知写入是否已执行。
当前只支持revert选项,它使得回滚到对象的前一个版本(如果它是新对象)或完全忽略它。要把 unfound对象标记为lost,执行命令:
	ceph pg {pg-id} mark_unfound_lost revert|delete
6.2.6.8 状态解释
Creating    当创建一个池的时候,Ceph会创建一些PG(通俗点说就是在OSD上建目录),处于创建中的PG就被标记为creating,
			当创建完之后,那些处于Acting集合 (ceph pg map 1.0 osdmap e9395 pg 1.0 (1.0) -> up [27,4,10] acting [27,4,10],
			对于pg它的三副本会分布在osd.27,osd.4,osd.10上,那么这三个OSD上的pg1.0就会发生沟通,确保状态一致)的PG就会进行peer(osd互联),
			当peering完成后,也就是这个PG的三副本状态一致后,这个PG就会变成active+clean状态,也就意味着客户端可以进行写入操作了。
            
Peering     peer过程实际上就是让三个保存同一个PG副本的OSD对保存在各自OSD上的对象状态和元数据进行协商的过程,
			但是呢peer完成并不意味着每个副本都保存着最新的数据。直到OSD的副本都完成写操作,Ceph才会通知客户端写操作完成。
			这确保了Acting集合中至少有一个副本,自最后一次成功的peer后。剩下的不好翻译因为没怎么理解。(对象和元数据的状态达成一致的过程。)

Active      当PG完成了Peer之后,就会成为active状态,这个状态意味着主从OSD的该PG都可以提供读写了。

Clean       这个状态的意思就是主从OSD已经成功peer并且没有滞后的副本。PG的正常副本数满足集群副本数。

Degraded    当客户端向一个主OSD写入一个对象时,主OSD负责向从OSD写剩下的副本, 在主OSD写完后,
            在从OSD向主OSD发送ack之前,这个PG均会处于降级状态。
            而PG处于active+degraded状态是因为一个OSD处于active状态但是这个OSD上的PG并没有保存所有的对象。
            当一个OSDdown了,Ceph会将这个OSD上的PG都标记为降级。当这个挂掉的OSD重新上线之后,OSD们必须重新peer。
            然后,客户端还是可以向一个active+degraded的PG写入的。当OSDdown掉五分钟后,集群会自动将这个OSD标为out,
            然后将缺少的PGremap到其他OSD上进行恢复以保证副本充足,这个五分钟的配置项是mon osd down out interval,默认值为300s。
            PG如果丢了对象,Ceph也会将其标记为降级。
            你可以继续访问没丢的对象,但是不能读写已经丢失的对象了。
            假设有9个OSD,三副本,然后osd.8挂了,在osd.8上的PG都会被标记为降级,
            如果osd.8不再加回到集群那么集群就会自动恢复出那个OSD上的数据,在这个场景中,PG是降级的然后恢复完后就会变成active状态。
            
Recovering  Ceph设计之初就考虑到了容错性,比如软硬件的错误。当一个OSD挂了,
            它所包含的副本内容将会落后于其他副本,当这个OSD起来之后,
            这个OSD的数据将会更新到当前最新的状态。这段时间,这个OSD上的PG就会被标记为recover。
            而recover是不容忽视的,因为有时候一个小的硬件故障可能会导致多个OSD发生一连串的问题。
            比如,如果一个机架或者机柜的路由挂了,会导致一大批OSD数据滞后,
            每个OSD在故障解决重新上线后都需要进行recover。
            Ceph提供了一些配置项,用来解决客户端请求和数据恢复的请求优先级问题,这些配置参考上面加粗的字体吧。
            
Backfilling   当一个新的OSD加入到集群后,CRUSH会重新规划PG将其他OSD上的部分PG迁移到这个新增的PG上。
            如果强制要求新OSD接受所有的PG迁入要求会极大的增加该OSD的负载。
            回填这个OSD允许进程在后端执行。一旦回填完成后,新的OSD将会承接IO请求。在回填过程中,你可能会看到如下状态:
            backfill_wait: 表明回填动作被挂起,并没有执行。
            backfill:表明回填动作正在执行。
            backfill_too_full:表明当OSD收到回填请求时,由于OSD已经满了不能再回填PG了。 
            
imcomplete: 当一个PG不能被回填时,这个PG会被认为是不完整的。
            同样,Ceph提供了一系列的参数来限制回填动作,包括osd_max_backfills:OSD最大回填PG数。
            osd_backfill_full_ratio:当OSD容量达到默认的85%是拒绝回填请求。osd_backfill_retry_interval:字面意思。
            
Remmapped   当Acting集合里面的PG组合发生变化时,数据从旧的集合迁移到新的集合中。
            这段时间可能比较久,新集合的主OSD在迁移完之前不能响应请求。
            所以新主OSD会要求旧主OSD继续服务指导PG迁移完成。
            一旦数据迁移完成,新主OSD就会生效接受请求。
            
Stale      	Ceph使用心跳来确保主机和进程都在运行,OSD进程如果不能周期性的发送心跳包,
           	那么PG就会变成stuck状态。默认情况下,OSD每半秒钟汇报一次PG,up thru,boot, failure statistics等信息,要比心跳包更会频繁一点。
           	如果主OSD不能汇报给MON或者其他OSD汇报主OSD挂了,Monitor会将主OSD上的PG标记为stale。当启动集群后,
           	直到peer过程完成,PG都会处于stale状态。而当集群运行了一段时间后,如果PG卡在stale状态,
           	说明主OSD上的PG挂了或者不能给MON发送信息。
           	
Misplaced   有一些回填的场景:PG被临时映射到一个OSD上。而这种情况实际上不应太久,
            PG可能仍然处于临时位置而不是正确的位置。这种情况下个PG就是misplaced。
            这是因为正确的副本数存在但是有个别副本保存在错误的位置上。

Incomplete  当一个PG被标记为incomplete,说明这个PG内容不完整或者peer失败,
            比如没有一个完整的OSD用来恢复数据了。
            
scrubbing   清理中,pg正在做不一致性校验。

inconsistent   不一致的,pg的副本出现不一致。比如说对象的大小不一样了。

卡住的pg状态:  
Unclean: 归置组里有些对象的副本数未达到期望次数,它们应该在恢复中;  
Inactive: 归置组不能处理读写请求,因为它们在等着一个持有最新数据的OSD 回到up 状态;  
Stale: 归置组们处于一种未知状态,因为存储它们的OSD 有一阵子没向监视器报告了
(由mon osd report timeout 配置) 
为找出卡住的归置组,执行:
ceph pg dump_stuck [unclean|inactive|stale|undersized|degraded]

6.2.7 使用套接字

Ceph 管理套接字允许你通过套接字接口查询守护进程,它们默认存在于 /var/run/ceph 下。要通过管理套接字访问某个守护进程,先登录它所在的主机、再执行下列命令:

例如下列命令查看可用的管理套接字命令:
ceph daemon {daemon—type}.{id} help

注意:管理套接字命令允许你在运行时查看和修改配置。
另外,你可以在运行时直接修改配置选项(也就是说管理套接字会绕过 Mon,不要求你直接登录宿主主机,不像 ceph {daemon-type} tell {id} injectargs 会依赖监视器)。

6.3 用户管理

6.3.1 相关概念

一:认证与授权
	Ceph使用cephx协议对客户端进行身份验证,集群中每一个Monitor节点都可以对客户端进行身份验证,所以不存在单点故障。
	cephx仅用于Ceph集群中的各组件,而不能用于非Ceph组件。它并不解决 数据传输加密问题,但也可以提高访问控制安全性问题。
二:认证授权流程如下
    •1、客户端向Monitor请求创建用户。
    •2、Monitor返回用户共享密钥给客户端,并将此用户信息共享给MDS和QSDO
    •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
		使能表示用户可以行使的能力,通俗点也可以理解为用户所拥有的权限。对于不同的对象所能使用 的权限也不一样,大致如下所示。
		
		权限包括以下
			allow,r,w,x,class-read,class-write,*,profile osd,profile bootstrap-osd
		
        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 。授予部署工具,像 ceph-disk/deploy 等等,这样它们在自举引导 OSD 时就有权限增加密钥了。
        profile mds :授权一个用户以 MDS 身份连接其它 MDS 或 Monitor。
        profile bootstrap-mds :授权用户自举引导一个 MDS。授予例如 ceph-deploy 的部署工具,这样它们在自举引导 MDS 时就有权限增加密钥了。

6.3.2 查看用户

1、 查看ceph集群中的认证用户及相关的key
ceph auth list # 简写:ceph auth ls

2、 查看某一用户详细信息
ceph auth get client.admin

3、 只查看用户的key信息
ceph auth print-key client.admin

6.3.3 增删改

一,增加用户
增加一个用户就是创建一个用户名(即 TYPE.ID)、一个密钥和任何包含在创建命令中的能力。有以下几种方式可以新增一个用户:

ceph auth add:此命令是最权威的新增用户方式。它回新建一个用户,产生一个 key ,并赋予用户任何给定的能力。

ceph auth get-or-create:这种方式通常是最便捷的一种,因为它的返回值是包含用户名(在方括号内)和密钥的格式。如果用户已经存在,该命令会返回密钥文件格式的用户名和密钥信息。可以使用 -o {filename} 选项把输入保存到一个文件中。

ceph auth get-or-create-key:该命令可以很方便地创建用户,但是只会返回用户的密钥。对于某些只需要密钥的用户(如 libvirt )来说是很有用的。如果用户已经存在,该命令仅仅返回用户的密钥。可以使用 -o {filename} 选项把输入保存到一个文件中。

例如:

ceph auth add client.john mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth get-or-create client.paul mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth get-or-create client.george mon 'allow r' osd 'allow rw pool=liverpool' -o george.keyring
ceph auth get-or-create-key client.ringo mon 'allow r' osd 'allow rw pool=liverpool' -o ringo.key

二,修改用户
ceph auth caps 命令允许你指定用户并改变用户的能力。设定新的能力会覆盖当前的能力。查看当前的能力可以使用 ceph auth get USERTYPE.USERID 命令。要增加能力,你应该在如下格式的命令中包含当前已经存在的能力:

ceph auth caps USERTYPE.USERID {daemon} 'allow [r|w|x|*|...] [pool={pool-name}] [namespace={namespace-name}]' [{daemon} 'allow [r|w|x|*|...] [pool={pool-name}] [namespace={namespace-name}]']

例如 :
ceph auth get client.john
ceph auth caps client.john mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth caps client.paul mon 'allow rw' osd 'allow rwx pool=liverpool'
ceph auth caps client.brian-manager mon 'allow *' osd 'allow *'
要移除某个能力,你可能需要进行重置。如果你想取消某个用户对特定守护进程的所有访问权限,可以指定一个空的字符串。比如:
ceph auth caps client.ringo mon ' ' osd ' '

三,删除用户
想要删除一个用户,可以用 ceph auth del 命令:
ceph auth del {TYPE}.{ID}

##注意 其中, {TYPE} 是 client,osd,mon 或 mds 的其中一种。{ID} 是用户的名字或守护进程的 ID 。

6.3.4 导入用户

使用 ceph auth import 命令并指定密钥文件,可以导入一个或多个用户:
ceph auth import -i /path/to/keyring

6.3.5 秘钥管理

当你通过客户端访问 Ceph 集群时,Ceph 客户端会使用本地的 keyring 文件。默认使用下列路径和名称的 keyring 文件:

/etc/ceph/$cluster.$name.keyring
/etc/ceph/$cluster.keyring
/etc/ceph/keyring
/etc/ceph/keyring.bin
你也可以在 ceph.conf 中另行指定 keyring 的路径,但不推荐这样做。

$cluster 元变量是你的 Ceph 集群名称,默认名称是 ceph 。$name 元变量是用户类型和 ID 。比如用户是 client.admin,那就得到 ceph.client.admin.keyring 。

本小节介绍如何使用 ceph-authtool 工具来从客户端管理 keyring 。
6.3.5.1 创建秘钥
创建一个空的 keyring 文件,使用 --create-keyring 或 -C 选项。比如:

ceph-authtool --create-keyring /path/to/keyring

创建一个包含多个用户的 keyring 文件,推荐使用 $cluster.keyring 作为文件名,并存放于 /etc/ceph 目录下。这样就无需在本地的 ceph.conf 文件中指定 keyring 的路径了。

sudo ceph-authtool -C /etc/ceph/ceph.keyring
创建仅包含一个用户的 keyring 文件时,建议使用集群名、用户类型和用户名称作为文件名,并存放于 /etc/ceph 目录下。
6.3.5.2 增加用户
为了获取某个用户的 keyring 文件,可以使用 ceph auth get 命令加 -o 选项,以 keyring 文件格式来保存输出。比如:

ceph auth get client.admin -o /etc/ceph/ceph.client.admin.keyring

当你想要向 keyring 文件中导入某个用户时,可以使用 ceph-authtool 来指定目的和源 keyring 文件。比如:

ceph-authtool /etc/ceph/ceph.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring

6.3.5.3 导出秘钥
导出用户秘钥到指定文件
ceph auth export {TYPE}.{ID} -o /path/to/keyring
例如:
ceph auth export osd.1 -o aaa
6.3.5.4 创建用户
可以在 Ceph 客户端直接创建用户、密钥和能力。然后再导入 Ceph 集群。比如:

sudo ceph-authtool -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx' /etc/ceph/ceph.keyring

创建 keyring 文件、增加用户也可以同时进行。比如:

sudo ceph-authtool -C /etc/ceph/ceph.keyring -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx' --gen-key
上述步骤中,新用户 client.ringo 仅存在于 keyring 文件中,还需要把新用户加入到 Ceph 集群中。

sudo ceph auth add client.ringo -i /etc/ceph/ceph.keyring   //把新用户加入到 Ceph 集群中
6.3.5.5 修改用户
修改记录在 keyring 文件中的用户能力时,需要指定 keyring 、用户和新的能力选项。比如:

sudo ceph-authtool /etc/ceph/ceph.keyring -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx'

更新 Ceph 存储集群的用户,你必须更新 keyring 文件中对应用户入口的信息。

sudo ceph auth import -i /etc/ceph/ceph.keyring
6.3.5.6 应用场景(重要)
在一个CEPH集群中,用户想要使用存储池,有时为了方便,将Admin用户的kering拷贝给用户,那用户就能通过CEPH客户端,控制集群。倘若用户失手,删掉OSD等,将导致灾难。需要赋予该用户一个独有的权限。
解决方案:
第一步 确认用户的存储池

第二步 为用户的存储池创建一个kerying

ceph auth get-or-create client.kyc mon 'allow r' osd 'profile rbd pool=yucheng_pool' > ceph.client.kyc.keyring

// 其中kyc为用户名,yucheng_pool 为存储池名

第三步 CEPH客户端访问集群方法
首先,需要在机器上安装ceph客户端
然后,将两个文件拷贝到客户端所在节点的/etc/ceph目录下

最后测试

倘若不指定用户,则必然无法查看。

需要使用 --user 加上用户名

ceph -s --user kyc

6.3.6 命令行使用

Ceph 支持通过下列方式使用用户名称和密钥。

--id | --user

描述: Ceph 通过类型和 ID 来确定用户,如 TYPE.ID 或 client.admin, client.user1 。使用 --id 或 --user 选项指定用户的 ID,比如,指定使用 client.foo 用户:

ceph --id foo --keyring /path/to/keyring health
ceph --user foo --keyring /path/to/keyring health

--name | -n

描述: 使用 —name 或 -n 选项指定用户的全名( TYPE.ID ),比如:

ceph --name client.foo --keyring /path/to/keyring health
ceph -n client.foo --keyring /path/to/keyring health
--keyring

描述: 指定包含一个或多个用户及其密钥的 keyring 文件路径。 --secret 选项提供同样的功能,但对 Ceph RADOS Gateway 不生效( --secret 选项有其他的作用)。比如:

sudo rbd map --id foo --keyring /path/to/keyring mypool/myimage

6.4 存储池pool

6.4.1 相关概念

如果你开始部署集群时没有创建存储池, Ceph 会用默认存储池 rbd 存放数据。存储池提供的功能:

自恢复力: 你可以设置在不丢数据的前提下允许多少 OSD 失效。对多副本存储池来说,此值是一对象应达到的副本数。典型配置是存储一个对象和它的一个副本(即 size = 2 ),但你可以更改副本数;对纠删编码的存储池来说,此值是编码块数(即纠删码配置里的 m = 2 )。
归置组: 你可以设置一个存储池的 PG 数量。典型配置给每个 OSD 分配大约 100 个 PG,这样,不用过多计算资源就能得到较优的均衡。配置了多个存储池时,要考虑到这些存储池和整个集群的 PG 数量要合理。
CRUSH 规则: 当你在存储池里存数据的时候,与此存储池相关联的 CRUSH 规则集可控制 CRUSH 算法,并以此操纵集群内对象及其副本的复制(或纠删码编码的存储池里的数据块)。你可以自定义存储池的 CRUSH 规则。
快照: 用 ceph osd pool mksnap 创建快照的时候,实际上创建了某一特定存储池的快照。
要把数据组织到存储池里,你可以列出、创建、删除存储池,也可以查看每个存储池的使用统计数据

6.4.2 增删改查

1、创建存储池
    # 语法:ceph osd pool create <pool name> <pg num> <pgp num> [type] 
    pool name :存储池名称,必须唯一。
    pg num :存储池中的pg数量。
    pgp num :用于归置的pg数量,默认与pg数量相等。
    type :指定存储池的类型,有replicated和erasure,默认为replicated。

    #例:创建一个副本池
    ceph osd pool create <pool name> 32 32	# 生路 type,默认为replicated
    1234567
2、 修改存储池的pg数
注意:在更改pool的PG数量时,需同时更改PGP的数量。PGP是为了管理placement而存在的专门的 PG,它和PG的数量应该保持一致。如果你增加pool的pg_num,就需要同时增加pgp_num,保持它们 大小一致,这样集群才能正常rebalancing。
	ceph osd pool set <pool name> pg_num 60
	ceph osd pool set <pool name> pgp_num 60
3、 查看存储池
	#查看ceph集群中的pool数量
    ceph osd lspools
    #查看名字与详情
    ceph osd pool ls
    ceph osd pool ls detail
    #查看状态
    ceph osd pool stats
4、 重命名
	ceph osd pool rename <old name> <new name>
	
5、 在集群中删除一个pool,注意删除poolpool映射的image会直接被删除,线上操作要谨慎  存储池的名字需要重复两次
	ceph osd pool delete <pool name> <pool name> --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节点进行相应 的设置。
    解决方案:
    #=============方案 1==================
    ceph tell mon.* injectargs --mon_allow_pool_delete=true
    ceph osd pool delete <pool name> <pool name> --yes-i-really-really-mean-it
    册U除完成后最好把mon_allow_pool_delete改回去,降低误删的风险
    #删除后关闭允许删除存储池
	ceph tell mon.* injectargs --mon-allow-pool-delete=false
    #=============方案 2==================
    如果是测试环境,想随意删除存储池,可以在配置文件中全局开启删除存储池的功能
    #1、编辑配置文件:vi /etc/ceph/ceph.conf
    在配置文件中添加如下内容:
    [mon]
    mon allow pool delete = true
    #2、推送配置文件
    ceph-deploy --overwrite-conf config push cephmgr cephstore2 cephstore3 cephstore4 cephstore5
    #3、重启ceph-mon服务:
    systemctl restart ceph-mon.target
    #4、重新执行删除pool命令即可
    ceph osd pool delete <pool name> <pool name> --yes-i-really-really-mean-it
6、修改rule    
  	ceph osd pool set mypool crush_rule  egon_rule # 修改 mypool 的 crush_rule 为 egon_rule  //详见 6.3.11 rules

6.4.3 配置配额

1、 为一个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

6.4.4 配置参数

1、 配置参数 
	对于存储池的配置参数可以通过下面命令获取。
	ceph osd pool get <pool name> [key name]
	例如:
	ceph osd pool get <pool name> size  //获取参数
	
	ceph osd pool set <pool name> <key> <value> 
	例如:
	#修改pool的最大副本数与最小副本数  //配置参数 
    ceph osd pool set <pool name> min_size 1
    ceph osd pool set <pool name> 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:整理存储池的最大时间间隔

6.4.5 快照

1、快照 
	创建存储池快照需要大量的存储空间,取决于存储池的大小。创建快照,以下两条命令都可以。
        ceph osd pool mksnap <pool name> <snap name>
        rados -p <pool name> mksnap <snap name>
	列出快照。
		rados -p <pool name> lssnap
	回滚至存储池快照。
		rados -p <pool name> rollback <obj-name> <snap name> # 只能回复某个对象
	删除存储池快照,以下两条命令都可以删除。
		ceph osd pool rmsnap <pool name> <snap name>
		rados -p <pool name> rmsnap <snap name>
    提示:
    	Pool池的快照,相对来说是有局限性的,没办法直接恢复快照里边全部。bject对象文件,只能一个个来恢复,保存点密码文件应该还是可以的。这样的设计效果,猜测有可能是因为如果pool池直接整体恢复,会导致整个ceph集群数据混乱,毕竟集群中数据是分布式存放的!

6.4.6 压缩

1、压缩
	如果使用bulestore存储引擎,默认提供数据压缩,以节约磁盘空间。启用压缩。
	#设置压缩算法
    	ceph osd pool set <pool name> compression_algorithm snappy # 默 认 算 法 为 snappy
	注意:snappy:压缩使用的算法,还有有none、zlib、Iz4、zstd和snappy等算法。
		默认为sanppy。zstd压缩 比好,但消耗CPU, Iz4和snappy对CPU占用较低,不建议使用zlib。
	
    #设置压缩模式 
		ceph osd pool set <pool name> compression_mode aggressive
	#例如
		ceph osd pool set mypool compression_mode aggressive  #mypool是 poolname
	
	压缩的模式有none、aggressive、passive和force
    •默认none。表示不压缩
    •passive表示提示COMPRESS IB LE才压缩
    •aggressive表示提示INCOMPRESS IB LE不压缩,其它都压缩
    •force表示始终压缩。压缩参数。
	参数:
	compression_algorithm #压缩算法 
    compression_mode #压缩模式 
    compression_required_ratio #压缩后与压缩前的压缩比,默认为.875 
    compression_max_blob_size: #大于此的块在被压缩之前被分解成更小的 blob(块),此设置将覆盖 bluestore 压缩 max blob * 的全局设置。 
    compression_min_blob_size:#小于此的块不压缩, 此设置将覆盖 bluestore 压缩 min blob *的全局设置。
    
    全局压缩选项,这些可以配置到ceph.conf配置文件,作用于所有存储池。 
    bluestore_compression_algorithm #压缩算法 
    bluestore_compression_mode #压缩模式 
    bluestore_compression_required_ratio #压缩后与压缩前的压缩比,默认为.875 
    bluestore_compression_min_blob_size #小于它的块不会被压缩,默认 0 
    bluestore_compression_max_blob_size #大于它的块在压缩前会被拆成更小的块,默认 0 
    bluestore_compression_min_blob_size_ssd #默认 8k 
    bluestore_compression_max_blob_size_ssd #默认 64k 
    bluestore_compression_min_blob_size_hdd #默认 128k 
    bluestore_compression_max_blob_size_hdd #默认 512k

6.4.7 统计

要查看某存储池的使用统计信息,执行命令:
rados df

6.5 crushmap

6.5.1 相关概念

CRUSH 算法通过计算数据存储位置来确定如何存储和检索。 CRUSH 授权 Ceph 客户端直接连接 OSD ,而非通过一个中央服务器或代理。数据存储、检索算法的使用,使 Ceph 避免了单点故障、性能瓶颈、和伸缩的物理限制。

CRUSH 需要一张集群的 Map,且使用 CRUSH Map 把数据伪随机地、尽量平均地分布到整个集群的 OSD 里。CRUSH Map 包含 OSD 列表、把设备汇聚为物理位置的“桶”列表、和指示 CRUSH 如何复制存储池里的数据的规则列表。

6.5.2 提取编译

1、 提取crushmap图
	# 提取最新crush图
	# ceph osd getcrushmap -o {compiled-crushmap-filename}
	例如 ceph osd getcrushmap -o /tmp/crush
2、 反编译crushmap图
	# crushtool -d {compiled-crushmap-filename} -o {decompiled-crushmap-filename}
	例如 crushtool -d /tmp/crush -o /tmp/decompiled_crush

6.5.3 注入crushmap

3、 注入crushmap图
	#例如修改故障域host为osd,需要提取crush图,修改故障域,然后注入crush图
	# 编译crush图
	# crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename}
	例如 crushtool -c /tmp/decompiled_crush -o /tmp/crush_new
	#注入crush图
	# ceph osd setcrushmap -i {compiled-crushmap-filename}
	例如 ceph osd setcrushmap -i /tmp/crush_new

6.5.4 构建故障域

使用命令:
ceph osd tree  //先查看 osd树状图 

[root@cephmgr tmp]# ceph osd tree
ID  CLASS  WEIGHT   TYPE NAME            STATUS  REWEIGHT  PRI-AFF
-1         0.01469  root default                                  
-3         0.00490      host cephstore2                           
 0    hdd  0.00490          osd.0            up   1.00000  1.00000
-5         0.00490      host cephstore3                           
 1    hdd  0.00490          osd.1            up   1.00000  1.00000
-7         0.00490      host cephstore4                           
 2    hdd  0.00490          osd.2            up   1.00000  1.00000
 
 开始构建:
 # 创建数据中心:datacenter0
ceph osd crush add-bucket datacenter0 datacenter

# 创建机房:room0 
ceph osd crush add-bucket room0 room

# 创建机架:rack0、rack1、rack2
ceph osd crush add-bucket rack2 rack
ceph osd crush add-bucket rack3 rack
ceph osd crush add-bucket rack4 rack

# 把机房room0移动到数据中心datacenter0下
ceph osd crush move room0 datacenter=datacenter0

# 把机架rack0、rack1、rack2移动到机房room0下
ceph osd crush move rack2 room=room0
ceph osd crush move rack3 room=room0
ceph osd crush move rack4 room=room0

# 把主机osd01移动到:datacenter0/room0/rack0下
ceph osd crush move cephstore2 datacenter=datacenter0 room=room0 rack=rack2

# 把主机osd02移动到:datacenter0/room0/rack1下
ceph osd crush move cephstore3 datacenter=datacenter0 room=room0 rack=rack3

# 把主机osd03移动到:datacenter0/room0/rack2下
ceph osd crush move cephstore4 datacenter=datacenter0 room=room0 rack=rack4
使用命令:
ceph osd tree  //再次查看 osd树状图 
[root@cephmgr tmp]# ceph osd tree
ID   CLASS  WEIGHT   TYPE NAME                    STATUS  REWEIGHT  PRI-AFF
 -9         0.01469  datacenter datacenter0                                
-10         0.01469      room room0                                        
-11         0.00490          rack rack0                                    
 -3         0.00490              host cephstore2                           
  0    hdd  0.00490                  osd.0            up   1.00000  1.00000
-12         0.00490          rack rack1                                    
 -5         0.00490              host cephstore3                           
  1    hdd  0.00490                  osd.1            up   1.00000  1.00000
-13         0.00490          rack rack2                                    
 -7         0.00490              host cephstore4                           
  2    hdd  0.00490                  osd.2            up   1.00000  1.00000
 -1               0  root default     
 
 故障域 如下图所示:

img

6.5.5 设置crush class

1,查看当前集群布局:
ceph osd tree

2,查看CLASS 类型列表: 
ceph osd crush class ls

3,设置osd的class为ssd: 
ceph osd crush set-device-class ssd osd.<id>
或者使用下面命令 循环设置:
for i in 0 1 2;do ceph osd crush set-device-class ssd osd.$i;done

4,删除osd的class:
ceph osd crush rm-device-class ssd osd.<id>
或者使用下面命令 循环设置:
for i in 0 1 2;do ceph osd crush rm-device-class osd.$i;done

6.5.6 crushmap参数

CRUSH Map 参数
CRUSH Map 主要有 4 个段落。

设备:由任意对象存储设备组成,即对应一个 ceph-osd进程的存储器。 Ceph 配置文件里的每个 OSD 都应该有一个设备。
桶类型: 定义了 CRUSH 分级结构里要用的桶类型( types ),桶由逐级汇聚的存储位置(如行、机柜、机箱、主机等等)及其权重组成。
桶实例: 定义了桶类型后,还必须声明主机的桶类型、以及规划的其它故障域。
规则: 由选择桶的方法组成。
CRUSH Map 之设备
为把 PG 映射到 OSD , CRUSH Map 需要 OSD 列表(即配置文件所定义的 OSD 守护进程名称),所以它们首先出现在 CRUSH Map 里。要在 CRUSH Map 里声明一个设备,在设备列表后面新建一行,输入 device 、之后是唯一的数字 ID 、之后是相应的 ceph-osd 守护进程实例名字。
# devices
device {num} {osd.name}


CRUSH Map 之桶类型
CRUSH Map 里的第二个列表定义了 bucket (桶)类型,桶简化了节点和叶子层次。节点(或非叶子)桶在分级结构里一般表示物理位置,节点汇聚了其它节点或叶子,叶桶表示 ceph-osd 守护进程及其对应的存储媒体。

要往 CRUSH Map 中增加一种 bucket 类型,在现有桶类型列表下方新增一行,输入 type 、之后是惟一数字 ID 和一个桶名。按惯例,会有一个叶子桶为 type 0 ,然而你可以指定任何名字(如 osd 、 disk 、 drive 、 storage 等等):

# types
type {num} {bucket-name}

CRUSH Map 之桶层次
CRUSH 算法根据各设备的权重、大致统一的概率把数据对象分布到存储设备中。 CRUSH 根据你定义的集群运行图分布对象及其副本, CRUSH Map 表达了可用存储设备以及包含它们的逻辑单元。

要把 PG 映射到跨故障域的 OSD ,一个 CRUSH Map 需定义一系列分级桶类型(即现有 CRUSH Map 的 # type 下)。创建桶分级结构的目的是按故障域隔离叶子节点,像主机、机箱、机柜、电力分配单元、机群、行、房间、和数据中心。除了表示叶子节点的 OSD ,其它分级结构都是任意的,你可以按需定义。

声明一个桶实例时,你必须指定其类型、惟一名称(字符串)、惟一负整数 ID (可选)、指定和各条目总容量/能力相关的权重、指定桶算法(通常是 straw )、和哈希(通常为 0 ,表示哈希算法 rjenkins1 )。一个桶可以包含一到多个条目,这些条目可以由节点桶或叶子组成,它们可以有个权重用来反映条目的相对权重。

你可以按下列语法声明一个节点桶:
[bucket-type] [bucket-name] {
        id [a unique negative numeric ID]
        weight [the relative capacity/capability of the item(s)]
        alg [the bucket type: uniform | list | tree | straw ]
        hash [the hash type: 0 by default]
        item [item-name] weight [weight]
}

Ceph 用双精度类型数据表示桶权重。权重和设备容量不同,我们建议用 1.00 作为 1TB 存储设备的相对权重,这样 0.5 的权重大概代表 500GB 、 3.00 大概代表 3TB 。较高级桶的权重是所有叶子桶的权重之和。

一个桶的权重是一维的,你也可以计算条目权重来反映存储设备性能。例如,如果你有很多 1TB 的硬盘,其中一些数据传输速率相对低、其他的数据传输率相对高,即使它们容量相同,也应该设置不同的权重(如给吞吐量较低的硬盘设置权重 0.8 ,较高的设置 1.20 )。

CRUSH Map 之规则
CRUSH Map 支持“ CRUSH 规则”的概念,用以确定一个存储池里数据的分布。CRUSH 规则定义了归置和复制策略、或分布策略,用它可以规定 CRUSH 如何放置对象副本。对大型集群来说,你可能创建很多存储池,且每个存储池都有它自己的 CRUSH 规则集和规则。默认的 CRUSH Map 里,每个存储池有一条规则、一个规则集被分配到每个默认存储池。

注意: 大多数情况下,你都不需要修改默认规则。新创建存储池的默认规则集是 0 。

规则格式如下:

rule <rulename> {
        id <id>
        type [ replicated | erasure ]
        min_size <min-size>
        max_size <max-size>
        step take <bucket-type>
        step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>
        step emit
}

参数说明:

id:区分一条规则属于某个规则集的手段。给存储池设置规则集后激活。
type:规则类型,目前仅支持 replicated 和 erasure ,默认是 replicated 。
min_size:可以选择此规则的存储池最小副本数。
max_size:可以选择此规则的存储池最大副本数。
step take <bucket-name>:选取起始的桶名,并迭代到树底。

step [choose|chooseleaf] [firstn|indep] <N> <bucket-type> 这个表示 选择策略

    <1>: choose/chooseleaf
    choose表示选择结果类型为故障域(由<4>指定)
    chooseleaf表示在确定故障域后,还必须选出该域下面的OSD节点(即leaf)

    <2>: firstn/indep
    firstn: 适用于副本池,选择结果中rep(replica,指一份副本或者EC中的一个分块,下同)位置无明显意义
    indep: 适用于EC池,选择结果中rep位置不可随意变动
    举例来说,副本池中每份副本保存的是完全相同的数据,因此选择结果为[0, 1, 2](数字代表OSD编号)与[0, 2, 1]并无大的不同。
    但是EC池不一样,在2+1的配比下前两份是数据块,最后一份是校验块,后两份rep位置一交换就会导致数据出错。

    <3>: num_reps
    这个整数值指定需要选择的rep数目,可以是正值负值或0。

    正整数值即代表要选择的副本数,非常直观
    0表示的是与实际逻辑池的size相等;也就是说,如果2副本池用了这个rule,0就代表了2;如果3副本池用了此rule,0就相当于3
    负整数值代表与实际逻辑池size的差值;如果3副本池使用此rule将该值设为了-1,那边该策略只会选择出2个reps

    <4>: failure domain  bucket-type 
    指定故障域类型;CRUSH确保同一故障域最多只会被选中一次。


step emit:输出当前值并清空堆栈。通常用于规则末尾,也适用于相同规则应用到不同树的情况。


-------------------------------------------------------------------------------------------------------------------------------
参考设置 

# tunable:这里都是一些微调的参数,通常不建议修改,一般得集群规模够大,到了专家级别才会去修改。
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

# devices:这下面将列出集群中的所有OSD基本信息。
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd

# types:这里列出集中可用的故障域,可以自定义。
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。

# buckets:这里就是定义故障域名。 不展开讲了

# rules:这里定义的是存储池的规则
# 1、type为存储池的类型,replicated代表副本池。如果有纠删码池也会创建出一个默认的配置,这里没有。
# 2、min_size代表允许的最少副本数
# 3、max_size允许的最大副本数
# 4、step代表每一个步骤,基本第二步为选择如何找到OSD,需要指定故障域级别,这里定义为host,如果有机房或者其它的,可以将故障域定义为更高的级别。
rule replicated_rule {
    id 0
    type replicated
    min_size 1
    max_size 10
    step take default  #这边 可以加入 class  例如  step take default class ssd
    step chooseleaf firstn 0 type host
    step emit
}
--------------------------------------------------------------------------------------------------------------------------------
//如果做了修改,,修改完
crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename} //编译成二进制文件 

ceph osd setcrushmap -i {compiled-crushmap-filename}   // 注入

6.5.7 新增rule

crushmap配置中最核心的当属rule了,crush rule决定了三点重要事项:

1、从OSDMap中的哪个节点开始查找
2、使用那个节点作为故障隔离域
3、定位副本的搜索模式(广度优先 or 深度优先)。

使用命令创建 
ceph osd crush rule create-replicated <name> <root> <type> [<class>] 
ceph osd crush rule create-replicated ws_custom_rule datacenter0 host ssd 

# rules
rule ws_custom_rule                       			#规则集的命名,创建pool时可以指定rule集  当前命名的rule名字为 ws_custom_rule
{
    id 1                                            #rules集的编号,顺序编即可
    type replicated                                	#定义pool类型为replicated(还有esurecode模式)
    min_size 1                                     	#pool中最小指定的副本数量不能小1\
	max_size 10                                    	#pool中最大指定的副本数量不能大于10   
    
							                        #定义pg查找副本的入口点  这里 datacenter0 就是我们自定义的 
	step take datacenter0 class ssd					#这边 可以加入 class  例如  step take datacenter0 class ssd
													
	step chooseleaf firstn 0 type host         	#选叶子节点、深度优先、隔离host 隔离默认为host,设置为host
	step emit                                      	#结束
}


pg 选择osd的过程,首先要知道在rules中 指明从osdmap中哪个节点开始查找,入口点默认为default也就是root节点,
然后隔离域为host节点(也就是同一个host下面不能选择两个子节点)。由default到3个host的选择过程,
这里由default根据节点的bucket类型选择下一个子节点,由子节点再根据本身的类型继续选择,直到选择到host,然后在host下选择一个osd。

--------------------------------------------------------------------------------------------------------------------------------
//增加 完 做以下操作 才能 配置成功 
crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename} //编译成二进制文件 

ceph osd setcrushmap -i {compiled-crushmap-filename}   // 注入

6.5.8 设置rule

重新导入集群后,需要把之前存在过的pool池的crush_rule都修一下,否则集群会出现unknown状态有无法达到activee+clean状态

ceph osd pool set <pool name> crush_rule <rule name>

6.5.9 注意事项(重要)

**注意:如果设置了故障域,则必须设置rule以及 更新牵扯到的pool的rule 否则会出问题**

6.6 集群配置

6.6.1 查看配置

如果你的 Ceph 存储集群在运行,而你想看一个在运行进程的配置,用下面的命令:
ceph daemon {daemon-type}.{id} config show | less

如果你现在位于 osd.0 所在的主机,命令将是:
ceph daemon osd.0 config show | less

或者可以在 ceph.conf文件里看

6.6.2 修改配置

6.6.2.1 修改文件
修改配置文件
Ceph 配置文件可用于配置存储集群内的所有守护进程、或者某一类型的所有守护进程。要配置一系列守护进程,这些配置必须位于能收到配置的段落之下,比如:

[global]
描述: [global] 下的配置影响 Ceph 集群里的所有守护进程。
实例: auth supported = cephx

[osd]
描述: [osd] 下的配置影响存储集群里的所有 ceph-osd 进程,并且会覆盖 [global] 下的同一选项。
实例: osd journal size = 1000

[mon]
描述: [mon] 下的配置影响集群里的所有 ceph-mon 进程,并且会覆盖 [global] 下的同一选项。
实例: mon addr = 10.0.0.101:6789

[mds]
描述: [mds] 下的配置影响集群里的所有 ceph-mds 进程,并且会覆盖 [global] 下的同一选项。
实例: host = myserver01

[client]
描述: [client] 下的配置影响所有客户端(如挂载的 Ceph 文件系统、挂载的块设备等等)。
实例: log file = /var/log/ceph/radosgw.log

全局设置影响集群内所有守护进程的例程,所以 [global] 可用于设置适用所有守护进程的选项。但可以用这些覆盖 [global] 设置:

1,在 [osd] 、 [mon] 、 [mds] 下更改某一类进程的配置。
2,更改特定进程的设置,如 [osd.1] 。
覆盖全局设置会影响所有子进程,明确剔除的例外。
6.6.2.2 动态调整
有时候需要更改服务的配置,但不想重启服务,或者是临时修改,此时我们就可以通过admin sockets 直接与守护进程交互。如查看和修改守护进程的配置参数。
Ceph 可以在运行时更改 ceph-osd 、 ceph-mon 、 ceph-mds 守护进程的配置,此功能在增加/降低日志输出、启用/禁用调试设置、甚至是运行时优化的时候非常有用。Ceph 集群提供两种方式的调整,使用 tell 的方式和 daemon 设置的方式。

•方式一: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.monOl 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设置,可以使用*
    
•方式二:daemon子命令
命令格式如下,需要登录到守护进程所在的那台主机上执行
	ceph daemon {daemon—type}.{id} config set {name}={value}
	例。
	ssh root@mon01
	ceph daemon mon.monOl config set mon allow pool delete false
	
•方式三:通过socket文件
命令格式如下
	ceph --admin-daemon /var/run/ceph/$cluster-$type.$id.asok command
    常用command如下
        help
        config get parameter
        config set parameter
        config show
        perf dump
	例如: 
    #1、查看帮助
    ceph --admin-daemon /var/run/ceph/ceph-mds.mon01.asok help
    #2、查看配置项
    ceph --admin-daemon /var/run/ceph/ceph-mds.mon01.asok config get
    mon allow pool delete
    #3、设置
    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
6.6.2.3 两者区别
注意: 重启进程后配置会恢复到默认参数,在进行在线调整后,如果这个参数是后续是需要使用的,那么就需要将相关的参数写入到配置文件 ceph.conf 当中。

两种设置方式的使用场景
使用 tell 的方式适合对整个集群进行设置,使用 * 号进行匹配,就可以对整个集群的角色进行设置。而出现节点异常无法设置时候,只会在命令行当中进行报错,不太便于查找。

使用 daemon 进行设置的方式就是一个个的去设置,这样可以比较好的反馈,此方法是需要在设置的角色所在的主机上进行设置。

6.7 日志系统

6.7.1 日志介绍

ceph的日志默认输入到/var/log/ceph目录下,可以进入到该目录下,查找相应信息。

6.7.2 日志级别

Ceph 的日志级别范围是 1~20 , 1 是简洁、 20 是详细。通常,内存驻留日志不会发送到输出日志
除非:

致命信号出现,或者
源码中的 assert 被触发,或者
明确要求发送。

如果您指定,Ceph 会将其视为日志级别和内存级别。您也可以单独指定它们。第一个设置是日志级别,第二个设置是内存级别。您必须用正斜杠 (/) 分隔它们。例如,如果要将子系统的调试日志记录级别设置为并将其内存级别设置为,则可以将其指定为。例如:
debug ms = 1/5 或者 debug ms = 5 如果是第二种,则代表 日志级别和内存级别都是 5

6.7.3 级别设置

查看日志级别 
如果你想在运行时查看某一进程的配置,必须先登录对应主机,然后执行命令:
ceph daemon {daemon-name} config show | grep debug 可以查看 所有 debug的信息
例如
ceph daemon osd.0 config show | grep debug

一,运行时 设置级别 
1,要在运行时激活 Ceph 的调试输出(即 dout() ),用 ceph tell 命令把参数注入运行时配置:

ceph tell {daemon-type}.{daemon id or *} injectargs --{name} {value} [--{name} {value}]

用 osd 、 mon 或 mds 替代 {daemon-type} 。还可以用星号( * )把配置应用到同类型的所有守护进程,或者指定具体守护进程的 ID 。例如,要给名为 ods.0 的 ceph-osd 守护进程提高调试级别,用下列命令:

ceph tell osd.0 injectargs --debug-osd 0/5

ceph tell 命令会通过 monitor 起作用。如果你不能绑定 monitor,仍可以登录你要改的那台主机然后用 ceph daemon 来更改。例如:

ceph daemon osd.0 config set debug_osd 0/5

二,启动时 设置级别
要在启动时激活调试输出(即 dout() ),你得把选项加入配置文件。各进程共有配置可写在配置文件的 [global] 段下,某类进程的配置可写在对应的守护进程段下(如 [mon] 、 [osd] 、 [mds] )。例如:

[global]
        debug ms = 1/5
[mon]
        debug mon = 20
        debug paxos = 1/5
        debug auth = 2
[osd]
        debug osd = 1/5
        debug filestore = 1/5
        debug journal = 1
        debug monc = 5/20
[mds]
        debug mds = 1
        debug mds balancer = 1
        debug mds log = 1
        debug mds migrator = 1
        
把上面内容复制到ceph.conf里, 使用推送命令,推送给所有节点

6.7.4 日志更迭

如果你的系统盘比较满,可以修改 /etc/logrotate.d/ceph 内的日志滚动配置以加快滚动。在滚动频率后增加一个日志 size 选项(达到此大小就滚动)来加快滚动(通过 cronjob )。例如默认配置大致如此:

rotate 7
weekly
compress
sharedscripts

增加一个 size 选项。

rotate 7
weekly
size 500M
compress
sharedscripts

然后,打开 crontab 编辑器。

crontab -e

最后,增加一条用以检查 /etc/logrorate.d/ceph 文件的语句。

30 * * * * /usr/sbin/logrotate /etc/logrotate.d/ceph >/dev/null 2>&1

本例中每 30 分钟检查一次 /etc/logrorate.d/ceph 文件。

6.7.5 注意事项

Ceph 子系统及其默认日志和内存级别具体见
https://docs.ceph.com/en/latest/rados/troubleshooting/log-and-debug/
一旦你完成调试,应该恢复默认值,或一个适合平常运营的级别。


default        			0        5        
lockdep        			0        1        
context        			0        1        
crush        			1        1        
mds       			 	1        5        
mds balancer        	1        5        
mds locker        		1        5        
mds log        			1        5        
mds log expire        	1        5        
mds migrator        	1        5        
buffer        			0        1        
timer        			0        1        
filer       	 		0        1        
striper        			0        1        
objecter        		0        1        
rados        			0        5        
rbd        				0        5        
rbd mirror        		0        5        
rbd replay        		0        5        
journaler        		0        5        
objectcacher        	0        5        
client        			0        5        
osd        				1        5        
optracker        		0        5        
objclass        		0        5        
filestore        		1        3        
journal        			1        3        
ms        				0        5        
mon        				1        5        
monc        			0        10        
paxos        			1        5        
tp       		 		0        5        
auth        			1        5        
crypto        			1        5        
finisher        		1        1        
reserver        		1        1        
heartbeatmap        	1        5        
perfcounter        		1        5        
rgw        				1        5        
rgw sync        		1        5        
civetweb        		1        10        
javaclient        		1        5        
asok       				1        5        
throttle        		1        1        
refs        			0        0        
compressor        		1        5        
bluestore        		1        5       
bluefs        			1        5        
bdev        			1        3        
kstore        			1        5        
rocksdb        			4        5        
leveldb        			4        5        
memdb        			4        5        
fuse        			1        5        
mgr        				1        5       
 mgrc        			1        5        
 dpdk        			1        5        
 eventtrace        		1        5

6.8 osd相关

6.8.1 一般设置

1、 设置osd的权重//注意,这个和 osd的crush权重不是一个东西,详见  https://www.cnblogs.com/chris-cp/p/6136831.html
	ceph osd reweight 3 0.5 # 把 o sd.3 的权重改为0.5

2、 暂停osd (暂停后整个ceph集群不再接收数据)
	ceph osd pause #暂停的是所有的osd

3、 再次开启osd (开启后再次接收数据)
	ceph osd unpause

4、 设置标志flags,不允许关闭osd、解决网络不稳定,osd状态不断切换的问题
    ceph osd set nodown
    取消设置
    ceph osd unset nodown
    
5、 设置osd的crush权重: //注意,这个和 osd的权重不是一个东西, 详见  https://www.cnblogs.com/chris-cp/p/6136831.html
	ceph osd crush reweight osd.3 3.0
	
6、 主亲和性
	# Ceph 客户端读写数据时,总是连接 acting set 里的主 OSD (如 [2, 3, 4] 中, osd.2 是主的)。
	# 有时候某个 OSD 与其它的相比并不适合做主 OSD (比如其硬盘慢、或控制器慢),最大化硬件利用率时为防止性能瓶颈(特别是读操作),
	# 你可以调整 OSD 的主亲和性,这样 CRUSH 就尽量不把它用作 acting set 里的主 OSD 了。
 
	#ceph osd primary-affinity <osd-id> <weight>   
 
	例如  ceph osd primary-affinity 2 1.0

	#主亲和性默认为 1 (就是说此 OSD 可作为主 OSD )。此值合法范围为 0-1 ,其中 0 意为此 OSD 不能用作主的,#1 意为 OSD 可用作主的;此权重小于 1 时, CRUSH 选择主 OSD 时选中它的可能性低
	
7、 停止自动均衡
	# 在集群维护过程中,如果某一个机架或者主机故障,而此时不想在停机维护osd过程中让crush自动均衡,提前设置为noout
	ceph osd set noout
	
8、 取消停止自动均衡
 	ceph osd unset noout

6.8.2 基本操作

1、 下线OSD:
	#让ID为3的osd down 掉,此时该 osd 不接受读写请求,但 osd 还是存活的,即对应down in状态
	ceph osd down 3
2、 上线OSD:
	#让ID为3的osd up起来,此时该 osd 接受读写请求,对应up in状态
  	ceph osd up 3
3、 OSD踢出集群:
	#让ID为3的osd踢出集群,对应down out状态
	ceph osd out 3
4、 OSD加入集群:
	#让ID为3的osd加入集群,对应up in状态,即上线一个OSD
	ceph osd in 3
5、 删除OSD:
	#在集群中删除一个OSD,需要先停止OSD,即stop osd
	ceph osd rm osd.3
6、 从crush map中删除OSD:
	#在crush map中删除一个OSD
 	ceph osd crush rm osd.3
7、 删除 OSD 认证密钥 	
 	ceph auth del osd.3
8、 删除host节点:
	#从集群中删除一个host节点
  	ceph osd crush rm node1

6.8.3 osd的flags

noin   			通常和noout一起用防止OSD up/down跳来跳去    
noout  			MON在过了300秒(mon_osd_down_out_interval)后自动将down掉的OSD标记为out,
				一旦out数据就会开始迁移,建议在处理故障期间设置该标记,避免数据迁移。
       			(故障处理的第一要则设置osd noout 防止数据迁移。ceph osd set noout ,ceph osd unset noout)
       			
noup   			通常和nodwon一起用解决OSD up/down跳来跳去
nodown 			网络问题可能会影响到Ceph进程之间的心跳,有时候OSD进程还在,却被其他OSD一起举报标记为down,导致不必要的损耗,如果确定OSD进程始终正常  
       			可以设置nodown标记防止OSD被误标记为down.
full   			如果集群快要满了,你可以预先将其设置为FULL,注意这个设置会停止写操作。(有没有效需要实际测试)
pause  			这个标记会停止一切客户端的读写,但是集群依旧保持正常运行。
nobackfill
norebalance  	这个标记通常和上面的nobackfill和下面的norecover一起设置,在操作集群(挂掉OSD或者整个节点)时,
             	如果不希望操作过程中数据发生恢复迁移等,可以设置这个标志,记得操作完后unset掉。
norecover  		也是在操作磁盘时防止数据发生恢复。

noscrub   		ceph集群不做osd清理
nodeep-scrub 	有时候在集群恢复时,scrub操作会影响到恢复的性能,和上面的noscrub一起设置来停止scrub。一般不建议打开。
notieragent  	停止tier引擎查找冷数据并下刷到后端存储。

cpeh osd set {option} 设置所有osd标志
ceph osd unset {option} 解除所有osd标志

使用下面的命令去修复pg和osd
ceph osd repair :修复一个特定的osd
ceph pg repair 修复一个特定的pg,可能会影响用户的数据,请谨慎使用。
ceph pg scrub:在指定的pg上做处理
ceph deep-scrub:在指定的pg上做深度清理。
ceph osd set pause 搬移机房时可以暂时停止读写,
ceph osd unset pause 等待客户端读写完毕了,就可以关闭集群

6.8.4 osd剔除

针对这台机器的所有osd进行以下操作:
	ceph osd crush reweight osd.{osd-num} 0 			将 osd 的权重标记为 0
	ceph -w											
	watch ceph -s										观察数据迁移

    ceph osd out {osd.num}  				 			标记为out状态,不让该osd继续承载pg 踢出集群
    
------------------------------------------------在对应的主机上执行---------------------------------------------
    systemctl status ceph-osd@{osd-num}
    systemctl stop ceph-osd@{osd-num}
    systemctl disable ceph-osd@{osd-num}
    systemctl status ceph-osd@{osd-num}					通过 systemctl 停止 osd 服务 停止osd相关进程 状态变为down
------------------------------------------------------------------------------------------------------------


    ceph osd crush remove osd.{osd.num}   				crush map 中删除osd条目
    ceph auth rm osd.{osd.num} 	 						删除 OSD 认证密钥  del和rm 都可以
    ceph osd rm osd.{osd.num}   						删除osd
    
    ceph osd purge osd.{osd.num} --yes-i-really-mean-it 清除监视器中的所有osd数据,包括osd id和crush 位置
    
    
处理配置文件:    
    如果 ceph.conf 中记载了相关的内容,则需要修改配置文件并更新到其他主机,如果没有,则忽略此步骤。
卸载 osd 挂载的磁盘:    
    df -h											
	umount /var/lib/ceph/osd/ceph-{osd-num}
	ceph-disk zap /dev/s{?}{?}							
清除主机:
	如果只想清除 /var/lib/ceph 下的数据、并保留 Ceph 安装包,可以用 purgedata 命令。
	ceph-deploy purgedata {hostname} [{hostname} ...] 	
	要清理掉 /var/lib/ceph 下的所有数据、并卸载 Ceph 软件包,用 purge 命令。 
	从远程主机上删除Ceph软件包并清除所有数据。
	
	ceph-deploy purge {hostname} [{hostname} ...]		

所有的osd节点下线删除之后:
    ceph osd crush remove {hostname}  将主机条目从crush map中删除
注意:该步骤会触发数据的重新分布。等待数据重新分布结束,整个集群会恢复到HEALTH_OK状态。

修改 crushmap:
	剔除完 osd 之后,使用 ceph -s 状态正常,但是使用 ceph osd tree 查看列表的时,却发现已经没有osd的主机依然存在。
	原因是 crushmap 的一些架构图,不会动态修改,所以需要手工的修改 crushmap。
	
    ceph osd  getcrushmap -o old.map  //导出crushmap
	crushtool -d old.map -o old.txt   //将crushmap转成文本文件,方便vim修改
	cp old.txt new.txt        //做好备份				  
	修改 new.txt, 将此 host 相关的内容删除
	  host host-name {
        xxxxx
        xxxxx
      }
      host host-name {
        xxxxx
        xxxxx
      }
      root default {
      item host-name weight 0.000
      item host-name weight 0.000
      }
	把以上的内容删除掉后,重新编译为二进制文件,并将二进制 map 应用到当前 map 中
    curshtool -c new.txt -o new.map
	ceph osd setcrushmap -i new.map
	此时ceph会重新收敛,等待收敛完毕后,ceph可正常使用
	ceph -s  等待集群变为active+clean状态

6.8.5 osd维护

你可能需要定期对集群中某个子网进行例行维护,或者要解决某个域内的问题。当你停止OSD时,默认 情况下CRUSH机制会对集群自动重平衡,可将集群设为noout状态来关闭自动重平衡:

# 1、关闭自动重平衡
ceph osd set noout
#2、关闭节点上的osd进程
ceph osd down编号	#分别把该节点上的osd设置为down状态
systemctl stop ceph-osd.target # stop 该节点上的所有 osd 进程
#3、关闭节点
shutdown -h now
#4、开始维护
当你对失败域中OSD维护时,其中的PG将会变为degraded状态。
#5、维护完成启动守护进程
systemctl start ceph-osd.target
#6、最后务必记得取消集群的noout状态
ceph osd unset noout

6.8.6 osd扩容

6.8.6.1 扩容概念

1.如果副本数为2, PB级的集群的容量超过50%,就要考虑扩容了。假如OSD主机的磁盘容量为 48TB (12*4TB),则需要backfill的数据为24TB (48TB 50%),假设网卡为10Gb,则新加一个 OSD时,集群大约需要19200s (24TB/(10Gb/8))约3小时完成backfill,而backfill后台数据填充 将会涉及大量的IO读和网络传输,必将影响生产业务运行。如果集群容量到80%再扩容会导致更 长的backfil l时间,近8个小时。
2.OSD对应的磁盘利用率如果超过50%,也需要尽快扩容。
3.在业务闲时扩容
6.8.6.2 横向扩容
横向扩容scale out: 简单理解,横向扩容就是通过增加节点来达到增加容量的目的,大概操作流程如下:

1,对新节点进行初始化、配置yum源、时间同步,安装基础工具,集群间的主机名互相可解析,ceph-deploy节点可以免密登录到新节点等操作。
2,执行命令 ceph-deploy osd create --data {data-disk} {node-name} 同步配置文件
3,ceph -s 查看集群状态,如果无误,添加osd完成。
6.8.6.3 纵向扩容
纵向扩容scale up:通过增加现有节点的硬盘(OSD)来达到增加容量的目的。大概操作流程如下:

1,清理磁盘数据 如果目标磁盘有分区表,请执行下列命令进行删除分区信息,对应的数据也将会被删除。
 	执行命令 ceph-deploy disk zap {node-name} {data-disk}
2,执行命令 ceph-deploy osd create --data {data-disk} {node-name} 同步配置文件 
3,ceph -s 查看集群状态,如果无误,添加osd完成。
6.8.6.4 数据回填
ceph osd数据重新分布
当有新的osd加入集群或者移除了osd,就会把状态上报给Monitor,Monitor知道了osd map发生了变化就会触发rebalancing,确保pg能够平滑的移动到各个osd上。以pg为整体进行数据重平衡,重平衡的过程中可能会影响性能。一次性加入的osd越多,数据rebalancing就越频繁,业务也可能因此受到影响。生产环境中,强烈建议一次只添加一个osd,最大限度的减少性能和业务的影响.

临时关闭rebalance // 再平衡 
 
当在做rebalance的时候,每个osd都会按照osd_max_backfills指定数量的线程来同步,如果该数值比较大,同步会比较快,但是会影响部分性能;另外数据同步时,是走的cluster_network,而客户端连接是用的public_network,生产环境建议这两个网络用万兆网络,较少网络传输的影响!

可以执行下面命令 查看 osd_max_backfills
ceph daemon osd.0 config show | grep osd_max_backfills  
"osd_max_backfills": "1",  # osd_max_backfills默认还是比较小的

注意: 在生产环境中,一般不会再新节点加入 ceph 集群后,立即开始数据回填,这样会影响集群性能。所以我们需要设置一些标志位,来完成这个目的。

ceph osd set norecover		# 也是在操作磁盘时防止数据发生恢复。
ceph osd set norebalance    # 防止数据均衡操作
ceph osd set nobackfill    	# 防止集群进行数据回填操作
  
	
在用户访问的非高峰时,取消这些标志位,集群开始在平衡任务。	

ceph osd unset norecover		
ceph osd unset norebalance    	# 数据开始均衡操作
ceph osd unset nobackfill    	# 集群开始进行数据回填操作


当新的节点加入集群,ceph 集群开始将部分现有的数据重新平衡到新加入的 osd 上,用下面的命令可用观察平衡过程。
ceph -w
watch ceph -s
watch ceph health


再平衡 如下图所示:

img

6.8.6.5 osd缩容
当osd对应的硬件磁盘设备损坏或者其他情况,我们需要将磁盘对应的osd剔除集群,进行维护。那么应该怎么做呢?

ceph osd perf      # 检查磁盘延迟

# 如果磁盘有坏道,那么其延迟可能会很高
# 严重的话,会影响我们整个ceph集群的性能,故需要剔除出去

具体参考 6.8.4 osd剔除
6.8.6.6 扩容参数设置
注意

在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.0的 最大回填操作数
ceph daemon osd.0 config show | grep osd_max_backfills   
//设置 osd.0的 最大回填操作数
ceph tell osd.* injectargs --osd_max_backfills=4  

6.9 mon相关

6.9.1 增加mon

参考  4.1 扩展mon节点

6.9.2 删除mon(手动)

当你想要删除一个 mon 时,需要考虑删除后剩余的 mon 个数是否能够达到法定人数。
1、停止 mon 进程。
stop ceph-mon id={mon-id}

2、从集群中删除 monitor。
ceph mon remove {mon-id}

3、从 ceph.conf 中移除 mon 的入口部分(如果有)。

6.9.3 删除mon(不健康)

如何从一个不健康的集群(比如集群中的 monitor 无法达成法定人数)中删除 ceph-mon 守护进程。

1、停止集群中所有的 ceph-mon 守护进程。 //登录到所有mon节点

ssh {mon-host}
stop ceph-mon.target
# and repeat for all mons

2、确认存活的 mon 并登录该节点。
ssh {mon-host}

3、提取 mon map。
ceph-mon -i {mon-id} --extract-monmap {map-path}
# in most cases, that's
ceph-mon -i `hostname` --extract-monmap /tmp/monmap

4、删除未存活或有问题的的 monitor。比如,有 3 个 monitors,mon.a 、mon.b 和 mon.c,现在仅有 mon.a 存活,执行下列步骤:
monmaptool {map-path} --rm {mon-id}
# for example,
monmaptool /tmp/monmap --rm b
monmaptool /tmp/monmap --rm c

5、向存活的 monitor(s) 注入修改后的 monmap。比如,把 monmap 注入 mon.a,执行下列步骤:
ceph-mon -i {mon-id} --inject-monmap {map-path}
# for example,
ceph-mon -i a --inject-monmap /tmp/monmap

6、启动存活的 monitor。

7、确认 monitor 是否达到法定人数( ceph -s )。

8、你可能需要把已删除的 monitor 的数据目录 /var/lib/ceph/mon 归档到一个安全的位置。或者,如果你确定剩下的 monitor 是健康的且数量足够,也可以直接删除数据目录。

6.9.2 删除mon( ceph-deploy )

ceph-deploy mon destroy {host-name [host-name]...}

注意: 确保你删除某个 Mon 后,其余 Mon 仍能达成一致。如果不可能,删除它之前可能需要先增加一个。

6.10 mds相关

    
2、删除mds节点
	ssh root@mon01 systemctl stop ceph-mds.target
	ceph mds rm 0 #删除一个不活跃的mds
	#启动mds后,则恢复正常
	
3、 关闭mds集群
	ceph mds cluster_down
	
4、 开启mds集群
	ceph mds cluster_up
	
5、 设置cephfs文件系统存储方式最大单个文件尺寸
	ceph mds set max_file_size 1024000000000
	
6、 了解:清除mds文件系统
    #1、强制mds状态为featrue
    ceph mds fail 0
    #2、删除mds文件系统
    ceph fs rm cephfs --yes-i-really-mean-it
    #3、删除数据池
    ceph osd pool delete cephfs_data cephfs_data --yes-i-really-really-mean-it
    #4、删除元数据池
    ceph osd pool delete cephfs_metadata cephfs_metadata --yes-i-really-really-mean-it
    #5、然后再删除mds key,残留文件等
    #6、最后删除不活跃的mds
    ceph mds rm 0

6.11 rados相关

rados是和Ceph的对象存储集群(RADOS), Ceph的分布式文件系统的一部分进行交互是一种实用工 具。
1、 看ceph集群中有多少个pool (只是查看pool)
	rados lspools # 同 ceph osd pool ls 输出结果一致

2、 显示整个系统和被池毁掉的使用率统计,包括磁盘使用(字节)和对象计数
	rados df

3、 创建一个pool
	rados mkpool test  #这个命令好像 在高版本 被移除了 

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

6.12 ceph调优

什么是 scrub
    scrub是 Ceph 集群副本进行数据扫描的操作,用于检测副本间数据的一致性,包括 scrub 和 deep-scrub。
    其中scrub 只对元数据信息进行扫描,相对比较快;而deep-scrub 不仅对元数据进行扫描,还会对存储的数据进行扫描,相对比较慢。

scrub默认执行周期
    osd 的scrub 默认策略是每天到每周(如果集群负载大周期就是一周,如果集群负载小周期就是一天)进行一次,
    时间区域默认为全体(0时-24时),deep-scrub默认策略是每周一次。
    
    为了避开客户业务高峰时段,建议在晚上0点到第二天早上5点之间,执行scrub 操作。
    
设置标识位:    
    在任一monitor节点进行如下操作:
    ceph osd set noscrub
	ceph osd set nodeep-scrub
	
临时配置:
    先通过tell 方式,让scrub 时间区间配置立即生效,在任一monitor节点进行如下操作:

    ceph tell osd.* injectargs '--osd_scrub_begin_hour 0'
    ceph tell osd.* injectargs '--osd_scrub_end_hour 5'
    ceph tell mon.* injectargs '--osd_scrub_begin_hour 0'
    ceph tell mon.* injectargs '--osd_scrub_end_hour 5'
 
修改配置文件
    为了保证集群服务重启或者节点重启依然有效,需要修改Ceph集群所有节点的配置文件 /etc/ceph/ceph.conf

    # vim /etc/ceph/ceph.conf
    [osd]
    osd_scrub_begin_hour = 0    # scrub操作的起始时间为0点
    osd_scrub_end_hour = 5      # scrub操作的结束时间为5点#ps: 该时间设置需要参考物理节点的时区设置

    osd_scrub_chunk_min = 1  #标记每次scrub的最小数
    osd_scrub_chunk_max = 1  #标记每次scrub的最大数据块
    osd_scrub_sleep = 3  #标记当前scrub结束,执行下次scrub的等待时间,增加该值,会导致scrub变慢,客户端影响反而会减小
    
取消标识位
    ceph osd unset noscrub
    ceph osd unset nodeep-scrub

7,故障处理

注意:
故障分析来源于:https://docs.ceph.com/en/latest/rados/troubleshooting/

7.1 mon故障

7.1.1 故障说明

Monitor 维护着 Ceph 集群的信息,如果 Monitor 无法正常提供服务,那整个 Ceph 集群就不可访问。
一般来说,在实际运行中,Ceph Monitor的个数是 2n + 1 ( n >= 0) 个,在线上至少3个,只要正常的节点数 >= n+1,Ceph 的 Paxos 算法就能保证系统的正常运行。

7.1.2 排障手段

7.1.2.1 使用套接字
使用 Mon 的管理套接字
	请牢记,只有在 Mon 运行时管理套接字才可用。Mon 正常关闭时,管理套接字会被删除;
	如果 Mon 不运行了、但管理套接字还存在,就说明 Mon 不是正常关闭的。不管怎样,Mon 没在运行,你就不能使用管理套接字
	
	使用命令:
	ceph-conf --name mon.ID --show-config-value admin_socket  //获取路径
	
	访问管理套接字很简单,就是让 ceph 工具使用 asok 文件。对于 Dumpling 之前的版本,命令是这样的:
	ceph --admin-daemon /var/run/ceph/ceph-mon.<node name>.asok <command>
	
	对于 Dumpling 及后续版本,你可以用另一个(推荐的)命令:
	
	ceph daemon mon.<node name> <command> // 我们用这个命令  
	注意:这里面 这个 是 节点名字 而不是id 例如:
	
	ceph daemon mon.cephstore2 help
	
	前面两个都需要在对应的mon上面执行,,下面这个可以在集群任意有权限的机器上执行 :
	ceph tell mon.<id> mon_status
	
	ceph 工具的 help 命令会显示管理套接字支持的其它命令。
	请仔细了解一下 config get 、 config show 、 mon_status 和 quorum_status 命令,在排除 Mon 故障时它们会很有用。
7.1.2.2 分析mon_status
3,分析 mon_status
[root@cephstore2 ceph]# ceph daemon mon.cephstore2 mon_status
{
    "name": "cephstore2",
    "rank": 0,
    "state": "leader", 	 
    "election_epoch": 11,
    "quorum": [
        0
    ],
    "monmap": {
        "epoch": 1,
        "mons": [
            {
                "rank": 0,
                "name": "cephstore2",
                "public_addrs": {
                    "addrvec": [
                        {
                            "type": "v2",
                            "addr": "192.168.182.132:3300",
                            "nonce": 0
                        },
                        {
                            "type": "v1",
                            "addr": "192.168.182.132:6789",
                            "nonce": 0
                        }
                    ]
                }
            }
        ]
    }
}
//从上面的信息可以看出, monmap 中包含 1 个monitor, cephstore2 是法定人数中的leader 角色 (非 peon 角色)。

//请看 quorum 集合。这个集合里面的值 不是 monitor 的名字,而是它们加入当前 monmap 后确定的等级。 如果有多个 会0,1,2,3 一直往下增加 
monitor 的等级是如何确定的?
当加入或删除 monitor 时,会(重新)计算等级。计算时遵循一个简单的规则: IP:PORT 的组合值越大, 等级越低(等级数字越大,级别越低)。

7.1.3 常见问题

7.1.3.1 mon处于down状态
达到了法定人数但是有至少一个 Monitor 处于 Down 状态

使用命令 可能看到类似下面的输出:
ceph health detail
HEALTH_WARN 1 mons down, quorum 1,2 b,c
mon.a (rank 0) addr 127.0.0.1:6789/0 is down (out of quorum)

解决办法:
1,首先,确认 mon.a 进程是否运行。

2,其次,确定可以从其他 monitor 节点连到 mon.a 所在节点。同时检查下端口。如果开了防火墙,还需要检查下所有 monitor 节点的 iptables ,以确定没有丢弃/拒绝连接。
如果前两步没有解决问题,请继续往下走。

3,首先,通过管理套接字检查问题 monitor 的 mon_status 。考虑到该 monitor 并不在法定人数中,它的状态应该是 probing , electing 或 synchronizing 中的一种。如果它恰巧是 leader 或 peon 角色,它会认为自己在法定人数中,但集群中其他 monitor 并不这样认为。或者在我们处理故障的过程中它加入了法定人数,所以再次使用 ceph -s 确认下集群状态。如果该 monitor 还没加入法定人数,继续。

probing 状态是什么情况?

这意味着该 monitor 还在搜寻其他 monitors 。每次你启动一个 monitor,它会去搜寻 monmap 中的其他 monitors ,所以会有一段时间处于该状态。此段时间的长短不一。例如,单节点 monitor 环境, monitor 几乎会立即通过该阶段。在多 monitor 环境中,monitors 在找到足够的节点形成法定人数之前,都会处于该状态,这意味着如果 3 个 monitor 中的 2 个 down 了,剩下的 1 个会一直处于该状态,直到你再启动一个 monitor 。

如果你的环境已经形成法定人数,只要 monitor 之间可以互通,新 monitor 应该可以很快搜寻到其他 monitors 。如果卡在 probing 状态,并且排除了连接的问题,那很有可能是该 monitor 在尝试连接一个错误的 monitor 地址。可以根据 mon_status 命令输出中的 monmap 内容,检查其他 monitor 的地址是否和实际相符。如果不相符,请跳至恢复 Monitor 损坏的 monmap。如果相符,这些 monitor 节点间可能存在严重的时钟偏移问题,请首先参考时钟偏移,如果没有解决问题,可以搜集相关的日志并向社区求助。

electing 状态是什么情况?

这意味着该 monitor 处于选举过程中。选举应该很快就可以完成,但偶尔也会卡住,这往往是 monitors 节点时钟偏移的一个标志,跳转至时钟偏移获取更多信息。如果时钟是正确同步的,可以搜集相关日志并向社区求助。此种情况除非是一些(非常)古老的 bug ,往往都是由时钟不同步引起的。

synchronizing 状态是什么情况?

这意味着该 monitor 正在和集群中的其他 monitor 进行同步以便加入法定人数。Monitor 的数据库越小,同步过程的耗时就越短。

然而,如果你注意到 monitor 的状态从 synchronizing 变为 electing 后又变回 synchronizing ,那么就有问题了:集群的状态更新的太快(即产生新的 maps ),同步过程已经无法追赶上了。这种情况在早期版本中可以见到,但现在经过代码重构和增强,在较新版本中已经基本见不到了。

leader 或 peon 状态是什么情况?

这种情况不应该发生,但还是有一定概率会发生,这常和时钟偏移有关。
7.1.3.2 时钟偏移
Monitor 节点间明显的时钟偏移会对 monitor 造成严重的影响。这通常会导致一些奇怪的问题。为了避免这些问题,在 monitor 节点上应该运行时间同步工具。

允许的最大时钟偏移量是多少?

默认最大允许的时钟偏移量是 0.05 秒。

如何增加最大时钟偏移量?

通过 mon-clock-drift-allowed 选项来配置。尽管你 可以 修改但不代表你 应该 修改。时钟偏移机制之所以是合理的,是因为有时钟偏移的 monitor 可能会表现不正常。未经测试而修改该值,尽管没有丢失数据的风险,但仍可能会对 monitors 的稳定性和集群的健康造成不可预知的影响。

如何知道是否存在时钟偏移?

Monitor 会用 HEALTH_WARN 的方式警告你。 ceph health detail 应该输出如下格式的信息:

mon.0 addr 192.168.182.132:6789/0 clock skew 0.08235s > max 0.05s (latency 0.0045s)

这表示 mon.0 已被标记出正在遭受时钟偏移。

如果存在时钟偏移该怎么处理?

同步各 monitor 节点的时钟。运行 NTP 客户端会有帮助。如果你已经启动了 NTP 服务,但仍遭遇此问题,检查一下使用的 NTP 服务器是否离你的网络太过遥远,然后可以考虑在你的网络环境中运行自己的 NTP 服务器。最后这种选择可趋于减少 monitor 时钟偏移带来的问题。

查看时间同步状态
ceph time-sync-status
7.1.3.3 客户端无法连接
检查 IP 过滤表。某些操作系统安装工具会给 iptables 增加一条 REJECT 规则。这条规则会拒绝所有尝试连接该主机的客户端(除了 ssh )。如果你的 monitor 主机设置了这条防火墙 REJECT 规则,客户端从其他节点连接过来时就会超时失败。你需要定位出拒绝客户端连接 Ceph 守护进程的那条 iptables 规则。
给 Ceph 主机的 IP 过滤表增加规则,以确保客户端可以访问 Ceph monitor (默认端口 6789 )和 Ceph OSD (默认 6800 ~ 7300 )的相关端口。

iptables -A INPUT -m multiport -p tcp -s {ip-address}/{netmask} --dports 6789,6800:7300 -j ACCEPT

或者,如果你的环境允许,也可以直接关闭主机的防火墙。
7.1.3.4 磁盘空间不足
当 monitor 进程检测到本地可用磁盘空间不足时,会停止 monitor 服务。Monitor 的日志中应该会有类似如下信息的输出:

2016-09-01 16:45:54.994488 7fb1cac09700  0 mon.jyceph01@0(leader).data_health(62) update_stats avail 5% total 297 GB, used 264 GB, avail 18107 MB
2016-09-01 16:45:54.994747 7fb1cac09700 -1 mon.jyceph01@0(leader).data_health(62) reached critical levels of available space on local monitor storage -- shutdown!
清理本地磁盘,增大可用空间,重启 monitor 进程,即可恢复正常。

7.1.4 mon数据库

7.1.4.1 mon数据库崩溃
数据库崩溃的表现
Ceph monitor 把集群的各种 map 信息存放在 key/value 数据库中,如 LevelDB 。如果 monitor 是因为数据库崩溃而失败,在 monitor 的 log 日志中应该会有如下错误信息:
	Corruption: error in middle of record
或者 
	Corruption: 1 missing files; e.g.: /var/lib/ceph/mon/mon.0/store.db/1234567.ldb
	
如何恢复?
1,通过健康的 Monitor(s) 恢复
如果还有幸存的 monitor,我们通常可以用新的数据库替换崩溃的数据库。并且在启动后,新加入的成员会和其他健康的伙伴进行同步,一旦同步完成,它就可以为客户端提供服务了。

2,通过 OSDs 恢复
但是万一所有的 monitors 都同时失败了该怎么办?由于建议用户在部署集群时至少安装 3 个 monitors,同时失效的可能性较小。但是数据中心意外的断电,再加上磁盘/文件系统配置不当,可能会引起底层文件系统失败,从而杀掉所有的 monitors 。这种情况下,我们可以通过存放在 OSDs 上的信息来恢复 monitor 的数据库:

上面的这些步骤:

    (1),从所有的 OSD 主机上收集 map 信息。
    (2),重建数据库。
    (3),用恢复副本替换 mon.0 上崩溃的数据库。
    
已知的限制

下面这些信息无法通过上述步骤恢复:

	(1),一些新增的 keyring : 通过 ceph auth add 命令增加的所有 OSD keyrings 都可以恢复。用 ceph-monstore-tool 可以导入 client.admin 的 keyring 。但是 MDS 和其他 keyrings 在被恢复的那个 monitor 数据库中就会丢失。你可能需要手动重新添加一下。
	(2),pg 的设置:通过 ceph pg set_full_ratio 和 ceph pg set_nearfull_ratio 命令设置的 full ratio 和 nearfull ratio 值会丢失。
MDS Maps:MDS maps 会丢失。
7.1.4.2 mon数据库备份
Monitor 的备份
每个 MON 的数据都是保存在数据库内的,这个数据库位于 /var/lib/ceph/mon/$cluster-$hostname/store.db ,这里的 $cluster 是集群的名字, $hostname 为主机名,MON 的所有数据即目录 /var/lib/ceph/mon/$cluster-$hostname/ ,备份好这个目录之后,就可以在任一主机上恢复 MON 了。

cd /var/lib/ceph/mon/ 
systemctl stop ceph-mon.target
tar czf /var/backups/ceph-mon-backup_$(date +%Y_%m_%d_%H_%M_%S).tar.gz .
systemctl start ceph-mon.target
#for safety, copy it to other nodes
scp /var/backups/* someNode:/backup/
7.1.4.3 mon数据库恢复
现在有一个 Ceph 集群,包含 3 个 monitors: cephstore2 、cephstore3 和 cephstore4。

假设发生了某种故障,导致这 3 台 MON 节点全都无法启动,这时 Ceph 集群也将变得不可用。我们可以通过前面备份的数据库文件来恢复 MON。当某个集群的所有的 MON 节点都挂掉之后,我们可以将最新的备份的数据库解压到其他任意一个节点上,新建 monmap,注入,启动 MON,推送 config,重启 OSD就好了。

1,将 cephstore2 的 /var/lib/ceph/mon/ceph-cephstore2/ 目录的文件拷贝到新节点 cephstore5 的 /var/lib/ceph/mon/ceph-cephstore5/ 目录下(或者从备份路径拷贝到 cephstore5 节点),一定要注意目录的名称!

########在 cephstore5 上面 创建文件 
mkdir /var/lib/ceph/mon/ceph-cephstore5

########在 cephstore2 上面 执行拷贝命令
scp -r /var/lib/ceph/mon/ceph-cephstore2/*  cephstore5:/var/lib/ceph/mon/ceph-cephstore5/

2,同时,将 /etc/ceph 目录文件也拷贝到 cephstore5 节点,然后将 ceph.conf 中的 mon_initial_members 修改为 cephstore5。

########在 cephstore2 上面 执行拷贝命令
scp /etc/ceph/* cephstore5:/etc/ceph/

########在 cephmgr 上面 编辑文件 
vim /etc/ceph/ceph.conf 

mon_initial_members = cephstore5
mon_host = 192.168.182.135

3,新建一个 monmap,使用原来集群的 fsid,并且将 cephstore5 加入到这个 monmap,然后将 monmap 注入到 cephstore5 的 MON 数据库中,最后启动 cephstore5 上的 MON 进程。

########在 cephstore5 上面 创建 monmap  ##这里的fsid就是集群的id 通过ceph -s 来获取
monmaptool --create --fsid 7a900680-5c34-490c-bfe3-ed670773478d --add cephstore5 192.168.182.135 /tmp/monmap 
########在 cephstore5 上面 把monmap注入进去
ceph-mon -i cephstore5 --inject-monmap /tmp/monmap 

3, 将 cephmgr 的 ceph.conf 推送到其他所有节点上,再重启 OSD 集群就可以恢复正常了。

########在 cephmgr 上面 推送 ceph.conf文件  
ceph-deploy --overwrite-conf config push cephmgr cephstore2 cephstore3 cephstore4 cephstore5

7.1.5 monmap

7.1.5.1 获取monmap
获取 monmap:
1,使用命令 
ceph mon dump
2,获取所有的monitor的信息
ceph mon getmap -o monmap.map    #	把 monmap 放到当前路径下的 monmap.map文件里
monmaptool --print monmap.map  	 # 	打印 monmap.map 内容

3,全部通过montoolmap工具,优点是可以查看指定Monitor的monmap
	(1)用montoolmap生成指定的monitors 的map,添加mon可以通过 --add参数
	monmaptool  --create  --add  mon.<id> <ip name>:6789  --clobber monmap
	例如:
	monmaptool  --create  --add  mon.0 192.168.182.132:6789  --clobber monmap
	(2) 使用montoolmap工具查看map
	monmaptool --print monmap 
	
注意:测试的时候 ,发现 3的(2)步骤 出现 min_mon_release 0 (unknown)  不知道是什么问题,可能是bug

7.1.5.2 处理monmap
1,销毁 monitor 然后新建

只有在你确定不会丢失保存在该 monitor 上的数据时,你才能够采用这个方法。也就是说,集群中还有其他运行正常的 monitors,以便新 monitor 可以和其他 monitors 达到同步。请谨记,销毁一个 monitor 时,如果没有其上数据的备份,可能会丢失数据。

2,给 monitor 手动注入 monmap

通常是最安全的做法。你应该从剩余的 monitor 中抓取 monmap,然后手动注入 monmap 有问题的 monitor 节点。

下面是基本步骤:
(1)、是否已形成法定人数?如果是,从法定人数中抓取 monmap :
	ceph mon getmap -o /tmp/monmap
(2)、没有形成法定人数?直接从其他 monitor 节点上抓取 monmap (这里假定你抓取 monmap 的 monitor 的 id 是 ID-FOO 并且守护进程已经停止运行):
	ceph-mon -i ID-FOO --extract-monmap /tmp/monmap
(3)、停止你想要往其中注入 monmap 的 monitor。

(4)、注入 monmap 。
	ceph-mon -i ID --inject-monmap /tmp/monmap
(5)、启动 monitor 。

请记住,能够注入 monmap 是一个很强大的特性,如果滥用可能会对 monitor 造成大破坏,因为这样做会覆盖 monitor 持有的最新 monmap 。

7.2 osd故障

7.2.1 故障说明

进行 OSD 排障前,先检查一下 monitors 和网络。如果 ceph health 或 ceph -s 返回的是健康状态,这意味着 monitors 形成了法定人数。如果 monitor 还没达到法定人数、或者 monitor 状态错误,要先解决 monitor 的问题。核实下你的网络,确保它在正常运行,因为网络对 OSD 的运行和性能有显著影响。

7.2.2 排障手段

7.2.2.1 收集数据
开始 OSD 排障的第一步最好先收集信息,另外还有监控 OSD 时收集的,如 ceph osd tree 。

如果你没改默认路径,可以在 /var/log/ceph 下找到 Ceph 的日志:
ls /var/log/ceph

如果看到的日志还不够详细,可以增大日志级别。请参考1.12 日志和调试,查阅如何保证看到大量日志又不影响集群运行。
7.2.2.2 使用套接字
执行下例命令显示可用选项,把 {daemon-name} 换成实际的守护进程(如 osd.0 ): 
ceph daemon {daemon-name} help

注意和 mon的区分 mon的是 mon.<node name> osd的是 osd.<id>

和其它手段相比,管理套接字允许你:
    在运行时列出配置
    列出历史操作
    列出操作的优先队列状态
    列出在进行的操作
    列出性能计数器
7.2.2.3 其他信息
1,显示可用空间 : 
#可能会引起文件系统问题。用 df 命令显示文件系统的可用空间。
df -h
#其它用法见 df --help 。

2,I/O 统计信息 :
#用 iostat 工具定位 I/O 相关问题。
iostat -x

3,诊断信息 :
#要查看诊断信息,配合 less 、 more 、 grep 或 tail 使用 dmesg ,例如:
dmesg | grep scsi
7.2.2.4 停止数据向外重平衡
你得周期性地对集群的子集进行维护,或解决某个故障域的问题(如某个机架)。如果你不想在停机维护 OSD 时让 CRUSH 自动重均衡,首先设置集群的 `noout` 标志:
ceph osd set noout
设置了 noout 后,你就可以停机维护失败域内的 OSD 了。
systemctl stop ceph-osd.target
**注意:**在定位某故障域内的问题时,停机的 OSD 内的 PG 状态会变为 `degraded` 。

维护结束后,重启 OSD 。
systemctl start ceph-osd.target
最后,解除 `noout` 标志。
ceph osd unset noout

7.2.6 常见问题

7.2.6.1 OSD 没运行
通常情况下,简单地重启 ceph-osd 进程就可以让它重回集群并恢复。

OSD 起不来
如果你重启了集群,但其中一个 OSD 起不来,依次检查:

配置文件: 如果你新装的 OSD 不能启动,检查下配置文件,确保它符合规定(比如 host 而非 hostname ,等等)。

检查路径: 检查配置文件的路径,以及 OSD 的数据和日志分区路径。如果你分离了 OSD 的数据和日志分区、而配置文件和实际挂载点存在出入,启动 OSD 时就可能失败。如果你想把日志存储于一个块设备,应该为日志硬盘分区并为各 OSD 分别指定一个分区。

检查最大线程数: 如果你的节点有很多 OSD ,也许就会触碰到默认的最大线程数限制(如通常是 32k 个),尤其是在恢复期间。你可以用 sysctl 增大线程数,把最大线程数更改为支持的最大值(即 4194303 ),看看是否有用。例如:

sysctl -w kernel.pid_max=4194303

如果增大最大线程数解决了这个问题,你可以把此配置 kernel.pid_max 写入配置文件 /etc/sysctl.conf,使之永久生效,例如:

kernel.pid_max = 4194303
内核版本: 确认你使用的内核版本和发布版本。 Ceph 默认依赖一些第三方工具,这些工具可能有缺陷或者与特定发布版和/或内核版本冲突(如 Google perftools )。检查下操作系统推荐表,确保你已经解决了内核相关的问题。

段错误: 如果有了段错误,提高日志级别(如果还没提高),再试试。如果重现了,联系 ceph-devel 邮件列表并提供你的配置文件、monitor 输出和日志文件内容。


OSD 失败
当 ceph-osd 挂掉时,monitor 可通过活着的 ceph-osd 了解到此情况,并通过 ceph health 命令报告:

ceph health
HEALTH_WARN 1/3 in osds are down
特别地,有 ceph-osd 进程标记为 in 且 down 的时候,你也会得到警告。你可以用下面的命令得知哪个 ceph-osd 进程挂了:

ceph health detail
HEALTH_WARN 1/3 in osds are down
osd.0 is down since epoch 23, last address 192.168.182.132:6800/11080

如果有硬盘失败或其它错误使 ceph-osd 不能正常运行或重启,将会在日志文件 /var/log/ceph/ 里输出一条错误信息。

如果守护进程因心跳失败、或者底层核心文件系统无响应而停止,查看 dmesg 获取硬盘或者内核错误。

如果是软件错误(失败的断言或其它意外错误),应该向 ceph-devel 邮件列表报告。
7.2.6.2 硬盘没剩余空间
Ceph 不允许你向满的 OSD 写入数据,以免丢失数据。在运行着的集群中,你应该能收到集群空间将满的警告。 mon osd full ratio 默认为 0.95 ,或达到 95% 的空间使用率时它将阻止客户端写入数据。 mon osd nearfull ratio 默认为 0.85 ,也就是说达到容量的 85% 时它会产生健康警告。

满载集群问题一般产生于测试小型 Ceph 集群上如何处理 OSD 失败时。当某一节点使用率较高时,集群能够很快掩盖将满和占满率。如果你在测试小型集群上的 Ceph 如何应对 OSD 失败,应该保留足够的可用磁盘空间,然后试着临时降低 mon osd full ratio 和 mon osd nearfull ratio 值。

ceph health 会报告将满的 ceph-osds :

ceph health
HEALTH_WARN 1 nearfull osds
osd.2 is near full at 85%
或者:

ceph health
HEALTH_ERR 1 nearfull osds, 1 full osds
osd.2 is near full at 85%
osd.3 is full at 97%
处理这种情况的最好方法就是在出现 near full 告警时尽快增加新的 ceph-osd ,这允许集群把数据重分布到新 OSD 里。


 
如果因满载而导致 OSD 不能启动,你可以试着删除那个 OSD 上的一些数据。但是这时有个问题,当一个 OSD 使用比例达到 95% 时,集群将不接受任何 Ceph Client 端的读写数据的请求。这时 rbd rm 删除命令将不会得到响应。

让集群能够读写是首先要做的事情。最容易想到的就是调高 mon osd full ratio 和 mon osd nearfull ratio 值,但是对于生产环境,一旦调整这个全局比例,可能会导致整个集群的数据都会动起来,引发更多的数据迁移。因此另一种折衷方法就是单独调整已满 OSD 的 near full 和 full 比例;也可以使用调低 OSD 的 crush weight 的方法,使已满 OSD 上的数据迁移一部分出去。

# 调整单个 osd 的比例
ceph tell osd.<id> injectargs '--mon-osd-full-ratio .98'
ceph tell osd.<id> injectargs '--mon-osd-full-ratio 0.98'
# 调整 osd 的 crush weight 值
ceph osd crush reweight osd.<id> {a-little-lower-weight-value}
7.2.6.3 OSD 龟速或无响应
一个反复出现的问题是 OSD 龟速或无响应。在深入性能问题前,你应该先确保不是其他故障。例如,确保你的网络运行正常、且 OSD 在运行,还要检查 OSD 是否被恢复流量拖住了。

Tip: 较新版本的 Ceph 能更好地处理恢复,可防止恢复进程耗尽系统资源而导致 up 且 in 的 OSD 不可用或响应慢。
7.2.6.3.1 网络问题
Ceph 是一个分布式存储系统,所以它依赖于网络来互联 OSD 们、复制对象、从错误中恢复和检查心跳。网络问题会导致 OSD 延时和震荡(反复经历 up and down,详情可参考下文中的相关小节) 。

确保 Ceph 进程和 Ceph 依赖的进程已建立连接和/或在监听。

netstat -a | grep ceph
netstat -l | grep ceph
sudo netstat -p | grep ceph
检查网络统计信息。

netstat -s
7.2.6.3.2 驱动器配置
一个存储驱动器应该只用于一个 OSD 。如果有其它进程共享驱动器,顺序读写吞吐量会成为瓶颈,包括日志、操作系统、monitor 、其它 OSD 和非 Ceph 进程。

Ceph 在日志记录完成之后才会确认写操作,所以使用 ext4 或 XFS 文件系统时高速的 SSD 对降低响应延时很有吸引力。与之相比, btrfs 文件系统可以同时读写日志和数据分区。

 
注意: 给驱动器分区并不能改变总吞吐量或顺序读写限制。把日志分离到单独的分区可能有帮助,但最好是另外一块硬盘的分区。
7.2.6.3.3 扇区损坏 / 碎片化硬盘
检修下硬盘是否有坏扇区和碎片。这会导致总吞吐量急剧下降。
7.2.6.3.4 MON 和 OSD 共存
Monitor 通常是轻量级进程,但它们会频繁调用 fsync() ,这会妨碍其它工作负载,特别是 Mon 和 OSD 共享驱动器时。另外,如果你在 OSD 主机上同时运行 Mon,遭遇的性能问题可能和这些相关:

运行较老的内核(低于 3.0 )
Argonaut 版运行在老的 glibc 之上
运行的内核不支持 syncfs(2) 系统调用
在这些情况下,同一主机上的多个 OSD 会相互拖垮对方。它们经常导致爆炸式写入。
7.2.6.3.5 进程共存
共用同一套硬件、并向 Ceph 写入数据的进程(像基于云的解决方案、虚拟机和其他应用程序)会导致 OSD 延时大增。一般来说,我们建议用单独的主机跑 Ceph 、其它主机跑其它进程。实践证明把 Ceph 和其他应用程序分开可提高性能、并简化故障排除和维护。
7.2.6.3.6 日志记录级别
如果你为追踪某问题提高过日志级别,结束后又忘了调回去,这个 OSD 将向硬盘写入大量日志。如果你想始终保持高日志级别,可以考虑给默认日志路径(即 /var/log/ceph/$cluster-$name.log )挂载一个单独的硬盘。
7.2.6.3.7 恢复限流
根据你的配置, Ceph 可以降低恢复速度来维持性能,否则它会加快恢复速度而影响 OSD 的性能。检查下 OSD 是否正在恢复。
7.2.6.3.8 内核版本
检查下你在用的内核版本。较老的内核也许没有反合能提高 Ceph 性能的代码。
7.2.6.3.9 内核与 SYNCFS 问题
试试在一个主机上只运行一个 OSD ,看看能否提升性能。老内核未必支持有 syncfs(2) 系统调用的 glibc 。
7.2.6.3.10 文件系统问题
当前,我们推荐基于 xfs 部署集群。 btrfs 有很多诱人的功能,但文件系统内的缺陷可能会导致性能问题。我们不推荐使用 ext4 ,因为 xattr 大小的限制破坏了对长对象名的支持( RGW 需要)。
7.2.6.3.11 内存不足
我们建议为每 OSD 进程规划 1GB 内存。你也许注意到了,通常情况下 OSD 仅会使用一小部分(如 100 – 200MB )。你也许想用这些空闲内存跑一些其他应用,如虚拟机等等。然而当 OSD 进入恢复状态时,其内存利用率将激增。如果没有足够的可用内存,此 OSD 的性能将会明显下降。
7.2.6.3.12 OLD/SLOW REQUESTS
如果某 ceph-osd 守护进程对一请求响应很慢,它会生成日志消息来抱怨请求耗费的时间过长。默认警告阀值是 30 秒,可以通过 osd op complaint time 选项来配置。这种情况发生时,集群日志会收到这些消息。

很老的版本抱怨 “old requests” :

osd.0 192.168.106.220:6800/18813 312 : [WRN] old request osd_op(client.5099.0:790 fatty_26485_object789 [write 0~4096] 2.5e54f643) v4 received at 2012-03-06 15:42:56.054801 currently waiting for sub ops
较新版本的 Ceph 抱怨 “slow requests” :

{date} {osd.num} [WRN] 1 slow requests, 1 included below; oldest blocked for > 30.005692 secs
{date} {osd.num}  [WRN] slow request 30.005692 seconds old, received at {date-time}: osd_op(client.4240.0:8 benchmark_data_ceph-1_39426_object7 [write 0~4194304] 0.69848840) v4 currently waiting for subops from [610]
可能的原因有:

    坏驱动器(查看 dmesg 输出)
    内核文件系统缺陷(查看 dmesg 输出)
    集群过载(检查系统负载、 iostat 等等)
    ceph-osd 守护进程的 bug
可能的解决方法:

    从 Ceph 主机分离 VM 云解决方案
    升级内核
    升级 Ceph
    重启 OSD
7.2.6.3.13 OSD震荡
我们建议同时部署 public(前端)网络和 cluster(后端)网络,这样能更好地满足对象复制的网络性能需求。另一个优点是你可以运营一个不连接互联网的集群,以此避免某些拒绝服务攻击。 OSD 们互联和检查心跳时会优选 cluster(后端)网络。

img

然而,如果 cluster(后端)网络失败、或出现了明显的延时,同时 public(前端)网络却运行良好, OSD 目前不能很好地处理这种情况。这时 OSD 们会向 monitor 报告邻居 down 了、同时报告自己是 up 的,我们把这种情形称为震荡( flapping )。

如果有原因导致 OSD 震荡(反复地被标记为 down ,然后又 up ),你可以强制 monitor 停止这种震荡状态:
ceph osd set noup      # prevent OSDs from getting marked up
ceph osd set nodown    # prevent OSDs from getting marked down

这些标记记录在 osdmap 数据结构里:

ceph osd dump | grep flags
flags no-up,no-down
可用下列命令清除标记:

ceph osd unset noup
ceph osd unset nodown


Ceph 还支持另外两个标记 noin 和 noout ,它们可防止正在启动的 OSD 被标记为 in (可以分配数据),或被误标记为 out (不管 mon osd down out interval 的值是多少)。

注意: noup 、 noout 和 nodown 从某种意义上说是临时的,一旦标记被清除了,被它们阻塞的动作短时间内就会发生。另一方面, noin 标记阻止 OSD 启动后加入集群,但其它守护进程都维持原样。

7.3 pg故障

7.3.1 PG 无法达到 CLEAN 状态

创建一个新集群后,PG 的状态一直处于 active , active + remapped 或 active + degraded 状态, 而无法达到 active + clean 状态 ,那很可能是你的配置有问题。

你可能需要检查下集群中有关 Pool 、 PG 和 CRUSH 的配置项,做以适当的调整。

一般来说,你的集群中需要多于 1 个 OSD,并且存储池的 size 要大于 1 副本。
7.3.1.1 单节点集群
有时候,我们需要搭建一个单节点的 Ceph 实验环境。此时,在开始创建 monitor 和 OSD 之前,你需要把 Ceph 配置文件中的 osd crush chooseleaf type 选项从默认值 1 (表示 host 或 node)修改为 0 (表示 osd)。这样做是告诉 Ceph 允许把数据的不同副本分布到同一 host 的 OSDs 上。
7.3.1.2 OSD 个数小于副本数
如果你已经启动了 2 个 OSD,它们都处于 up 和 in 的状态,但 PG 仍未达到 active + clean 状态,那可能是给 osd pool default size 设置了一个大于 2 的值。

如果你想要在 active + degraded 状态( 2 副本)操作你的集群,可以设置 osd pool default min size 为 2 ,这样你就可以对处于 active + degraded 的对象写入数据。然后你还可以把 osd pool default size 的值改为 2 ,这样集群就可以达到 active + clean 状态了。

ceph osd pool set <pool name> min_size 1
ceph osd pool set <pool name> size 2

另外,修改参数 osd pool default size/min_size后,只会对后面新建的 pool 起作用。如果想修改已存在的 pool 的 size/min_size ,可用下面的命令:

ceph osd pool set <poolname> size|min_size <val>
注意: 你可以在运行时修改参数值。如果是在 Ceph 配置文件中进行的修改,你可能需要重启集群。
7.3.1.3 POOL SIZE = 1
如果你设置了 osd pool default size 的值为 1 ,那你就仅有对象的单份拷贝。OSD 依赖于其他 OSD 告诉自己应该保存哪些对象。如果第一个 OSD 持有对象的拷贝,并且没有第二份拷贝,那么也就没有第二个 OSD 去告诉第一个 OSD 它应该保管那份拷贝。对于每一个映射到第一个 OSD 上的 PG (参考 ceph pg dump 的输出),你可以强制第一个 OSD 关注它应该保存的 PGs :

ceph pg force_create_pg <pgid>
7.3.1.3 crushmap错误
PG 达不到 clean 状态的另一个可能的原因就是集群的 CRUSH Map 有错误,导致 PG 不能映射到正确的地方。

7.3.2 卡住的 PGs

有失败发生后,PG 会进入“degraded”(降级)或“peering”(连接建立中)状态,这种情况时有发生。通常这些状态意味着正常的失败恢复正在进行。然而,如果一个 PG 长时间处于这些状态中的某个,就意味着有更大的问题。因此 monitor 在 PG 卡 ( stuck ) 在非最优状态时会告警。我们具体检查:

inactive (不活跃)—— PG 长时间不是 active (即它不能提供读写服务了);
unclean (不干净)—— PG 长时间不是 clean (例如它未能从前面的失败完全恢复);
stale (不新鲜)—— PG 状态没有被 ceph-osd 更新,表明存储这个 PG 的所有节点可能都 down 了。
你可以用下列命令显式地列出卡住的 PGs:

ceph pg dump_stuck stale
ceph pg dump_stuck inactive
ceph pg dump_stuck unclean

卡在 stale 状态的 PG 通过重启 ceph-osd 进程通常可以修复;卡在 inactive 状态的 PG 通常是互联问题(参见 PG 挂了 —— 互联失败 );卡在 unclean 状态的 PG 通常是由于某些原因阻止了恢复的完成,像未找到的对象(参见 未找到的对象 )。

7.3.3 PG 挂了 —— 互联失败

在某些情况下, ceph-osd 互联进程会遇到问题,阻值 PG 达到活跃、可用的状态。例如, ceph health 也许显示:

ceph health detail
HEALTH_ERR 7 pgs degraded; 12 pgs down; 12 pgs peering; 1 pgs recovering; 6 pgs stuck unclean; 114/3300 degraded (3.455%); 1/3 in osds are down
...
pg 0.5 is down+peering
pg 1.4 is down+peering
...
osd.1 is down since epoch 69, last address 192.168.182.133:6801/8651

可以查询到 PG 为何被标记为 down :

ceph pg 0.5 query  

{ "state": "down+peering",
    ...
    "recovery_state": [
       { "name": "Started\/Primary\/Peering\/GetInfo",
          "enter_time": "2012-03-06 14:40:16.169679",
          "requested_info_from": []},
          { "name": "Started\/Primary\/Peering",
          "enter_time": "2012-03-06 14:40:16.169659",
          "probing_osds": [
                  0,
               1],
          "blocked": "peering is blocked due to down osds",
          "down_osds_we_would_probe": [
               1],
          "peering_blocked_by": [
                  { "osd": 1,
                  "current_lost_at": 0,
                  "comment": "starting or marking this osd lost may let us proceed"}]},
          { "name": "Started",
          "enter_time": "2012-03-06 14:40:16.169513"}
  ]
}
recovery_state 段告诉我们互联过程因 ceph-osd 进程挂了而被阻塞,本例是 osd.1 挂了,启动这个进程应该就可以恢复。


 
或者,如果 osd.1 发生了灾难性的失败(如硬盘损坏),我们可以告诉集群它丢失( lost )了,让集群尽力完成副本拷贝。

重要: 集群不能保证其它数据副本是一致且最新的,就会很危险!

让 Ceph 无论如何都继续:

ceph osd lost <osd id>  将osd.1标记为永久丢失。如果不再存在复制副本,这会破坏数据,请小心

恢复将继续进行。

7.3.4 未找到的对象

某几种失败相组合,可能导致 Ceph 抱怨有找不到( unfound )的对象:

ceph health detail
HEALTH_WARN 1 pgs degraded; 78/3778 unfound (2.065%)
pg 2.4 is active+degraded, 78 unfound
这意味着存储集群知道一些对象(或者存在对象的较新副本)存在,却没有找到它们的副本。下例展示了这种情况是如何发生的,一个 PG 的数据存储在 ceph-osd 1 和 2 上:

1 挂了
2 独自处理一些写动作
1 起来了
1 和 2 重新互联, 1 上面丢失的对象加入队列准备恢复
新对象还未拷贝完, 2 挂了
这时, 1 知道这些对象存在,但是活着的 ceph-osd 都没有这些副本。这种情况下,读写这些对象的 IO 就会被阻塞,集群只能指望 down 掉的节点尽早恢复。这样处理是假设比直接给用户返回一个 IO 错误要好一些。

首先,你应该确认哪些对象找不到了:
执行命令:[starting offset, in json]
ceph pg 2.4 list_unfound 

{
  "num_missing": 1,
  "num_unfound": 1,
  "objects": [
      {
          "oid": {
              "oid": "object",
              "key": "",
              "snapid": -2,
              "hash": 2249616407,
              "max": 0,
              "pool": 2,
              "namespace": ""
          },
          "need": "43'251",
          "have": "0'0",
          "flags": "none",
          "clean_regions": "clean_offsets: [], clean_omap: 0, new_object: 1",
          "locations": [
              "0(3)",
              "4(2)"
          ]
      }
  ],
  "state": "NotRecovering",
  "available_might_have_unfound": true,
  "might_have_unfound": [
      {
          "osd": "2(4)",
          "status": "osd is down"
      }
  ],
  "more": false
}


其次,你可以找出哪些 OSD 上探测到、或可能包含数据:
ceph pg 2.4 query

本例中,集群知道 osd.1 可能有数据,但它挂了( down )。所有可能的状态有:

    已经探测到了
    在查询
    OSD 挂了
    尚未查询
    有时候集群要花一些时间来查询可能的位置。

还有一种可能性,对象存在于其它位置却未被列出。例如,集群里的一个 ceph-osd 停止且被剔出集群,然后集群完全恢复了;后来一系列的失败导致了未找到的对象,它也不会觉得早已死亡的 ceph-osd 上仍可能包含这些对象。(这种情况几乎不太可能发生)。

如果所有可能的位置都查询过了但仍有对象丢失,那就得放弃丢失的对象了。这仍可能是罕见的失败组合导致的,集群在写操作恢复后,未能得知写入是否已执行。以下命令把未找到的( unfound )对象标记为丢失( lost )。

ceph pg 2.5 mark_unfound_lost revert|delete

上述最后一个参数告诉集群应如何处理丢失的对象。

	delete 选项将导致完全删除它们。
	revert 选项(纠删码存储池不可用)会回滚到前一个版本或者(如果它是新对象的话)删除它。要慎用,它可能迷惑那些期望对象存在的应用程序。

7.3.5 无家可归的 PG

拥有 PG 拷贝的 OSD 可能会全部失败,这种情况下,那一部分的对象存储不可用, monitor 也就不会收到那些 PG 的状态更新了。为检测这种情况,monitor 会把任何主 OSD 失败的 PG 标记为 stale (不新鲜),例如:

ceph health
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
可以找出哪些 PG 是 stale 状态,和存储这些归置组的最新 OSD ,命令如下:

ceph health detail
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
...
pg 2.5 is stuck stale+active+remapped, last acting [2,0]
...
osd.10 is down since epoch 23, last address 192.168.106.220:6800/11080
osd.11 is down since epoch 13, last address 192.168.106.220:6803/11539
osd.12 is down since epoch 24, last address 192.168.106.220:6806/11861
如果想使 PG 2.5 重新上线,例如,上面的输出告诉我们它最后由 osd.0 和 osd.2 管理,重启这些 ceph-osd 将恢复之(可以假定还有其它的很多 PG 也会进行恢复 )。

7.3.6 只有几个 OSD 接收数据

如果你的集群有很多节点,但只有其中几个接收数据,检查下存储池里的 PG 数量。因为 PG 是映射到多个 OSD 的,较少的 PG 将不能均衡地分布于整个集群。试着创建个新存储池,设置 PG 数量是 OSD 数量的若干倍。更详细的信息可以参考 Ceph 官方文档 —— Placement Groups 。

7.3.7 不能写入数据

如果你的集群已启动,但一些 OSD 没起来,导致不能写入数据,确认下运行的 OSD 数量满足 PG 要求的最低 OSD 数。如果不能满足, Ceph 就不会允许你写入数据,因为 Ceph 不能保证复制能如愿进行。这个最低 OSD 个数是由参数 osd pool default min size 限定的。

7.3.8 PG 不一致

如果收到 active + clean + inconsistent 这样的状态,很可能是由于在对 PG 做擦洗( scrubbing )时发生了错误。如果是由于磁盘错误导致的不一致,请检查磁盘,如果磁盘有损坏,可能需要将这个磁盘对应的 OSD 踢出集群,然后进行更换。生产环境中遇到过不一致的问题,就是由于磁盘坏道导致的。

当集群中出现 PG 不一致的问题时,执行 ceph -s 命令会出现下面的信息:
root@mon:~# ceph -s
    cluster 614e77b4-c997-490a-a3f9-e89aa0274da3
     health HEALTH_ERR
            1 pgs inconsistent
            1 scrub errors
     monmap e5: 1 mons at {osd1=10.95.2.43:6789/0}
            election epoch 796, quorum 0 osd1
     osdmap e1079: 3 osds: 3 up, 3 in
            flags sortbitwise
      pgmap v312153: 384 pgs, 6 pools, 1148 MB data, 311 objects
            3604 MB used, 73154 MB / 76759 MB avail
                 383 active+clean
                   1 active+clean+inconsistent
                   
                   
查找处于 inconsistent 状态的问题 PG :

root@mon:~# ceph health detail
HEALTH_ERR 1 pgs inconsistent; 1 scrub errors
pg 9.14 is active+clean+inconsistent, acting [1,2,0]
1 scrub errors
这个有问题的 PG 分布在 osd.1 、 osd.2 和 osd.0 上,其中 osd.1 是主 OSD。


2、去主 OSD( osd.1 )的日志中查找不一致的具体对象 。

root@osd0:~# grep -Hn 'ERR' /var/log/ceph/ceph-osd.1.log
/var/log/ceph/ceph-osd.1.log:30:2016-11-10 13:49:07.848804 7f628c5e6700 -1 log_channel(cluster) log [ERR] : 9.14 shard 0: soid 9:29b4ad99:::rbd_data.1349f035c101d9.0000000000000001:head missing attr _
/var/log/ceph/ceph-osd.1.log:31:2016-11-10 13:49:07.849803 7f628c5e6700 -1 log_channel(cluster) log [ERR] : 9.14 scrub 0 missing, 1 inconsistent objects
/var/log/ceph/ceph-osd.1.log:32:2016-11-10 13:49:07.849824 7f628c5e6700 -1 log_channel(cluster) log [ERR] : 9.14 scrub 1 errors

从日志中可以知道,是 rbd_data.1349f035c101d9.0000000000000001 这个对象的属性 _ 丢失了,所以在 scrub 的过程中产生了 error 。

3、执行 ceph pg repair 命令修复问题 PG 。

root@mon:~# ceph pg repair 9.14
instructing pg 9.14 on osd.1 to repair

4、检查 Ceph 集群是否恢复到 HEALTH_OK 状态。

root@mon:~# ceph -s
    cluster 614e77b4-c997-490a-a3f9-e89aa0274da3
     health HEALTH_OK
     monmap e5: 1 mons at {osd1=10.95.2.43:6789/0}
            election epoch 796, quorum 0 osd1
     osdmap e1079: 3 osds: 3 up, 3 in
            flags sortbitwise
      pgmap v312171: 384 pgs, 6 pools, 1148 MB data, 311 objects
            3604 MB used, 73154 MB / 76759 MB avail
                 384 active+clean
osd.1 的日志里也提示修复成功:

2016-11-10 14:04:31.732640 7f628c5e6700  0 log_channel(cluster) log [INF] : 9.14 repair starts
2016-11-10 14:04:31.827951 7f628edeb700 -1 log_channel(cluster) log [ERR] : 9.14 shard 0: soid 9:29b4ad99:::rbd_data.1349f035c101d9.0000000000000001:head missing attr _
2016-11-10 14:04:31.828117 7f628edeb700 -1 log_channel(cluster) log [ERR] : 9.14 repair 0 missing, 1 inconsistent objects
2016-11-10 14:04:31.828273 7f628edeb700 -1 log_channel(cluster) log [ERR] : 9.14 repair 1 errors, 1 fixed
如果经过前面的步骤,Ceph 仍没有达到 HEALTH_OK 状态,可以尝试用下面这种方式进行修复。

1、停掉不一致的 object 所属的 osd 。
systemctl stop ceph-osd.target 

2、刷新该 osd 的日志。
ceph-osd -i <osd-id> --flush-journal

3、将不一致的 object 移除。
mv /var/lib/ceph/osd/ceph-{osd-id}/current/{pg.id}_head/ rbd\\udata.xxx /home

4、重新启动该 osd 。
systemctl start ceph-osd.target 

5、重新执行修复命令。
ceph pg repair {pg_id}

7.3.9 Too Many/Few PGs per OSD

有时候,我们在 ceph -s 的输出中可以看到如下的告警信息:

root@node241:~# ceph -s
    cluster 3b37db44-f401-4409-b3bb-75585d21adfe
     health HEALTH_WARN
            too many PGs per OSD (652 > max 300)
     monmap e1: 1 mons at {node241=192.168.2.41:6789/0}
            election epoch 1, quorum 0 node241
     osdmap e408: 5 osds: 5 up, 5 in
      pgmap v23049: 1088 pgs, 16 pools, 256 MB data, 2889 objects
            6100 MB used, 473 GB / 479 GB avail
                 1088 active+clean
                 
这是因为集群 OSD 数量较少,测试过程中建立了多个存储池,每个存储池都要建立一些 PGs 。而目前 Ceph 配置的默认值是每 OSD 上最多有 300 个 PGs 。在测试环境中,为了快速解决这个问题,可以调大集群的关于此选项的告警阀值。方法如下:

在 monitor 节点的 ceph.conf 配置文件中添加:

[global]
.......
mon_pg_warn_max_per_osd = 1000
然后重启 monitor 进程。

或者直接用 tell 命令在运行时更改参数的值而不用重启服务:

ceph tell mon.* injectargs '--mon_pg_warn_max_per_osd 1000'
而另一种情况, too few PGs per OSD (16 < min 20) 这样的告警信息则往往出现在集群刚刚建立起来,除了默认的 rbd 存储池,还没建立自己的存储池,再加上 OSD 个数较多,就会出现这个提示信息。这通常不是什么问题,也无需修改配置项,在建立了自己的存储池后,这个告警信息就会消失。

7.4 全局节点宕机

在极端情况下,如数据中心断电,造成 Ceph 存储集群全局宕机,可以按照本节所示流程进行 Ceph 集群上电恢复操作。

如为 Ceph 集群上电,monitor server 应最先上电;集群上电前确认使用 Ceph 之前端作业服务已停止。

8,ceph进阶

8.1. PG 和 PGP 的区别

 

【版权声明】
本文首发于云博客,欢迎转载,但是必须保留本文的署名云博客(包含链接)。
如您想成为本站的作者或者编辑,请给我留言:yun@yka.moe
本文永久链接:Ceph安装教程
本文作者:yun
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇