http://docs.ceph.org.cn/rados/ #ceph 集群配置、部署与运维
1 Ceph 集群维护
1.1 通过套接字进行单机管理
node 节点操作:
root@ceph-node1:~# ll /var/run/ceph/
total 0
drwxrwx--- 2 ceph ceph 120 Aug 26 21:46 ./
drwxr-xr-x 28 root root 960 Aug 27 16:02 ../
srwxr-xr-x 1 ceph ceph 0 Aug 26 21:46 ceph-osd.0.asok=
srwxr-xr-x 1 ceph ceph 0 Aug 26 21:46 ceph-osd.1.asok=
srwxr-xr-x 1 ceph ceph 0 Aug 26 21:46 ceph-osd.2.asok=
srwxr-xr-x 1 ceph ceph 0 Aug 26 21:46 ceph-osd.3.asok=
# 每个 node 节点上在 /var/run/ceph/ 目录下都有 osd 进程都有一个套接字文件
# 这个 osd 套接字文件可以和当前进程直接交互
我们如果想通过套接字文件来进行管理的话就必须得有 ceph 得认证文件,也就是在 node 节点上能执行 ceph -s 命令
# 在 node1 节点上执行 ceph -s
root@ceph-node1:~# ceph -s
cluster:
id: 14ce1d1a-3323-4337-963a-f96484ddd363
health: HEALTH_OK
services:
mon: 3 daemons, quorum ceph-mon1,ceph-mon2,ceph-mon3 (age 56m)
mgr: ceph-mgr1(active, since 18h), standbys: ceph-mgr2
mds: 1/1 daemons up
osd: 16 osds: 16 up (since 56m), 16 in (since 6d)
rgw: 1 daemon active (1 hosts, 1 zones)
data:
volumes: 1/1 healthy
pools: 10 pools, 313 pgs
objects: 232 objects, 14 MiB
usage: 1.1 GiB used, 1.6 TiB / 1.6 TiB avail
pgs: 313 active+clean
# 可在 node 节点或者 mon 节点通过 ceph 命令进行单机管理本机的 mon 或者 osd 服务:
# 先将 admin 认证文件同步到 mon 或者 node 节点:
通过指定对 ceph-osd.3.asok 套接字文件操作查看帮助信息
root@ceph-node1:~# ceph --admin-socket /var/run/ceph/ceph-osd.3.asok --help
一般我们都不会通过这种方式来执行,而是通过 ceph 命令来查看
1.2 ceph 集群的停止或重启
比如在工作中突发意外情况,比如断电,我们就需要通过这种方式来进行集群的停止和重启
重启之前,要提前设置 ceph 集群不要将 OSD 标记为 out,避免 node 节点关闭服务后被踢出 ceph 集群外:
# 通过查看 node 节点的 osd 监听 3300 端口
root@ceph-node1:~# netstat -tanlp | grep 3300
tcp 0 0 10.0.0.107:40534 10.0.0.104:3300 ESTABLISHED 1364/ceph-osd
tcp 0 0 10.0.0.107:40532 10.0.0.104:3300 ESTABLISHED 1365/ceph-osd
tcp 0 0 10.0.0.107:40528 10.0.0.104:3300 ESTABLISHED 1366/ceph-osd
tcp 0 0 10.0.0.107:40524 10.0.0.104:3300 ESTABLISHED 1367/ceph-osd
# 这就是 node 节点的 osd 需要向 mon 节点同步数据,默认情况下是 6s 汇报一次当前所以的 osd 状态
# mon 认为 20s 之后 osd 没有向他同步状态,mon 就会将该 osd 标记为 out 状态
# 标记为 out 状态之后 ceph 内部就会开始进行选举状态和数据同步
所以我们在重启之后为了避免服务 osd 被提出 ceph 集群,就可以通过下面操作:
# 关闭服务前设置 noout 即使 osd 宕机了也不会将他踢出 ceph 集群
[16:41:23 ceph@ceph-deploy ceph-cluster]$ceph osd set noout
# ceph -s 查看会多出来一条警告信息
[16:42:26 ceph@ceph-deploy ceph-cluster]$ceph -s
cluster:
id: 14ce1d1a-3323-4337-963a-f96484ddd363
health: HEALTH_WARN
noout flag(s) set # 警告信息
# 当然我们重启好了之后就要立即取消 noout 这个设置
[16:43:02 ceph@ceph-deploy ceph-cluster]$ceph osd unset noout
1.2.1 集群关闭顺序
# 关闭服务前设置 noout
# 关闭存储客户端停止读写数据,如什么 mysql java 等程序确保客户端不在写入数据
# 如果使用了 RGW,关闭 RGW
# 关闭 cephfs 元数据服务
# 关闭 ceph OSD
# 关闭 ceph manager 关
# 闭 ceph monitor
1.2.2 启动顺序
# 启动 ceph monitor
# 启动 ceph manager
# 启动 ceph OSD
# 关闭 cephfs 元数据服务
# 启动 RGW
# 启动存储客户端
# 启动服务后取消 noout-->ceph osd unset noout
1.2.3 添加服务器
后期生产环境中可能存储空间不够我们会涉及到添加服务器
1.添加 ceph 仓库源
2.导入 ceph key
3.ceph-deploy install --release pacific ceph-node
4.擦除磁盘:
ceph-deploy disk zap ceph-node /dev/sdb
5.添加 osd
sudo ceph-deploy osd create ceph-node --data /dev/sdb
1.2.4 删除服务器
在 ceph 集群中删除我们不想要的服务器,但是停用服务器之前要把服务器的 osd 先停用并从 ceph 集群中删除
1.将 osd 提出 ceph 集群
ceph osd out
2.等待一段时间
3.停止 osd.x 进程
systemctl stop ceph-osd
4.删除 osd
ceph osd rm 1
5.当前主机的其它磁盘重复以下操作
6.OSD 全部操作完毕后下线主机
1.3 ceph 配置文件
Ceph 的主配置文件是/etc/ceph/ceph.conf,ceph 服务在启动时会检查 cep.conf,分号;和
ceph 在启动的时候会读取这个配置文件
#在配置文件中都是注释,ceph.conf 主要由以下配置段组成:
[global] #全局配置
[osd] #osd 专用配置,可以使用 osd.N,来表示某一个 OSD 专用配置,N 为 osd 的编号, 如 0、2、1 等。
[mon] #mon 专用配置,也可以使用 mon.A 来为某一个 monitor 节点做专用配置,其中 A 为该节点的名称,ceph-monitor-2、ceph-monitor-1 等,使用命令 ceph mon dump 可以 获取节点的名称
[client] #客户端专用配置。
ceph 文件的加载顺序:
$CEPH_CONF 环境变量
-c 指定的位置
/etc/ceph/ceph.conf # 默认读取
~/.ceph/ceph.conf # 读取 ceph 用户目录下的配置
./ceph.conf # 当前目录下 ceph.conf 配置
2 存储池、PG 与 CRUSH
存储池分为两类:
-
副本池(replicated)使用较多:定义每个对象在集群中保存为多少个副本,默认为三个副本,一主两备,实现高可用,副本池是 ceph 默认的存储池类型。在我们创建的时候可以指定副本池的类型
-
纠删码池(erasure code)使用较少:因为纠删码池数据的高可用机制不是很强,而我们使用 ceph 就是使用它的多副本机制,把各对象存储为 N=K+M 个块,其中 K 为数据块数量,M 为编码块数量,因此存储池的尺寸为 K+M。 即数据保存在 K 个数据块,并提供 M 个冗余块提供数据高可用,那么最多能故障的块就是 M 个,实际的磁盘占用就是 K+M 块,因此相比副本池机制比较节省存储资源,一般采用 8+4 机制,即 8 个数据块+4 个冗余块,那么也就是 12 个数据块有 8 个数据块保存数据, 有 4 个实现数据冗余,即 1/3 的磁盘空间用于数据冗余,比默认副本池的三倍冗余节省空间, 但是不能出现大于一定数据块故障
但是不是所有的应用都支持纠删码池,RBD 只支持副本池而 radosgw 则可以支持纠删码池。
2.1 副本池 IO 流程
将一个数据对象存储为多个副本
在客户端写入操作时,ceph 使用 CRUSH 算法计算出与对象相对应的 PG ID 和 primary OSD 主 OSD 根据设置的副本数、对象名称、存储池名称和集群运行图(cluster map)计算出 PG 的各辅助 OSD,然后由 OSD 将数据再同步给副本 OSD。
读取数据:
-
客户端发送读请求,ceph 会将这个请求发给主的 osd(primary osd),由主的 osd 来从磁盘中读取数据
-
主 OSD 从本地磁盘读取数据并返回数据,最终完成读取请求
写入数据:
-
由客户端发起写请求,然后再发给我们的 RADOS 集群
-
RADOS 集群通过 CRUSH 算法,计算出往那个主的 OSD 上进行写入操作
-
主 OSD 会标记处他的副本 osd
-
主 osd 这时候会同时在本地写并将数据同步发送给副本 osd
-
副本 OSD 写完之后给主 OSD 返回信号说写完了
-
等全部副本 OSD 写入信号返回给主 OSD 之后,主 OSD 在返回给客户端说数据写完了
2.2 纠删码池 IO(使用较少)
http://ceph.org.cn/2016/08/01/ceph-%E7%BA%A0%E5%88%A0%E7%A0%81%E4%BB%8B%E7%BB%8D/
Ceph 从 Firefly 版本开始支持纠删码,但是不推荐在生产环境使用纠删码池。纠删码池降低了数据保存所需要的磁盘总空间数量,但是读写数据的计算成本要比副本池高 RGW 可以支持纠删码池,RBD 不支持纠删码池可以降低企业的前期 TCO 总拥有成本
纠删码写:
数据将在主 OSD 进行编码然后分发到相应的 OSDs 上去。
-
计算出合适的数据块并进行编码(需要看纠删码池创建了几个副本)
-
然后对每个数据块进行编码,并写到不同的 osd 上
2.2.1 纠删码池使用
1.创建纠删码池
# 创建纠删码池命名为 erasure-testpool
[17:20:31 ceph@ceph-deploy ceph-cluster]$ceph osd pool create erasure-testpool 16 16 erasure
pool 'erasure-testpool' created
# erasure 指定存储池类型为 erasure 纠删码池
# 查看纠删码池信息
[18:04:18 ceph@ceph-deploy ceph-cluster]$ceph osd erasure-code-profile get default
k=2
m=2
plugin=jerasure
technique=reed_sol_van
# 参数解析
k=2 #k 为数据块的数量,即要将原始对象分割成的块数量,例如,如果 k = 2,则会将一个 10kB 对象分割成各为 5kB 的 k 个对象。
m=2 #编码块(chunk)的数量,即编码函数计算的额外块的数量。如果有 2 个编码块,则表 示有两个额外的备份,最多可以从当前 pg 中宕机 2 个 OSD,而不会丢失数据。
plugin=jerasure # 纠删码池通过jerasure算法进行计算数据的存储
technique=reed_sol_van
2.写入数据:
[18:15:20 ceph@ceph-deploy ceph-cluster]$sudo rados put -p erasure-testpool testfile1 /var/log/syslog
# -p erasure-testpool :指定 pool
# testfile1 :写入到 pool 中的名称
# /var/log/syslog :写入我们的 /var/log/syslog 文件
3.验证数据
# 通过 ceph osd map 验证写入的数据是否成功写入
[18:38:18 ceph@ceph-deploy ceph-cluster]$ceph osd map erasure-testpool testfile1
osdmap e313 pool 'erasure-testpool' (11) object 'testfile1' -> pg 11.3a643fcb (11.b) -> up ([3,4,8,12], p3)acting ([3,4,8,12], p3)
# 写入到 [3,4,8,12], p3 pgp 中 3 是主 osd
# pg 11.3a643fcb 放到了该 pg 中
# erasure-testpool :指定 pool 名称
# testfile1 :指定我们写入到存储池中的数据对象
4.验证当前 pg 状态
[18:43:11 ceph@ceph-deploy ceph-cluster]$ceph pg ls-by-pool erasure-testpool | awk '{print $1,$2,$15}'
PG OBJECTS ACTING
11.0 0 [1,6,13,8]p1
11.1 0 [14,10,2,6]p14
11.2 0 [2,9,14,5]p2
11.3 0 [10,15,7,3]p10
11.4 0 [7,15,1,9]p7
11.5 0 [12,5,1,11]p12
11.6 0 [15,1,9,6]p15
11.7 0 [5,1,14,11]p5
11.8 0 [8,0,6,12]p8
11.9 0 [3,12,11,7]p3
11.a 0 [11,6,2,13]p11
11.b 1 [3,4,8,12]p3
11.c 0 [15,2,7,9]p15
11.d 0 [2,6,11,12]p2
11.e 0 [10,15,6,2]p10
11.f 0 [7,11,14,0]p7
* NOTE: afterwards
5.测试获取数据:
[18:48:13 ceph@ceph-deploy ceph-cluster]$rados --pool erasure-testpool get testfile1 -
# 这是我存储池刚才写入的数据
Aug 27 18:04:14 ceph-deploy systemd-timesyncd[566]: Timed out waiting for reply from 91.189.89.199:123 (ntp.ubuntu.com).
....
6.从 pool 中下载数据
# 下载数据
[18:50:34 ceph@ceph-deploy ceph-cluster]$sudo rados get -p erasure-testpool testfile1 /root/testfiel1
# 已经下载至 /root/testfiel1 中
[18:52:13 ceph@ceph-deploy ceph-cluster]$sudo ls -l /root/testfiel1
-rw-r--r-- 1 root root 1778981 Aug 27 18:50 /root/testfiel1
纠删码读:
从相应的 OSDs 中获取数据后进行解码
如果此时有数据丢失,Ceph 会自动从存放校验码的 OSD 中读取数据进行解码。
2.3 PG 与 PGP 计算
一个存储池中应该有多少个 pg 维持在一个合理的值
PG = Placement Group
# 归置组,也就是说数据在往 ceph 写的时候,对于副本池来说是被拆分为多少份,如果是一个 G 的数据写入过来会被拆分为几份
PGP = Placement Group for Placement purpose
# 归置组的组合,pgp 相当于是 pg 对应 osd 的一种排列组合关系。
# 如果我要是有个 4 个 PG 那么我这 4 个 PG 该怎么组合呢,这个 pgp 组合关系数量一般在创建的时候和 PG 是一样的
PG 归置组(placement group)是用于跨越多 OSD 将数据存储在每个存储池中的内部数据结构。
PG 归置组在 OSD 守护进程和 ceph 客户端之间生成了一个中间层,CRUSH 算法负责将每个对象动态映射到一个归置组,然后再将每个归置组动态映射到一个或多个 OSD 守护进程,从而能够支持在新的 OSD 设备上线时进行数据重新平衡
如上图,也就是数据写入到 ceph 集群之后呢需要被拆分为多少份,这个 file 如果是数据比较大在往 ceph 中写的话,会被 ceph 拆分为对象,对象又被写入到 pool 中,pool 中的数据又往磁盘写入的时候会被归纳为 PG ,我们的 PG 有几个,就是我们的对象拆分颗粒度,这个颗粒度就是通过 file 数据的大小来判断,数据越大 PG 越多,如果说这个 file 是 5G ,这里是两个 PG 的话每个 PG 就会写入 2.5G ,如果这个时候 pg1 中的主 osd1 挂了,Ceph 就会在集群中会新选一个 osd 作为备的,并在 osd4 、osd7 中选举一个主的 osd
这里假如 osd4 是新的主 osd ,然后会在添加两个 osd 作为备 osd ,并且向这两个备 osd 同步 2.5G 数据,如果这个文件是 50G 呢,就会往这两个备的 osd 同步 25G 数据。
所以这个地方我们会按照数据的大小进行拆分,如果我们上传的数据越大那我们的 pg 就会被拆分的越多。
一般来说几百个 G 的数据没有达到 T 的级别,32 个 PG 就够了,如果上 T 了就用 64 个 PG 。
由此得出结论:
-
PG 数量:是根据业务的数据量来决定的(一定是 2 的整次方)
-
相对于存储池来说,PG 是一个虚拟组件,它是对象映射到存储池时使用的虚拟层。
-
PGP 组合关系一般都是和 PG 数量一样,可以自定义存储池中的归置组数量。
-
ceph 出于规模伸缩及性能方面的考虑,ceph 将存储池细分为多个归置组,把每个单独的对 象映射到归置组,并为归置组分配一个主 OSD。
-
存储池由一系列的归置组组成,而 CRUSH 算法则根据集群运行图和集群状态,将个 PG 均 匀、伪随机(基于 hash 映射,每次的计算结果够一样)的分布到集群中的 OSD 之上。
-
如果某个 OSD 失败或需要对集群进行重新平衡,ceph 则移动或复制整个归置组而不需要 单独对每个镜像进行寻址
2.4 PG 与 OSD 的关系
ceph 基于 crush 算法将归置组 PG 分配至 OSD 当一个客户端存储对象的时候,CRUSH 算法映射每一个对象至归置组(PG)
多各对象被映射到 PG 里面,一个 PG 中有三个副本,一个 OSD 可以属于多个 PG ,而且同一个 OSD 在每个 PG 中的角色还会不一样,比如说他在 PG1 中是一个主 OSD ,可能在 PG2 中就是一个备 OSD ,这种就是通过 CRUSH 算法来动态维护的,如上图中 OSD1 坏了他会重新在 OSD2、3、4 中重新选举一个新的主节点,然后再将别的 OSD 添加进来,再通过主 OSD 同步数据给新的备 OSD
2.5 PG 分配计算
归置组(PG)的数量是由管理员在创建存储池的时候指定的,然后由 CRUSH 负责创建和使用,PG 的数量是 2 的 N 次方的倍数,每个 OSD 的 PG 不要超出 250 个 PG,官方是每个 OSD 100 个 左 右
https://docs.ceph.com/en/mimic/rados/configuration/pool-pg-config-ref/
确保设置了合适的归置组大小,我们建议每个 OSD 大约 100 个,例如,osd 总数乘以 100 除以副本数量(即 osd 池默认大小),因此,对于 10 个 osd、存储池为 4 个,我们建议每 个存储池大约(100 * 10)/4=256 1.通常,PG 的数量应该是数据的合理力度的子集。 例如:一个包含 256 个 PG 的存储池,每个 PG 中包含大约 1/256 的存储池数据 2.当需要将 PG 从一个 OSD 移动到另一个 OSD 的时候,PG 的数量会对性能产生影响。 PG 的数量过少,一个 OSD 上保存的数据数据会相对加多,那么 ceph 同步数据的时候产 生的网络负载将对集群的性能输出产生一定影响。 PG 过多的时候,ceph 将会占用过多的 CPU 和内存资源用于记录 PG 的状态信息 3.PG 的数量在集群分发数据和重新平衡时扮演者重要的角色作用 在所有 OSD 质检进行数据持久存储以及完成数据分布会需要较多的归置组,但是他们的数量应该减少到实现 ceph 最大性能所需的最小 PG 数量值,以节省 CPU 和内存资源。 一般来说,对于有着超过 50 个 OSD 的 RADOS 集群,建议每个 OSD 大约有 50-100 个 PG 以平衡资源使用及取得更好的数据持久性和数据分布,而在更大的集群中,每个 OSD 可以有 100-200 个 PG 至于一个 pool 应该使用多少个 PG,可以通过下面的公式计算后,将 pool 的 PG 值四舍 五入到最近的 2 的 N 次幂,如下先计算出 ceph 集群的总 PG 数: Total OSDs * PGPerOSD/replication factor => total PGs 磁盘总数 x 每个磁盘 PG 数 / 副本数 => ceph 集群总 PG 数(略大于 2^n 次方) 官方的计算公式: Total PGs = (Total_number_of_OSD * 100) / max_replication_count 单个 pool 的 PG 计算如下: 有 100 个 osd,3 副本,5 个 pool Total PGs =100 * 100 / 3=3333 每个 pool 的 PG=3333 / 5=512,那么创建 pool 的时候就指定 pg 为 512 需要结合数据数量、磁盘数量及磁盘空间计算出 PG 数量,8、16、32、64、128、256 等 2 的 N 次方。 一个 RADOS 集群上会存在多个存储池,因此管理员还需要考虑所有存储池上的 PG 分布 后每个 OSD 需要映射的 PG 数量。
这里我创建一些不合法的 pg 和 pgp ,ceph 会有告警
1.这里创建 pg 的数量非 2 的整次方告警演示
# 这里创建的 pg 和 pgp 非 2 的整次方
[10:28:32 ceph@ceph-deploy ceph-cluster]$ceph osd pool create testpool2 60 60
pool 'testpool2' created
# 会报出警告
root@ceph-deploy:/etc/cron.hourly# ceph -s
health: HEALTH_WARN
1 pool(s) do not have an application enabled
1 pool(s) have non-power-of-two pg_num # pg 数量非 2 的整次方
-
pg 数量大于 pgp 告警演示
# 这里创建的 pg 为 30 pgp 为 20 root@ceph-deploy:~# ceph osd pool create testpoo3 30 20 pool 'testpoo3' created
报错 pg 数量大于 pgp
虽然会报警,但是还是能够正常使用,这不过这样的 pg 和 pgp 方式会导致我们的 ceph 集群在后期使用的时候会出现异常问题,所以我这里再将它们删除
2.5.1 删除 pool 操作
我们在删除之前需要关闭 mon 的访问机制,因为 mon 节点默认是不让我们删除 pool
1.先列出 pool 信息
root@ceph-deploy:~# ceph osd pool ls
device_health_metrics
32
mypool
myrbd1
.rgw.root
default.rgw.log
default.rgw.control
default.rgw.meta
cephfs-metadata
cephfs-data
erasure-testpool # 需要删除
testpool2 # 需要删除
testpoo3 # 需要删除
2.关闭 mon 访问机制,让 mon 允许删除 pool 存储池
root@ceph-deploy:~# ceph tell mon.* injectargs --mon-allow-pool-delete=true
mon.ceph-mon1: {}
mon.ceph-mon1: mon_allow_pool_delete = 'true'
mon.ceph-mon2: {}
mon.ceph-mon2: mon_allow_pool_delete = 'true'
mon.ceph-mon3: {}
mon.ceph-mon3: mon_allow_pool_delete = 'true'
# --mon-allow-pool-delete=true:允许所有 pool delete 为 true
3.在删除 pool 即可
# 先执行 rm testpool2
root@ceph-deploy:~# ceph osd pool rm testpool2 testpool2
# 然后再确认执行要删除 testpool2
root@ceph-deploy:~# ceph osd pool rm testpool2 testpool2 --yes-i-really-really-mean-it
# 删除 testpoo3 pool
root@ceph-deploy:~# ceph osd pool rm testpoo3 testpoo3 --yes-i-really-really-mean-it
# 删除 erasure-testpool
root@ceph-deploy:~# ceph osd pool rm erasure-testpool erasure-testpool --yes-i-really-really-mean-it
4.再次查看已经删除
root@ceph-deploy:~# ceph osd pool ls
device_health_metrics
32
mypool
myrbd1
.rgw.root
default.rgw.log
default.rgw.control
default.rgw.meta
cephfs-metadata
cephfs-data
5.删除完毕之后再将 mon 允许删除 pool 功能关闭,这样能够保证我们的数据安全
root@ceph-deploy:~# ceph tell mon.* injectargs --mon-allow-pool-delete=false
mon.ceph-mon1: {}
mon.ceph-mon1: mon_allow_pool_delete = 'false'
mon.ceph-mon2: {}
mon.ceph-mon2: mon_allow_pool_delete = 'false'
mon.ceph-mon3: {}
mon.ceph-mon3: mon_allow_pool_delete = 'false'
6.通过 ceph-s 查看该集群已经没有告警
2.6 :验证 PG 与 PGP 组合:
root@ceph-deploy:~# ceph pg ls-by-pool cephfs-metadata | awk '{print $1,$2,$15}'
PG OBJECTS ACTING
9.0 4 [1,13,11]p1
9.1 1 [15,3,9]p15
9.2 0 [14,1,9]p14
9.3 2 [9,15,5]p9
9.4 4 [1,4,12]p1
9.5 2 [11,12,7]p11
9.6 1 [12,1,9]p12
9.7 1 [10,12,2]p10
9.8 0 [12,1,5]p12
9.9 0 [10,5,12]p10
9.a 0 [5,14,3]p5
9.b 1 [8,5,15]p8
9.c 1 [3,12,10]p3
9.d 2 [7,14,8]p7
9.e 1 [7,10,1]p7
9.f 3 [5,12,9]p5
* NOTE: afterwards
2.7 :PG 的状态
PG 的常见在状态如下:
一般通过 ceph-s
然后再 pgs 后面会显示当前 pg 的状态信息
2.7.1 Peering
数据正在同步状态,同一个 PG 中的 OSD 需要将准备数据同步一致,而 Peering(对等)就是 OSD 同步数据过程中的状态。
2.7.2 Activating
Peering 同步已经完成,PG 正在等待所有 PG 实例同步 Peering 的结果(Info、Log 等)
2.7.3 Clean
干净态,PG 当前不存在待修复的对象,并且大小等于存储池的副本数,即 PG 的活动集 (Acting Set)和上行集(Up Set)为同一组 OSD 且内容一致。
活动集(Acting Set):由 PG 当前主的 OSD 和其余处于活动状态的备用 OSD 组成,当前 PG 内的 OSD 负责处理用户的读写请求。
上行集(Up Set):在某一个 OSD 故障时,需要将故障的 OSD 更换为可用的 OSD,并主 PG 内部的主 OSD 同步数据到新的 OSD 上,例如 PG 内有 OSD1、OSD2、OSD3,当 OSD3 故障后需要用 OSD4 替换 OSD3,那么 OSD1、OSD2、OSD3 就是上行集,替换后 OSD1、 OSD2、OSD4 就是活动集,OSD 替换完成后活动集最终要替换上行集
2.7.4 Active
就绪状态或活跃状态,Active 表示主 OSD 和备 OSD 处于正常工作状态,此时的 PG 可以正常处理来自客户端的读写请求,正常的 PG 默认就是 Active+Clean 状态。
root@ceph-deploy:~# ceph pg stat
313 pgs: 313 active+clean; 14 MiB data, 594 MiB used, 1.6 TiB / 1.6 TiB avail
2.7.5 Degraded:降级状态
降级状态出现于 OSD 被标记为 down 以后,那么其他映射到此 OSD 的 PG 都会转换到降级状态。
如果此 OSD 还能重新启动完成并完成 Peering 操作后,那么使用此 OSD 的 PG 将重新恢复为 clean 状态。
如果此 OSD 被标记为 down 的时间超过 5 分钟还没有修复,那么此 OSD 将会被 ceph 踢出集群,然后 ceph 会对被降级的 PG 启动恢复操作,直到所有由于此 OSD 而被降级的 PG
重新恢复为 clean 状态。
恢复数据会从 PG 内的主 OSD 恢复,如果是主 OSD 故障,那么会在剩下的两个备用 OSD 重新选择一个作为主 OSD。
2.7.6 Stale:过期状态
正常状态下,每个主 OSD 都要周期性的向 RADOS 集群中的监视器(Mon)报告其作为主 OSD 所持有的所有 PG 的最新统计数据,因任何原因导致某个 OSD 无法正常向监视器发送汇报 信息的、或者由其他 OSD 报告某个 OSD 已经 down 的时候,则所有以此 OSD 为主 PG 则 、会立即被标记为 stale 状态,即他们的主 OSD 已经不是最新的数据了,如果是备份的 OSD发送 down 的时候,则 ceph 会执行修复而不会触发 PG 状态转换为 stale 状态
2.7.7 undersized
PG 当前副本数小于其存储池定义的值的时候,PG 会转换为 undersized 状态,比如两个备份 OSD 都 down 了,那么此时 PG 中就只有一个主 OSD 了,不符合 ceph 最少要求一个主 OSD 加一个备 OSD 的要求,那么就会导致使用此 OSD 的 PG 转换为 undersized 状态, 直到添加备份 OSD 添加完成,或者修复完成。
2.7.8 Scrubbing 数据清洗
scrub 是 ceph 对数据的清洗状态,用来保证数据完整性的机制,Ceph 的 OSD 定期启动 scrub 线程来扫描部分对象,通过与其他副本比对来发现是否一致,如果存在不一致,抛出异常提示用户手动解决,scrub 以 PG 为单位,对于每一个 pg,ceph 分析该 pg 下所有的 object, 产生一个类似于元数据信息摘要的数据结构,如对象大小,属性等,叫 scrubmap, 比较主与副 scrubmap,来保证是不是有 object 丢失或者不匹配,扫描分为轻量级扫描和 深度扫描,轻量级扫描也叫做 light scrubs 或者 shallow scrubs 或者 simply scrubs 即轻量 级扫描.
Light scrub(daily)比较 object size 和属性,deep scrub (weekly)读取数据部分并通过 checksum(CRC32 算 法 ) 对 比 和 数 据 的 一 致 性 , 深度扫描过程中的 PG 会 处 于 scrubbing+deep 状态。
浅整理只会整理数据的元数据信息
深整理会整理数据的元数据和数据本身来保证 ceph 中各个 OSD 的数据都是一样的
2.7.9 Recovering
正在恢复态,集群正在执行迁移或同步对象和他们的副本,这可能是由于添加了一个新的 OSD 到集群中或者某个 OSD 宕掉后,PG 可能会被 CRUSH 算法重新分配不同的 OSD,而由于 OSD 更换导致 PG 发生内部数据同步的过程中的 PG 会被标记为 Recovering。
2.7.10 Backfilling
正在后台填充态,backfill 是 recovery 的一种特殊场景,指 peering 完成后,如果基于当前权威日志无法对 Up Set(上行集)当中的某些 PG 实例实施增量同步(例如承载这些 PG 实例的 OSD 离线太久,或者是新的 OSD 加入集群导致的 PG 实例整体迁移) 则通过完全拷贝当前 Primary 所有对象的方式进行全量同步,此过程中的 PG 会处于 backfilling。
2.7.11 Backfill-toofull
某个需要被 Backfill 的 PG 实例,其所在的 OSD 可用空间不足,Backfill 流程当前被挂起时 PG 给的状态。
PG 状态演示