ceph FS 即 ceph filesystem,可以实现文件系统共享功能,客户端通过 ceph 协议挂载并使用 ceph 集群作为数据存储服务器。
在 deploy 节点上查看对应的存储池信息,一般使用 ceph-fs 都会创建两个存储池
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 # 用于存储数据本身
也就是 mds 服务本身不负责对数据的高可用,所有数据信息都放到元数据存储池来实现高可用。如果 mds 服务挂了我们的 ceph-fs 就不能使用,所以这个风险相对较大,我们客户端在挂载的时候都是挂载 cephmds 服务 6789 端口这种情况下我们就会通过下图的方式来实现高可用
ceph-fs 高可用原理图
如上图,这个高可用就是基于多 mds 节点的方式来实现,mds 有多个的话都可以对客户端提供响应,如果客户端需要往 ceph 存储池中写入数据的话,这个数据就会通过某个 mds 服务向 ceph 存储池中写入数据,也就是 ceph-fs 的元数据都一定会在存储池的磁盘上来实现高可用,但是这个由那个 mds 服务来写入呢,这个时候就会用到元数据的动态子树分区
动态子树分区:
http://docs.ceph.org.cn/cephfs/
cephfs 的元数据使用的动态子树分区,把元数据划分名称空间对应到不同的 mds,写入元数据 的时候将元数据按照名称保存到不同主 mds 上,有点类似于 nginx 中的缓存目录分层一样.
元数据是有名称的按照什么名称开头的,然后将他分到那个那个主机上去,例如上图,是通过从上往下分叉结构,把某些以什么打头的文件分给那些 mds 服务进行读写。
最上面是客户端 ,我们的那些服务器可用,mon 会进行统计,当 mon 统计完了之后我们的客户端连接到 mon 就会连接到元数据列表,假如 /a
的文件就会交给 mds1 服务器处理,/b
开头的文件就会交给 mds2 服务器处理,/c
交给 mds3 服务器处理,/d
交给 mds4 服务器处理。
这种分类我们会使用动态分区,那些文件映射到那些服务器上并不会将他们写死,如果我们写死会出现的问题就是,如果这个 mds 服务器宕了怎么办?这时候客户端还是会到这个已经宕掉的 mds 服务器上进行元数据查询,就会发生元数据查不到丢失的问题,所以我们会使用动态。
动态分区:如果 mds 服务器内部节点宕机,其他的 mds 服务就会进行数据同步,将宕机节点的 mds 服务中的元数据再次划分到别的 mds 服务器上。
虽然 mds 部署在不同的服务器上,但是在 mds 的后台数据中其实就是一个 ceph 元数据存储池,在这个存储池下面又是多个不同的 osd
这 4 个 mds 服务各自来维护自己的元数据,并且把数据写到 ceph 存储池中,从而实现数据的一致性
动态分区好处:
如果有 mds 服务器宕机,并不会导致整个 ceph-fs 的不可用。
而且我们一般会给每个 mds active 节点起一个备份节点 standby 节点,因为如果让 mds 重新分的话会涉及到很高的负载,所以通过这种方式当 active 节点宕之后让 standby 接替 active 的元数据读写工作,这样比较耗费服务器但是高可用会做得很好,这样就不会触发 mds 的元数据重新分配
7.1 部署 MDS 服务
我部署高可用的 MDS 服务。这里我们可以将 mds 服务部署在 mon 节点上,当然如果我们使用 ceph-fs 较多的话我们可以单独部署在节点上
Ubuntu 部署方式:
root@ceph-mgr1:~# apt-cache madison ceph-mds
root@ceph-mgr1:~# apt install ceph-mds
Centos 部署方式:
[root@ceph-mgr1 ~]# yum install ceph-mds
这里通过 Ubuntu 进行演示
1.安装 mds 服务
# 分别在三个 mon 节点安装 mds
root@ceph-mon1:~# apt install ceph-mds
root@ceph-mon2:~# apt install ceph-mds
root@ceph-mon3:~# apt install ceph-mds
# 添加 mds 服务至 ceph-mgr1 节点
root@ceph-deploy:~# ceph-deploy mds create ceph-mon1
7.2 创建 CephFS metadata 和 data 存储池
使用 CephFS 之前需要事先于集群中创建一个文件系统,并为其分别指定元数据和数据相关的存储池。下面创建一个名为 cephfs 的文件系统用于测试,它使用 cephfs-metadata 为元数据存储池,使用 cephfs-data 为数据存储池:
# 创建元数据存储池
root@ceph-deploy:~# ceph osd pool create cephfs-metadata 32 32
# 创建数据本身存储池
root@ceph-deploy:~# ceph osd pool create cephfs-data 64 64
7.3 创建 CephFS 并验证
# 创建 mycephfs 的 cephfs,并且指定他的元数据存储池和数据本身存储池
root@ceph-deploy:~# ceph fs new mycephfs cephfs-metadata cephfs-data
# 验证 mycephfs 已经创建
root@ceph-deploy:~# ceph fs ls
name: mycephfs, metadata pool: cephfs-metadata, data pools: [cephfs-data ]
# 验证当前 cephfs 状态
root@ceph-deploy:~# ceph fs status
mycephfs - 0 clients
========
RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS
0 active ceph-mgr1 Reqs: 0 /s 16 14 12 0
POOL TYPE USED AVAIL
cephfs-metadata metadata 431k 506G
cephfs-data data 12.0k 506G
MDS version: ceph version 16.2.5 (0883bdea7337b95e4b611c768c0279868462204a) pacific (stable)
7.4 验证 cephfs 服务状态
root@ceph-deploy:~# ceph mds stat
mycephfs:1 {0=ceph-mgr1=up:active} # 现在已经转变为活动状态
7.5 创建客户端账户并导出 key
在 deploy 节点上创建普通用户,等会用于客户端使用
# 先查看我们现在的 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
rbd-data1
# 创建客户端 guigui 用户对 mon 权限只读,对 mds 读写,对 cephfs-data 存储池 读写执行
root@ceph-deploy:~# ceph auth add client.guigui mon 'allow r' mds 'allow rw' osd 'allow rwx pool=cephfs-data'
added key for client.guigui
# 查看 guigui 属性
root@ceph-deploy:~# ceph auth get client.guigui
[client.guigui]
key = AQD23S1hINJHERAAaqQpjx/3vHhZDJNGjapxfg==
caps mds = "allow rw"
caps mon = "allow r"
caps osd = "allow rwx pool=cephfs-data"
exported keyring for client.guigui
# 创建 keyring 文件
root@ceph-deploy:~# ceph auth get client.guigui -o ceph.client.guigui.keyring
# 创建 key 文件
root@ceph-deploy:~# ceph auth print-key client.guigui > guigui.key
7.6 客户端安装 ceph 客户端
由于我整个实验中都安装了 ceph 的客户端,所以我这里不用安装了,假如没有安装的话我们需要通过下面的命令进行安装
下面是通过 centos7 进行安装
[root@ceph-client3 ~]# yum install epel-release -y
[root@ceph-client3 ~]# yum install https://mirrors.aliyun.com/ceph/rpm-octopus/el7/noarch/ceph-release-1-1.el7.noarch.rpm
[root@ceph-client3 ~]# yum install ceph-common -y
7.7 同步客户端认证文件
等客户端安装好了 ceph 客户端之后,我将 deploy 节点上客户端认证文件拷贝至客户端上
# 拷贝给 10.0.0.3 客户端
root@ceph-deploy:~# scp /home/ceph/ceph-cluster/ceph.conf ceph.client.guigui.keyring guigui.key 10.0.0.3:/etc/ceph
# 拷贝给 10.0.0.30 客户端
root@ceph-deploy:~# scp /home/ceph/ceph-cluster/ceph.conf ceph.client.guigui.keyring guigui.key 10.0.0.30:/etc/ceph
# /home/ceph/ceph-cluster/ceph.conf :ceph 配置文件
# ceph.client.guigui.keyring :guigui 客户端 keyring 文件
# guigui.key :guigui key 文件
7.6 客户端验证权限
# 指定 guigui 用户访问 ceph 集群
[15:58:25 root@go ~]#ceph --user guigui -s
cluster:
id: 14ce1d1a-3323-4337-963a-f96484ddd363
health: HEALTH_OK
services:
mon: 3 daemons, quorum ceph-mon1,ceph-mon2,ceph-mon3 (age 6h)
mgr: ceph-mgr1(active, since 6h), standbys: ceph-mgr2
mds: 1/1 daemons up
osd: 16 osds: 16 up (since 6h), 16 in (since 3d)
rgw: 1 daemon active (1 hosts, 1 zones)
data:
volumes: 1/1 healthy
pools: 11 pools, 377 pgs
objects: 314 objects, 66 MiB
usage: 715 MiB used, 1.6 TiB / 1.6 TiB avail
pgs: 377 active+clean
7.9 内核空间挂载 ceph-fs
客户端挂载有两种方式,一是内核空间一是用户空间,内核空间挂载需要内核支持 ceph 模块,用户空间挂载需要安装 ceph-fuse,用户空间挂载性能较差,推荐使用内核空间挂载
7.9.1 客户端通过 key 文件挂载
10.0.0.3 客户端挂载:
# 创建 /data/cephfs 文件用于挂载测试
[15:58:33 root@go ~]#mkdir /data/cephfs
# 挂载 cephfs
[16:02:52 root@go ~]#mount -t ceph 10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ /data/cephfs -o name=guigui,secretfile=/etc/ceph/guigui.key
# mount -t ceph :挂在类型为 ceph
# 10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ ,部署了 mds 服务的 mon 服务器 6789 端口
# -o name=guigui 指定 guigui 用户
# secretfile=/etc/ceph/guigui.key :guigui 用户的 secretfile 认证文件
# 验证已经挂在成功
[16:08:56 root@go ~]#df -hT | grep /data/cephfs
10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ ceph 507G 0 507G 0% /data/cephfs
10.0.0.30 客户端挂载:
[09:44:36 root@server ~]#mkdir /data/cephfs
[16:20:48 root@server ~]#mount -t ceph 10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ /data/cephfs -o name=guigui,secretfile=/etc/ceph/guigui.key
c
7.9.1.1 客户端写入文件测试
我上面已经实现了 cephfs 的挂载,现在我们可以写入文件进行测试
10.0.0.3 客户端拷贝 messages 至挂载目录:
[16:09:00 root@go ~]#cp /var/log/messages /data/cephfs/
10.0.0.30 客户端验证 messages 文件已经拷贝过来
[16:20:57 root@server ~]#ll /data/cephfs/messages
-rw------- 1 root root 558422 Sep 1 2021 /data/cephfs/messages
这样就实现了数据的实时同步,根据网络速度来判断
7.9.2:客户端通过 key 挂载
通过在命令行终端输入 key 的 secret 明文,这种方式不太安全
# 查看 key 文件
[16:24:02 root@go ~]#cat /etc/ceph/guigui.key
AQD23S1hINJHERAAaqQpjx/3vHhZDJNGjapxfg==
# 通过 secret 名文方式挂载
[16:36:44 root@go ~]#mount -t ceph 10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ /data/cephfs -o name=guigui,secret=AQD23S1hINJHERAAaqQpjx/3vHhZDJNGjapxfg==
# df 验证已经挂载
[16:37:25 root@go ~]#df -hT
Filesystem Type Size Used Avail Use% Mounted on
10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ ceph 507G 0 507G 0% /data/cephfs
7.9.3 开机挂载
将挂载配置写入到 /etc/fstab 文件中实现开机挂载
[16:38:04 root@go ~]#vim /etc/fstab
10.0.0.102:6789,10.0.0.103:6789,10.0.0.104:6789:/ /data/cephfs ceph defaults,name=guigui,secretfile=/etc/ceph/guigui.key,_netdev 0 0
# secretfile= 这里采用的是通过 key 文件实现挂载,当然我们也可以通过 secret 来实现挂载
# 重启验证
[16:44:38 root@go ~]#reboot
7.9.4 客户端模块
客户端内核加载 ceph.ko 模块挂载 cephfs 文件系统
[16:49:26 root@go ~]#lsmod | grep ceph
ceph 362898 1
libceph 306750 1 ceph
dns_resolver 13140 1 libceph
libcrc32c 12644 2 xfs,libceph
[16:49:35 root@go ~]#modinfo ceph
filename: /lib/modules/3.10.0-1127.el7.x86_64/kernel/fs/ceph/ceph.ko.xz
license: GPL
description: Ceph filesystem for Linux
author: Patience Warnick <patience@newdream.net>
author: Yehuda Sadeh <yehuda@hq.newdream.net>
author: Sage Weil <sage@newdream.net>
alias: fs-ceph
retpoline: Y
rhelversion: 7.8
srcversion: D6633248223BF99973D75CD
depends: libceph
intree: Y
vermagic: 3.10.0-1127.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: 69:0E:8A:48:2F:E7:6B:FB:F2:31:D8:60:F0:C6:62:D8:F1:17:3D:57
sig_hashalgo: sha256
7.10 ceph MDS 高可用
Ceph mds(etadata service)作为 ceph 的访问入口,需要实现高性能及数据备份,假设启动 4 个 MDS 进程,设置 2 个 Rank。这时候有 2 个 MDS 进程会分配给两个 Rank,还剩下 2 个MDS 进程分别作为另外个的备份。
https://docs.ceph.com/en/latest/cephfs/add-remove-mds/
7.10.1 当前 mds 服务器状态
在 deploy 节点上查看当前 mds 服务器状态只有一个 mds
root@ceph-deploy:~# ceph mds stat
mycephfs:1 {0=ceph-mgr1=up:active} # 为 active 状态
7.10.2 添加 MDS 服务器
将 ceph-mgr2 和 ceph-mon2 和 ceph-mon3 作为 mds 服务角色添加至 ceph 集群,最后实两主两备的 mds 高可用和高性能结构。
1.安装 ceph-mds 服务
# mds 服务器安装 ceph-mds 服务
root@ceph-mon2# apt install ceph-mds -y
root@ceph-mon3# apt install ceph-mds -y
2.在 deploy 节点上添加 mds 服务器
# 进入到 ceph 配置目录下
root@ceph-deploy:~# cd /home/ceph/ceph-cluster/
# 将 ceph-mgr2 添加至 ceph
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy mds create ceph-mgr2
# 将 ceph-mon2 添加至 ceph
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy mds create ceph-mon2
# 将 ceph-mon3 添加至 ceph
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy mds create ceph-mon3
3.验证 mds 服务器当前状态
# 可以看到两个 mds 为 standby 状态
root@ceph-deploy:/home/ceph/ceph-cluster# ceph mds stat
mycephfs:1 {0=ceph-mgr1=up:active} 3 up:standby
mds 新节点加入到 ceph 中默认就是备份节点,那么怎么将他们设置为主备关系呢?
7.10.3 设置为主 MDS
目前有 4 个 mds 服务器,但是有一主三备,可以优化一下部署架构,设置为两个主两备。
1.设置 cephfs 的 mds 为 2
root@ceph-deploy:/home/ceph/ceph-cluster# ceph fs set mycephfs max_mds 2
# mycephfs:设置 mycephfs 这个 cephfs
# max_mds 2:最大 mds 为 2
2.验证
root@ceph-deploy:/home/ceph/ceph-cluster# ceph mds stat
mycephfs:2 {0=ceph-mgr1=up:active,1=ceph-mon2=up:active} 2 up:standby
# 通过 ceph mds stat 查看现在是 2 active ,两 standby
7.10.4 MDS 高可用优化
因为我这个集群中的 mds 服务是 4 个,而且我们想将备份节点指定自己的 master 节点,这种方式只要 master 节点宕了,我们指定的那个 备份节点就会立马提权为 master 节点。从而实现了高可用,并且在 master 宕机的时候不会有太大的数据同步问题
设置每个 Rank 的备份 MDS,也就是如果此 Rank 当前的 MDS 出现问题马上切换到另个 MDS。
设置备份的方法有很多,常用选项如下。
mds_standby_replay
:值为 true 或 false,true 表示开启 replay 模式,这种模式下主 MDS 内的数量将实时与从 MDS 同步,如果主宕机,从可以快速的切换。如果为 false 只有宕机的时 候才去同步数据,这样会有一段时间的中断。
mds_standby_for_name
:设置当前 MDS 进程只用于备份于指定名称的 MDS。
mds_standby_for_rank
:设置当前 MDS 进程只用于备份于哪个 Rank,通常为 Rank 编号。另 外在存在之个 CephFS 文件系统中,还可以使用 mds_standby_for_fscid
参数来为指定不同的 文件系统。
mds_standby_for_fscid
:指定 CephFS 文件系统 ID,需要联合 mds_standby_for_rank 生效,如果设置 mds_standby_for_rank
,那么就是用于指定文件系统的指定 Rank,如果没有设置,就是指定文件系统的所有 Rank。
目前的状态是 ceph-mgr1 和 ceph-mon2 分别是 active 状态,ceph-mon3 和 ceph-mgr2 分别处于 standby 状态,现在可以将 ceph-mgr2 设置为 ceph-mgr1 的 standby,将 ceph-mon3 设置为 ceph-mon2 的 standby,以实现每个主都有一个固定备份角色的结构,则修改配置文件
操作如下:
1.查看 ceph fs 中的 mds 状态
root@ceph-deploy:~# ceph fs status
mycephfs - 2 clients
========
RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS
0 active ceph-mgr1 Reqs: 0 /s 18 16 12 5
1 active ceph-mon2 Reqs: 0 /s 10 13 11 0
POOL TYPE USED AVAIL
cephfs-metadata metadata 611k 506G
cephfs-data data 1668k 506G
STANDBY MDS
ceph-mon3
ceph-mgr2
MDS version: ceph version 16.2.5 (0883bdea7337b95e4b611c768c0279868462204a) pacific (stable)
# ceph-mgr1 和 ceph-mon2 节点的 mds 为 active 状态
# ceph-mon3 和 ceph-mgr2 节点的 mds 为 STANDBY 状态
2.修改 ceph.conf 文件,这里是让他们各个节点之间交叉进行主备管理
root@ceph-deploy:/home/ceph/ceph-cluster# vim ceph.conf
# global 全局配置不做修改
[global]
fsid = 14ce1d1a-3323-4337-963a-f96484ddd363
public_network = 10.0.0.0/24
cluster_network = 192.168.10.0/24
mon_initial_members = ceph-mon1
mon_host = 10.0.0.102
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
# 修改 mds.ceph-mgr2 节点
[mds.ceph-mgr2]
mds_standby_for_name = ceph-mgr1 # 指定 ceph-mgr2 备份 ceph-mgr1 节点
mds_standby_replay = true # 开启实时同步
# 修改 mds.ceph-mon3 节点
[mds.ceph-mon3]
mds_standby_for_name = ceph-mon2 # 指定 ceph-mon3 备份 ceph-mon2 节点
mds_standby_replay = true # 开启实时同步
7.10.5 分发配置文件并重启 mds 服务
1.deploy 节点操作分发配置文件
# 推送配置文件至 ceph-mon3 节点
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy --overwrite-conf config push ceph-mon3
# 推送配置文件至 ceph-mon2 节点
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy --overwrite-conf config push ceph-mon2
# 推送配置文件至 ceph-mgr1 节点
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy --overwrite-conf config push ceph-mgr1
# 推送配置文件至 ceph-mgr1 节点
root@ceph-deploy:/home/ceph/ceph-cluster# ceph-deploy --overwrite-conf config push ceph-mgr2
2.到每个部署了 mds 服务的节点上重启 mds 服务
root@ceph-mon2:~# systemctl restart ceph-mds@ceph-mon2.service
root@ceph-mon3:~# systemctl restart ceph-mds@ceph-mon3.service
root@ceph-mgr1:~# systemctl restart ceph-mds@ceph-mgr1.service
root@ceph-mgr2:~# systemctl restart ceph-mds@ceph-mgr2.service