Ceph 分布式存储学习笔记(三):块存储和对象存储管理
ceph分布式存储
Ceph 分布式存储 块存储管理
管理 RADOS 块设备
RADOS 块设备
- 块设备基础:服务器 / 笔记本等的主流长期存储,以固定大小块存数据,含 HDD(旋转磁盘)和 SSD(非易失性存储器);Linux 中需先格式化文件系统,再挂载到文件系统层级。
- Ceph RBD:集群通过 RADOS 块设备(RBD)提供虚拟块设备,以RBD 镜像形式存于 Ceph 存储池。
创建 RBD 镜像
存储管理员使用 rbd 命令来创建、列出、检索信息、调整大小和删除块设备镜像。
- 创建 rbd 池。使用 ceph osd pool create 命令来创建用于存储 RBD 镜像池,并使用 rbd pool init 命令进行初始化池。
[root@ceph1 ~]# ceph osd pool create images_pool
pool 'images_pool' created
[root@ceph1 ~]# rbd pool init images_pool[root@ceph1 ~]# ceph osd pool ls detail | grep images_pool
pool 4 'images_pool' replicated size 2 min_size 1 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 autoscale_mode on last_change 107 flags hashpspool,selfmanaged_snaps stripe_width 0 application rbd
- 创建专用用户。虽然 Ceph 管理员可以访问这个池,但建议使用受限制的 Cephx 用户访问 rbd 池,仅向该受限用户授予所需 RBD 池的读写权限,而非整个集群的访问权限。
[root@ceph1 ~]# ceph auth get-or-create client.rbd mon 'profile rbd' osd 'profile rbd' -o /etc/ceph/ceph.client.rbd.keyring
- 创建 RBD 镜像。
[root@ceph1 ~]# rbd create images_pool/webapp1 --size 1G# 查看池中镜像清单
[root@ceph1 ~]# rbd ls images_pool
webapp1
# 等同于ceph osd pool application enable images_pool rbd# 查看池整体情况
[root@ceph1 ~]# rbd pool stats images_pool
Total Images: 1
Total Snapshots: 0
Provisioned Size: 1 GiB
如果用户不指定池名称,此命令会使用默认的池名称,默认的池名称由 rbd_default_pool 参数指定。使用 ceph config set osd rbd_default_pool value 设置此参数。
访问 RADOS 块设备存储
访问 Ceph RBD 存储的核心方法
- 通过 KRBD 模块访问:客户端借助 Linux 内核的
krbd
模块,直接将 Ceph 集群中的 RBD 镜像映射为本地 Linux 块设备,映射后可像使用物理块设备(如本地 SSD/HDD)一样操作。 - 通过 librbd 库访问:作为 Ceph 提供的核心开发库,
librbd
主要为上层应用提供 RBD 存储能力,典型场景包括:- 为 KVM 虚拟机提供块存储,使虚拟机可将 RBD 镜像作为磁盘使用;
- 为 OpenStack 云实例提供存储支持,OpenStack 会将 RBD 镜像连接并映射到后端 Linux 服务器,既可作为实例的数据盘,也可充当引导设备(启动磁盘)。
无论哪种访问方式,Ceph 集群都会将虚拟块设备的实际存储数据分散到集群节点中,并通过 IP 网络实现高性能访问,确保存储可靠性与读写效率。
使用内核RBD(KRBD)访问 Ceph 块存储
映射 RBD 镜像
示例:将 images_pool 池中的 webapp1 镜像映射为client上 /dev/rbd0 设备。
# client
[root@client ~]# dnf install -y ceph-common
[root@ceph1 ~]# scp /etc/ceph/ceph.conf /etc/ceph/ceph.client.rbd.keyring root@client:/etc/ceph
root@client's password:
ceph.conf 100% 283 241.4KB/s 00:00
ceph.client.rbd.keyring 100% 61 85.0KB/s 00:00# ceph1
[root@ceph1 ~]# scp /etc/ceph/ceph.conf /etc/ceph/ceph.client.rbd.keyring root@client:/etc/ceph
root@client's password:
ceph.conf 100% 283 241.4KB/s 00:00
ceph.client.rbd.keyring 100% 61 85.0KB/s 00:00# client
[root@client ~]# rbd --id rbd ls images_pool
webapp1# 简化命令参数,定义CEPH_ARGS环境变量,确保ceph相关命令使用该环境变量提供的默认值。
[root@client ~]# export CEPH_ARGS='--id=rbd'
[root@client ~]# rbd ls images_pool
webapp1# 使用 krbd 内核模块来映射镜像
# 或使用rbd map images_pool/webapp1映射镜像
[root@client ~]# rbd device map images_pool/webapp1
/dev/rbd0[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 200G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 199G 0 part├─cs-root 253:0 0 70G 0 lvm /├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]└─cs-home 253:2 0 125.1G 0 lvm /home
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sdd 8:48 0 20G 0 disk
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 1G 0 disk
Ceph 客户端系统可以像其他块设备一样使用映射的块设备,例如使用文件系统进行格式化、挂载和卸载。
# 列出计算机中映射的 RBD 镜像
[root@client ~]# rbd showmapped
id pool namespace image snap device
0 images_pool webapp1 - /dev/rbd0
或
[root@client ~]# rbd device list
id pool namespace image snap device
0 images_pool webapp1 - /dev/rbd0# 格式化和挂载
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 1G 0 disk
[root@client ~]# mkfs.xfs /dev/rbd0
meta-data=/dev/rbd0 isize=512 agcount=8, agsize=32768 blks= sectsz=512 attr=2, projid32bit=1= crc=1 finobt=1, sparse=1, rmapbt=0= reflink=1 bigtime=0 inobtcount=0
data = bsize=4096 blocks=262144, imaxpct=25= sunit=16 swidth=16 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2= sectsz=512 sunit=16 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Discarding blocks...Done.[root@client ~]# mkdir -p /webapp/webapp1
[root@client ~]# mount /dev/rbd0 /webapp/webapp1/
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 1G 0 disk /webapp/webapp1[root@client ~]# echo Hello World > /webapp/webapp1/index.html
[root@client ~]# cat /webapp/webapp1/index.html
Hello World[root@client ~]# df /webapp/webapp1/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/rbd0 1038336 40504 997832 4% /webapp/webapp1[root@client ~]# rbd status images_pool/webapp1
Watchers:watcher=192.168.108.10:0/1053665932 client.74223 cookie=18446462598732840961
取消映射 RBD 镜像
# 先卸载改设备
[root@client ~]# umount /webapp/webapp1# 取消映射
[root@client ~]# rbd unmap /dev/rbd0
或
[root@client ~]# rbd device unmap /dev/rbd0[root@client ~]# rbd device ls
[root@client ~]#z# 两个客户端可同时将同一个 RBD 镜像映射为块设备。但对于包含普通单挂载文件系统的块设备,建议每次仅连接到一个客户端;若将这类文件系统的 RADOS 块设备同时挂载到多个客户端,可能导致文件系统损坏和数据丢失。
持久映射 RBD 镜像
**rbdmap 服务可在系统启动自动映射 RBD 镜像到系统。**此服务在 /etc/ceph/rbdmap 文件中查找已映射的镜像及其凭据。当 系统识别到 RBD 镜像时,读取 /etc/fstab 文件中记录,并挂载镜像。
对 rbdmap 进行配置,以持久映射已包含文件系统的 RBD 镜像:
- 在 /etc/ceph/rbdmap 文件中创建单行条目,需包含:RBD 池名称、镜像名称、拥有镜像读写权限的 Cephx 用户及对应的密钥环文件。需确保客户端系统上已存在该 Cephx 用户的密钥环文件,格式示例:
{池名}/{镜像名} id={用户名},keyring=/etc/ceph/ceph.client.{用户名}.keyring
[root@client ~]# vim /etc/ceph/rbdmap
[root@client ~]# cat /etc/ceph/rbdmap
# RbdDevice Parameters
#poolname/imagename id=client,keyring=/etc/ceph/ceph.client.keyring
images_pool/webapp1 id=rbd,keyring=/etc/ceph/ceph.client.rbd.keyring
- 在客户端
/etc/fstab
中为 RBD 块设备创建条目时,需明确块设备路径、挂载点、文件系统类型,并通过_netdev
选项确保网络就绪后再挂载,同时依赖rbdmap
服务完成镜像映射,格式示例如下:
/dev/rbd/pool_name/image_name /mnt/rbd_mount_point xfs defaults,_netdev 0 2
[root@client ~]# vim /etc/fstab
[root@client ~]# cat /etc/fstab......
/dev/rbd/images_pool/webapp1 /webapp/webapp1 xfs _netdev 0 0
-
确认块设备映射正常工作。使用 rbdmap map 和 rbdmap unmap 命令来挂载和卸载镜像。
-
启用 rbdmap systemd 服务。
[root@client ~]# systemctl enable rbdmap.service
Created symlink /etc/systemd/system/multi-user.target.wants/rbdmap.service → /usr/lib/systemd/system/rbdmap.service.
- 重启系统验证。
[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sdd 8:48 0 200G 0 disk
├─sdd1 8:49 0 1G 0 part /boot
└─sdd2 8:50 0 199G 0 part├─cs-root 253:0 0 70G 0 lvm /├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 1G 0 disk /webapp/webapp1
RBD 镜像格式
与每个 RBD 镜像关联的三个参数:
- image_format:RBD 镜像格式版本,默认值为 2(最新版本)。版本 1 已弃用,且不支持克隆和镜像等功能。
- stripe_unit:一个对象中存储的连续字节数,默认值为 object_size。
- stripe_count:一个条带跨越的 RBD 镜像对象数量,默认值为 1。
对于 RBD 格式 2 镜像,用户可以更改以上各个参数的值。设置必须与下列等式一致:
stripe_unit * stripe_count = object_size
例如: stripe_unit = 1048576, stripe_count = 8 for default 8 MiB objects
[root@client ~]# rbd create --stripe-unit=1M --stripe-count=8 --size 1G images_pool/webapp2 --id rbd
[root@client ~]# rbd info images_pool/webapp2 --id rbd
rbd image 'webapp2':size 1 GiB in 256 objectsorder 22 (4 MiB objects)snapshot_count: 0id: 121f94f9ad1e0block_name_prefix: rbd_data.121f94f9ad1e0format: 2features: layering, striping, exclusive-lock, object-map, fast-diff, deep-flattenop_features:flags:create_timestamp: Tue Sep 30 11:36:13 2025access_timestamp: Tue Sep 30 11:36:13 2025modify_timestamp: Tue Sep 30 11:36:13 2025stripe unit: 1 MiBstripe count: 8
使用 rbd 命令管理镜像
status
用于查看哪些客户端在使用该镜像。
[root@client ~]# rbd status images_pool/webapp1 --id rbd
Watchers:watcher=192.168.108.10:0/691002435 client.74235 cookie=18446462598732840961[root@client ~]# rbd status images_pool/webapp2 --id rbd Watchers: none
du
用于查看镜像大小使用情况。
[root@client ~]# rbd du images_pool/webapp1 --id rbd
NAME PROVISIONED USED
webapp1 1 GiB 36 MiB
resize
用于扩展和缩减镜像。
# 扩展未在使用的镜像
[root@client ~]# rbd resize images_pool/webapp2 --size 2G --id rbd
Resizing image: 100% complete...done.
[root@client ~]# rbd du images_pool/webapp2
NAME PROVISIONED USED
webapp2 2 GiB 0 B# 扩展正在使用的镜像
[root@client ~]# rbd resize images_pool/webapp1 --size 2G --id rbd
Resizing image: 100% complete...done.
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 2G 0 disk /webapp/webapp1
[root@client ~]# df -h /dev/rbd0
Filesystem Size Used Avail Use% Mounted on
/dev/rbd0 1014M 40M 975M 4% /webapp/webapp1
[root@client ~]# xfs_growfs /webapp/webapp1/
meta-data=/dev/rbd0 isize=512 agcount=8, agsize=32768 blks= sectsz=512 attr=2, projid32bit=1= crc=1 finobt=1, sparse=1, rmapbt=0= reflink=1 bigtime=0 inobtcount=0
data = bsize=4096 blocks=262144, imaxpct=25= sunit=16 swidth=16 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2= sectsz=512 sunit=16 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
data blocks changed from 262144 to 524288
[root@client ~]# df -h /webapp/webapp1/
Filesystem Size Used Avail Use% Mounted on
/dev/rbd0 2.0G 48M 2.0G 3% /webapp/webapp1# 缩减镜像
[root@client ~]# rbd resize images_pool/webapp2 --size 1G --id rbd
rbd: shrinking an image is only allowed with the --allow-shrink flag
[root@client ~]# rbd resize images_pool/webapp2 --size 1G --allow-shrink --id rbd
Resizing image: 100% complete...done.
[root@client ~]# rbd du images_pool/webapp2 --id rbd
NAME PROVISIONED USED
webapp2 1 GiB 0 B# 缩减正在使用的镜像(xfs文件系统不支持缩减)
rename 和 mv
用于重命名镜像,该操作不支持跨池。
# 创建新池
[root@ceph1 ~]# ceph osd pool create images_pool_2 32 32
pool 'images_pool_2' already exists
[root@ceph1 ~]# rbd pool init images_pool_2# 重命名
[root@ceph1 ~]# rbd rename images_pool/webapp2 images_pool/webapp02
[root@ceph1 ~]# rbd ls images_pool
webapp02
webapp1
或
[root@ceph1 ~]# rbd mv images_pool/webapp02 images_pool/webapp2
[root@ceph1 ~]# rbd ls images_pool
webapp1
webapp2# 跨池重命名
# 发现不行
[root@ceph1 ~]# rbd rename images_pool/webapp2 images_pool_2/webapp02
rbd: mv/rename across pools not supported
source pool: images_pool dest pool: images_pool_2
cp
用于复制镜像。
[root@ceph1 ~]# rbd cp images_pool/webapp2 images_pool_2/webapp2
Image copy: 100% complete...done.
[root@ceph1 ~]# rbd ls -p images_pool
webapp1
webapp2
[root@ceph1 ~]# rbd ls -p images_pool_2
webapp2
trash
使用垃圾箱管理镜像。
# 将镜像放入垃圾箱
[root@ceph1 ~]# rbd ls images_pool
webapp1
webapp2
[root@ceph1 ~]# rbd trash mv images_pool/webapp2
[root@ceph1 ~]#
[root@ceph1 ~]# rbd ls images_pool
webapp1
[root@ceph1 ~]# rbd trash ls images_pool
121f94f9ad1e0 webapp2
[root@ceph1 ~]## 恢复垃圾箱中镜像,必须使用id
[root@ceph1 ~]# rbd trash restore -p images_pool 121f94f9ad1e0
[root@ceph1 ~]# rbd ls images_pool
webapp1
webapp2
[root@ceph1 ~]# rbd trash ls images_pool
[root@ceph1 ~]## 删除垃圾箱中镜像
[root@ceph1 ~]# rbd trash mv images_pool/webapp2
[root@ceph1 ~]# rbd trash ls images_pool
121f94f9ad1e0 webapp2
[root@ceph1 ~]# rbd trash rm -p images_pool 121f94f9ad1e0
Removing image: 100% complete...done.
[root@ceph1 ~]# rbd trash ls images_pool
[root@ceph1 ~]# rbd ls images_pool
webapp1
rm
用于删除镜像。
[root@ceph1 ~]# rbd rm images_pool_2/webapp2
Removing image: 100% complete...done.
[root@ceph1 ~]#
[root@ceph1 ~]# rbd ls images_pool_2
[root@ceph1 ~]#
管理 RADOS 块设备快照
RBD 镜像功能
格式 2 的 RBD 镜像支持以下可选功能:
- layering:镜像分层功能,支持快照和克隆。
- striping:由 librbd 支持的分条 v2 功能,可提高性能。
- exclusive-lock:独占锁定功能。
- object-map:对象映射功能(依赖 exclusive-lock)。
- fast-diff:快速 diff 命令功能(依赖 object-map 和 exclusive-lock)。
- deep-flatten:扁平化 RBD 镜像的所有快照。
- journaling:日志功能(依赖 exclusive-lock)。
- data-pool:EC 数据池功能。
集群中 RBD 镜像默认启用的功能为:layering, exclusive-lock, object-map, fast-diff, deep-flatten
,可通过 ceph config get client rbd_default_features
命令查看。
设置方式:
- 用
ceph config set client rbd_default_features value
命令配置镜像默认功能; - 在
/etc/ceph/ceph.conf
的[client]
段中,通过rbd_default_features
参数定义; - 命令行创建镜像时,可添加
--image-feature feature-name
指定具体功能。
禁用 object-map 功能
[root@ceph1 ~]# rbd feature disable images_pool/webapp1 object-map
启用 object-map 功能
[root@ceph1 ~]# rbd feature enable images_pool/webapp1 object-map
有些功能是永久性的,不能直接禁用和启用,例如 layering。
[root@ceph1 ~]# rbd feature disable images_pool/webapp1 layering
rbd: failed to update image features: (22) Invalid argument
2025-09-30T13:56:40.648+0800 7fb9079503c0 -1 librbd::Operations: cannot update immutable features
RBD 快照
RBD 快照采用 COW(写时复制)技术,能最大程度减少维护快照的存储空间。当写入 I/O 请求应用到 RBD 快照镜像前,集群会将原始数据复制到该 I/O 操作所影响对象的 PG 中的另一区域。快照创建时不占用存储空间,其大小会随包含对象的变化而增长。此外,RBD 镜像支持增量快照。
快照的 COW 技术在对象级别运行,不受对 RBD 镜像发出的写入 I/O 请求大小限制。即使用户仅向存在快照的 RBD 镜像写入一个字节,Ceph 也会将整个受影响的对象从 RBD 镜像复制到快照区域。
在拍摄快照前,必须要完成以下任一操作:
- 卸载文件系统;
- 使用
fsfreeze
命令冻结文件系统(冻结后仅允许读操作,禁止写操作)。
创建 Ceph 块设备的快照# 重新创建一个镜像
[root@client ~]# rbd create images_pool/webapp --size 2G
[root@client ~]# rbd map images_pool/webapp
/dev/rbd1
[root@client ~]# mkfs.xfs /dev/rbd/images_pool/webapp
meta-data=/dev/rbd/images_pool/webapp isize=512 agcount=8, agsize=65536 blks= sectsz=512 attr=2, projid32bit=1= crc=1 finobt=1, sparse=1, rmapbt=0= reflink=1 bigtime=0 inobtcount=0
data = bsize=4096 blocks=524288, imaxpct=25= sunit=16 swidth=16 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2= sectsz=512 sunit=16 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Discarding blocks...Done.
[root@client ~]# mkdir /webapp/webapp
[root@client ~]# mount /dev/rbd/images_pool/webapp /webapp/webapp
[root@client ~]# echo Hello World > /webapp/webapp/index.html
[root@client ~]# cat /webapp/webapp/index.html
Hello World# 卸载文件系统
[root@client ~]# umount /webapp/webapp# 拍摄快照
[root@client ~]# rbd snap create images_pool/webapp@snap1
Creating snap: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP4 snap1 2 GiB Tue Sep 30 14:06:46 2025# 挂载文件系统,并写入新数据
[root@client ~]# mount /dev/rbd/images_pool/webapp /webapp/webapp
[root@client ~]# echo Hello laogao > /webapp/webapp/index.html
[root@client ~]# cat /webapp/webapp/index.html
Hello laogao
[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sdd 8:48 0 200G 0 disk
├─sdd1 8:49 0 1G 0 part /boot
└─sdd2 8:50 0 199G 0 part├─cs-root 253:0 0 70G 0 lvm /├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 2G 0 disk /webapp/webapp1
rbd1 252:16 0 2G 0 disk /webapp/webapp列出块设备快照
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP4 snap1 2 GiB Tue Sep 30 14:06:46 2025# RBD 快照是创建于特定时间的 RBD 镜像的只读副本。
镜像快照和镜像具有相同的文件系统,同一客户端不允许挂载具有相同UUID的文件系统。# 挂载快照前,需要卸载原始镜像
[root@client ~]# umount /dev/rbd/images_pool/webapp
[root@client ~]# mkdir /webapp/webapp-snap1
[root@client ~]# rbd map images_pool/webapp@snap1
/dev/rbd2
[root@client ~]# mount /dev/rbd/images_pool/webapp@snap1 /webapp/webapp-snap1
mount: /webapp/webapp-snap1: WARNING: device write-protected, mounted read-only.
[root@client ~]# cat /webapp/webapp-snap1/index.html
Hello World回滚块设备快照,并用快照中的数据覆盖镜像的当前版本# 回滚快照失败
[root@client ~]# rbd snap rollback images_pool/webapp@snap1
Rolling back to snapshot: 0% complete...failed.
rbd: rollback failed: (30) Read-only file system删除 Ceph 块设备的快照
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP4 snap1 2 GiB Tue Sep 30 14:06:46 2025
[root@client ~]# umount /dev/rbd/images_pool/webapp@snap1
[root@client ~]# rbd unmap images_pool/webapp@snap1
[root@client ~]# rbd snap rm images_pool/webapp@snap1
Removing snap: 100% complete...done.[root@client ~]# rbd snap ls images_pool/webapp删除镜像所有快照
[root@client ~]# rbd snap create images_pool/webapp@snap1
Creating snap: 100% complete...done.
[root@client ~]# rbd snap create images_pool/webapp@snap2
Creating snap: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP6 snap1 2 GiB Tue Sep 30 14:18:11 20257 snap2 2 GiB Tue Sep 30 14:18:12 2025
[root@client ~]# rbd snap purge images_pool/webapp
Removing all snapshots: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
RBD 克隆
RBD 克隆是 RBD 镜像的可读写副本,它使用受保护的 RBD 快照克隆。RBD 克隆也可以被扁平化,转换为独立于来源的 RBD 镜像。
克隆过程有三个步骤:
- 创建快照
[root@client ~]# rbd snap create images_pool/webapp@snap1
Creating snap: 100% complete...done.[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP10 snap1 2 GiB Tue Sep 30 14:40:07 2025
- 保护快照以免被删除
[root@client ~]# rbd snap protect images_pool/webapp@snap1
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP10 snap1 2 GiB yes Tue Sep 30 14:40:07 2025
- 使用受保护的快照创建克隆
[root@client ~]# rbd clone images_pool/webapp@snap1 images_pool/webapp-clone-1
[root@client ~]# rbd map images_pool/webapp-clone-1
/dev/rbd2
[root@client ~]# mkdir /webapp/webapp-clone-1
[root@client ~]# umount /webapp/webapp
umount: /webapp/webapp: not mounted.
# 挂载clone前确保镜像和快照不要挂载[root@client ~]# mount /dev/rbd/images_pool/webapp-clone-1 /webapp/webapp-clone-1
[root@client ~]# df /webapp/webapp-clone-1/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/rbd2 2086912 47864 2039048 3% /webapp/webapp-clone-1
新创建的克隆可以像常规 RBD 镜像一样运作,克隆支持 COW 和 COR技术,默认只支持 COW。COW 会将父快照数据复制到克隆中,然后将写入 I/O 请求应用到克隆。
[root@client ~]# ceph config get client rbd_clone_copy_on_read
false
RBD 克隆未启用 COR 功能时,父 RBD 快照和克隆的相同数据会直接从父快照读取。若父快照的 OSD 对客户端而言延迟较高,会增加读取代价。
若启用 COR 功能,当克隆中尚未存在对应数据时,Ceph 会在处理读取 I/O 请求前,先将数据从父快照复制到克隆,且原始数据不会被覆盖。可通过命令激活 COR 功能:为客户端设置用 ceph config set client rbd_clone_copy_on_read true
,全局设置用 ceph config set global rbd_clone_copy_on_read true
。
# ceph config set client rbd_clone_copy_on_read true
如果不对 RBD 克隆启用 COR,则克隆无法满足的每个读取操作都会对克隆的父级发出 I/O 请求。
克隆 COW 和 COR 步骤在对象级别上运行,不受 I/O 请求大小的限制。要读取或写入 RBD 克隆的单个字节,Ceph 会将整个对象从父镜像或快照复制到克隆。
查看基于特定快照的克隆列表:
[root@client ~]# rbd clone images_pool/webapp@snap1 images_pool/webapp-clone-2
[root@client ~]# rbd children images_pool/webapp@snap1
images_pool/webapp-clone-1
images_pool/webapp-clone-2
扁平化克隆,Ceph 会将所有缺失的数据从父级复制到克隆,然后移除对父级的引用。克隆会变成独立的 RBD 镜像,不再是受保护快照的子级。
[root@client ~]# rbd flatten images_pool/webapp-clone-1
Image flatten: 100% complete...done.
[root@client ~]# rbd children images_pool/webapp@snap1
images_pool/webapp-clone-2
挂载克隆镜像
通过镜像快照克隆的镜像与原镜像具有相同的文件系统 UUID,而同一客户端不允许挂载 UUID 相同的文件系统,解决方法是修改克隆镜像的文件系统 UUID。
具体操作需先确保克隆镜像已映射为块设备且未挂载,然后使用对应文件系统的工具修改 UUID:
- 对于 ext 系列文件系统,使用
tune2fs -U 新UUID /dev/rbd/池名/克隆镜像名
- 对于 XFS 文件系统,使用
xfs_admin -U 新UUID /dev/rbd/池名/克隆镜像名
假设客户端将克隆出来的镜像映射为/dev/rbd3设备。操作如下:
[root@client ~]# rbd map images_pool/webapp-clone-2
/dev/rbd3
[root@client ~]# blkid | grep rbd
/dev/rbd0: UUID="fa3c47d7-4947-44ce-94cf-8cc065d032ef" BLOCK_SIZE="512" TYPE="xfs"
/dev/rbd1: UUID="72a27a29-3f0d-4d41-a8ec-3e4142f8ad68" BLOCK_SIZE="512" TYPE="xfs"
/dev/rbd2: UUID="72a27a29-3f0d-4d41-a8ec-3e4142f8ad68" BLOCK_SIZE="512" TYPE="xfs"
/dev/rbd3: UUID="72a27a29-3f0d-4d41-a8ec-3e4142f8ad68" BLOCK_SIZE="512" TYPE="xfs"# 生成新的 UUID
[root@client ~]# uuidgen
a4b7fc32-f29d-482f-bd5b-595d6866d3b3# 修改 ext4 文件系统 UUID
[root@client ~]# tune2fs -U a4b7fc32-f29d-482f-bd5b-595d6866d3b3 /dev/rbd3
tune2fs 1.45.6 (20-Mar-2020)
tune2fs: Bad magic number in super-block while trying to open /dev/rbd3
/dev/rbd3 contains a xfs file system# 修改 xfs 文件系统 UUID
[root@client ~]# xfs_admin -U a4b7fc32-f29d-482f-bd5b-595d6866d3b3 /dev/rbd3
Clearing log and setting UUID
writing all SBs
new UUID = a4b7fc32-f29d-482f-bd5b-595d6866d3b3# 挂载测试
[root@client ~]# mkdir /webapp/webapp-clone-2
[root@client ~]# mount /dev/rbd3 /webapp/webapp-clone-2/[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sdd 8:48 0 200G 0 disk
├─sdd1 8:49 0 1G 0 part /boot
└─sdd2 8:50 0 199G 0 part├─cs-root 253:0 0 70G 0 lvm /├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 2G 0 disk /webapp/webapp1
rbd1 252:16 0 2G 0 disk
rbd2 252:32 0 2G 0 disk /webapp/webapp-clone-1
rbd3 252:48 0 2G 0 disk /webapp/webapp-clone-2
导入和导出 RBD 镜像
导入和导出 RBD 镜像
利用 RBD 导出与导入机制,用户可在同一 Ceph 集群内,或跨独立集群维护 RBD 镜像的操作副本 —— 这些副本保留完整功能与可访问性,能适配多种实际用例,包括:
- 基于实际数据卷测试软件新版本,避免直接影响生产环境;
- 用真实数据卷运行质量保障(QA)流程,确保测试结果贴合实际场景;
- 支撑业务连续性方案,如跨集群备份以应对单点故障;
- 将备份进程与生产块设备解耦,减少备份操作对生产存储性能的占用。
导出 RBD 镜像
Ceph 存储的 rbd export
命令用于将 RBD 镜像或其快照导出到文件,语法如下:
rbd export [--export-format {1|2}] (image-spec | snap-spec) [dest-path]
--export-format
选项可指定导出数据的格式(1 或 2),支持将较早的格式 1 镜像转换为较新的格式 2 镜像。其中,image-spec
指 RBD 镜像,snap-spec
指 RBD 镜像快照,dest-path
为导出目标文件路径。
示例:
[root@ceph1 ~]# rbd export images_pool/webapp webapp.img
Exporting image: 100% complete...done.
导入 RBD 镜像
Ceph 存储的 rbd import
命令用于从文件导入 RBD 镜像,会新建镜像并从指定源路径导入数据,语法如下:
rbd import [--export-format {1|2}] [--image-format format-id] [--object-size size-in-B/K/M] [--stripe-unit size-in-B/K/M --stripe-count num] [--image-feature feature-name]... [--image-shared] src-path [image-spec]
参数说明:
--export-format
:指定待导入数据的格式(1 或 2),需与对应rbd export
命令使用的该参数值保持一致;- 导入格式 2 的数据时,可通过
--stripe-unit
、--stripe-count
、--object-size
和--image-feature
选项配置新 RBD 格式 2 镜像的属性。
**示例1:**同一集群导入
[root@ceph1 ~]# rbd import webapp.img images_pool/webapp-backup
Importing image: 100% complete...done.
[root@ceph1 ~]# rbd ls images_pool
webapp
webapp-backup
webapp-clone-1
webapp-clone-2
webapp1[root@ceph1 ~]# rbd info images_pool/webapp-backup
rbd image 'webapp-backup':size 2 GiB in 512 objectsorder 22 (4 MiB objects)snapshot_count: 0id: 1246296ac6eedblock_name_prefix: rbd_data.1246296ac6eedformat: 2features: layering, exclusive-lock, object-map, fast-diff, deep-flattenop_features:flags:create_timestamp: Tue Sep 30 15:08:36 2025access_timestamp: Tue Sep 30 15:08:36 2025modify_timestamp: Tue Sep 30 15:08:36 2025
**示例2:**不同集群导入
[root@ceph1 ~]# scp webapp.img root@ceph4:[root@ceph4 ~]# ceph osd pool create images_pool 32
[root@ceph4 ~]# rbd pool init images_pool
[root@ceph4 ~]# rbd ls images_pool #查看
[root@ceph4 ~]# rbd import webapp.img images_pool/webapp-backup
Importing image: 100% complete...done.
[root@ceph4 ~]# rbd ls images_pool #导入后再查看
webapp-backup
管道导出和导入进程
在 rbd export
中指定短划线(-
)作为目标文件,会将输出导向标准输出(stdout);同理,rbd import
中使用短划线作为源,可从标准输入(stdin)读取数据。
利用这一特性,可将两个命令通过管道直接衔接,实现 RBD 镜像的跨集群或本地快速迁移,例如:
rbd export --export-format 2 pool1/image1 - | rbd import --image-format 2 - pool2/image2
此命令将 pool1
中的 image1
导出到 stdout,再通过管道直接导入为 pool2
中的 image2
,无需中间文件,高效且节省存储空间。
# 同一集群导出和导入
[root@ceph1 ~]# rbd export images_pool/webapp - | rbd import - images_pool/webapp-backup2
Exporting image: 100% complete...done.
Importing image: 100% complete...done.# 不同集群导出和导入
[root@ceph1 ~]# rbd export images_pool/webapp - | ssh root@ceph4 rbd import - images_pool/webapp-backup2
root@ceph4's password: plete...
Exporting image: 100% complete...done.
Importing image: 100% complete...done.
Ceph 分布式存储 对象存储管理
对象存储介绍
对象存储简介
对象存储是基于对象的存储服务,具备海量、安全、高可靠、低成本的数据存储能力,其核心特性与结构如下:
- 数据存储形态与访问方式:对象存储将数据以离散的 “对象” 为单位存储,每个对象拥有唯一的对象 ID(或对象密钥)。用户无需知晓对象的物理存储位置,仅通过对象 ID 即可完成数据的存储与检索操作。
- 对象的组成结构:每个对象是文件数据与相关属性信息的集合,包含三部分核心内容:
- Key(键值):即对象名称,需为 UTF-8 编码的字符序列,长度大于 0 且不超过 1024 字符;同一存储容器(桶)内的对象 Key 必须唯一,作为对象的核心标识。
- Metadata(元数据):对象的描述信息,以键值对(Key-Value)形式存储,分为系统元数据与用户元数据。系统元数据由对象存储自动生成,用于数据处理(如 Date、Content-length、Last-modify、ETag 等);用户元数据可由用户自定义补充。
- Data(数据):即对象对应的文件原始数据内容。
- 存储命名空间:桶(Bucket):对象存储通过 “桶” 实现扁平的命名空间管理,桶是存储对象的容器,所有对象直接隶属于桶,不存在文件系统的多层级树形目录结构。每个桶拥有独立属性,包括存储类别(如标准存储、低频访问存储)、访问权限(如私有、公开读)、所属区域等,用户可根据业务场景(如数据访问频率、安全性需求)创建不同配置的桶,并扩展高级属性(如数据生命周期、防盗链)以满足需求。
对象存储特征
- 接入灵活:支持多种形态客户端,如通过用对象存储接口、 RESTful接口、 SDK等。
- 访问协议简单:使用http或https协议访问。
- 访问网络不受限:通过互联网或局域网都进行访问。
- 结构扁平化:对象直接存放在桶中,无目录结构。
RADOS 网关介绍
RADOS 网关简介
RADOS Gateway(对象网关,简称 RGW) 是 Ceph 集群的对象存储接入层,核心功能与特性如下:
-
API 兼容能力:为客户端提供标准对象存储 API 接口,支持两种主流协议:
-
Amazon S3:将扁平命名空间称为 “存储桶(Bucket)”;
-
OpenStack Swift
:将命名空间称为 “容器(Container)”。
这使得现有基于 S3 或 Swift 开发的应用可无缝对接 Ceph 集群。
-
-
技术架构:
- 核心守护进程为
radosgw
,基于librados
库构建,通过调用底层库与 Ceph 集群交互; - 前端集成 Beast HTTP、WebSocket 及网络协议库,负责接收和处理 API 请求,实现 HTTP 层与存储层的衔接。
- 核心守护进程为
-
角色定位:
radosgw
本身作为 Ceph 存储的客户端,承担对象存储的访问代理角色 —— 客户端通过 RGW 提供的 API 操作对象,而 RGW 则负责将这些请求转换为对 Ceph 集群的具体操作(如对象的增删改查),屏蔽了底层存储细节。
RADOS 网关的用户访问控制与默认池说明:
-
用户访问机制:
- RADOS 网关用户仅能通过网关访问存储资源,无法像 cephx 用户那样样直接访问集群。
- 客户端提交 S3 或 Swift API 请求时,需使用网关用户账户验证身份;验证通过后,网关会以 cephx 凭据向存储集群二次验证,完成对象操作处理。
- 支持集成 LDAP 外部身份验证服务管理网关用户,提升身份管理灵活性。
-
默认区域的池结构:
RADOS 网关会为默认区域自动创建多个专用池,各有明确用途:
.rgw.root
:存储基础信息记录.default.rgw.control
:控制指令相关存储.default.rgw.meta
:存储用户密钥(user_keys)及关键元数据.default.rgw.log
:记录所有桶 / 容器及对象的操作日志(创建、读取、删除等).default.rgw.buckets.index
:存储桶的索引信息.default.rgw.buckets.data
:存储桶的实际数据.default.rgw.buckets.non-ec
:用于对象元数据的上传存储
-
自定义池命名建议:
若手动创建这些池,建议以区域名称为前缀(如区域为
us-east-1
,则池名称可为.us-east-1.rgw.buckets.data
),便于多区域部署时的资源管理与区分。
RADOS 网关架构
Ceph RADOS 网关支持多站点部署:在多个 Ceph 存储集群之间自动复制对象数据。常见的用例是在地理上分隔的集群之间进行主动/主动复制,以便于灾难恢复。
Ceph RGW 多区域架构核心概念解析
Ceph RADOS 网关(RGW)通过 区域、区域组、域 的层级结构实现跨地域部署与数据高可用,配合 期间、时期 机制管理配置变更,具体定义与规则如下:
核心层级结构
- 区域(Zone)
- 定义:区域是 RGW 部署的基础单元,每个区域关联 1 个或多个 RGW 实例,且这些实例直接对接后端 Ceph 存储集群(通过 librados 交互)。
- 作用:作为数据存储与 API 服务的 “节点”,单个区域内的 RGW 实例共享同一套存储资源,提供统一的对象存储访问入口。
- 区域组(Zone Group)
- 定义:由 1 个或多个区域组成的集合,核心特性是 数据自动同步—— 存储在区域组中某一区域的数据,会被复制到该组内所有其他区域,确保区域间数据一致性。
- 主从角色:
- 主区域(Primary Zone):区域组内唯一的 “写入主节点”,负责处理所有元数据更新(如创建桶、修改对象属性)和数据写入请求,再同步到其他区域。
- 次要区域(Secondary Zone):区域组内的 “只读 / 同步节点”,仅接收来自主区域的同步数据,对外提供读服务(部分场景支持读写分离配置)。
- 域(Realm)
- 定义:RGW 架构的最高层级,代表 全局唯一的对象与存储桶命名空间—— 即同一域内的所有区域组、区域共享一套对象 / 桶名称规则(避免命名冲突)。
- 组成与主从:
- 包含 1 个或多个区域组,各区域组可对应不同地域(如 “华北区域组”“华南区域组”)。
- 主区域组(Primary Zone Group):域内唯一的 “配置主节点”,所有 RGW 实例的配置(如用户信息、权限规则)均从该组的 主区域 拉取。
- 次要区域组(Secondary Zone Group):仅接收来自主区域组的配置同步,自身不主动处理配置更新。
- 关键规则:所有需要修改元数据的操作(如创建 RGW 用户、删除桶)必须在主区域组的主区域执行,否则会因配置无法同步导致全局不一致。
配置变更管理:期间(Period)与时期(Epoch)
域的配置变更(如新增区域、修改同步规则)通过 期间 和 时期 进行版本化跟踪,确保所有 RGW 实例能获取最新且一致的配置。
- 期间(Period)
- 定义:用于记录 特定时间点域、区域组、区域的完整配置状态,可理解为 “配置快照”。
- 属性:
- 每个期间有唯一 ID,包含当前域的所有配置信息(区域组结构、主从关系、同步策略等)。
- 记录 “前一个期间的 ID”,形成配置变更的 “时间线”,支持回溯历史配置。
- 时期(Epoch)
- 定义:用于标记 同一期间内的配置版本号,是期间内的 “小版本迭代”。
- 作用:当配置变更较小时(无需新建期间),通过递增时期号区分不同版本,避免频繁创建期间导致的资源开销。
- 配置更新规则
变更类型 | 期间(Period)变化 | 时期(Epoch)变化 |
---|---|---|
主区域的核心配置更新(如新增区域组、修改主从关系) | 新建期间(成为当前期间) | 新期间的时期从 1 开始 |
非核心配置更新(如修改 RGW 端口、调整日志级别) | 不变化(沿用当前期间) | 递增 1(如从 5→6) |
总结
RGW 多区域架构通过 “域→区域组→区域” 的层级实现全局资源管理与数据同步,通过 “期间→时期” 实现配置版本化控制,最终达成:
- 跨地域数据高可用(区域组内同步);
- 全局配置一致性(从主区域拉取配置);
- 配置变更可追溯(期间时间线)。
RADOS 网关用例
Ceph 对象存储凭借 高扩展性、高可靠性、API 兼容性 及灵活的部署特性,可覆盖从海量数据存储到混合云协同的多元业务需求,以下为 10 类核心应用场景及适配逻辑解析:
1. 大规模非结构化数据存储
-
核心场景:存储 PB/EB 级别的非结构化数据,如视频素材、高清图片库、系统日志、用户生成内容(UGC)等。
-
适配原因:
Ceph 采用分布式架构,支持通过横向扩展 OSD 节点实现存储容量与性能的线性增长,无需担心单点瓶颈;同时通过 CRUSH 算法实现数据的均衡分布,可稳定承载海量数据的长期存储。
2. 公有云 / 私有云对象服务构建
-
核心场景:为企业私有云、行业云或公有云服务商提供标准化对象存储服务(如类似 AWS S3 的存储能力)。
-
适配原因:
原生支持Amazon S3 API和OpenStack Swift API,现有基于 S3/Swift 开发的应用可无缝迁移,无需修改代码;且支持通过 RGW 网关实现多租户隔离、访问权限控制,满足云服务的多用户管理需求。
3. 数据备份与长期归档
- 核心场景:企业核心业务数据备份(如数据库备份、业务系统配置备份)、合规性归档(如金融交易记录、医疗影像归档)。
- 适配原因:
- 高可靠性:通过多副本(默认 3 副本)或 EC 纠删码技术,确保数据在硬件故障时不丢失;
- 低成本:支持对接 SATA 等低成本硬盘,且可配置数据生命周期策略(如自动将冷数据迁移至低频存储池);
- 安全特性:原生支持数据加密(静态加密、传输加密)和访问权限管控,满足归档数据的安全性与合规性要求。
4. 大数据分析数据存储层
- 核心场景:作为 Hadoop、Spark 等大数据框架的底层存储,承载原始数据集(如用户行为日志、传感器数据)和分析过程中的中间结果。
- 适配原因:
- 高吞吐量:支持并行读写操作,可同时响应多个计算节点的数据流请求,匹配大数据分析的高 IO 需求;
- 接口兼容:可通过 S3 API 或 CephFS 与大数据框架集成,避免数据在不同存储系统间迁移的开销;
- 弹性扩展:随分析数据量增长动态扩容,无需中断业务。
5. 多媒体内容存储与分发
- 核心场景:视频点播平台(存储影视资源)、直播回放(存储直播录像)、图片 CDN 源站(存储静态图片资源)等。
- 适配原因:
- 高并发读写:RGW 网关支持水平扩展,可通过负载均衡器分发请求,应对海量用户同时访问的场景;
- 低延迟访问:结合 CRUSH 算法将数据存储在靠近用户的节点,降低内容分发的网络延迟;
- 支持大文件:单个对象最大支持 5TB,满足高清视频、大尺寸图片的存储需求。
6. 容器 / Kubernetes 持久化存储
- 核心场景:为 Kubernetes 集群中的无状态服务(如 Web 应用)、有状态服务(如数据库、消息队列)提供持久化存储。
- 适配原因:
- 灵活对接:通过 RBD(块存储接口) 或 CephFS(文件系统接口) 与 Kubernetes PV/PVC 机制集成,支持动态创建存储卷;
- 高可用:存储卷数据多副本存储,即使容器节点故障,数据也不会丢失,可快速在其他节点恢复服务;
- 性能适配:支持根据业务需求选择不同存储池(如 SSD 池用于数据库,HDD 池用于日志存储)。
7. 跨地域灾难恢复
- 核心场景:企业跨数据中心(如北京 - 上海)的数据灾备,确保主数据中心故障时,可从灾备中心恢复业务。
- 适配原因:
- 多站点复制:通过 RGW 区域组(Zone Group)机制,实现主区域数据实时同步到次要区域(灾备中心);
- 故障切换:当主区域不可用时,可快速将次要区域切换为新主区域,恢复对外服务,降低业务中断时间;
- 数据一致性:同步过程保障数据完整性,避免灾备数据损坏或丢失。
8. 混合云数据协同
- 核心场景:企业在私有云(如自建 Ceph 集群)与公有云(如 AWS、阿里云)之间实现数据互通,如将冷数据迁移至公有云归档,或从公有云拉取数据到私有云进行分析。
- 适配原因:
- API 统一:基于 S3 API 实现私有云与公有云存储的接口一致,应用无需修改代码即可访问不同环境的存储;
- 数据流动:支持通过工具(如 rclone、s3cmd)或自定义脚本实现私有云与公有云数据的双向迁移;
- 成本优化:可将高频访问数据留在私有云,低频数据迁移至公有云低成本存储,平衡性能与成本。
9. 科学计算 / HPC 数据存储
- 核心场景:为气象模拟、基因测序、天文观测等科学计算场景存储海量实验数据、计算模型和结果文件。
- 适配原因:
- 高并行能力:支持 thousands 级 OSD 节点并行读写,匹配 HPC 集群多计算节点同时访问数据的需求;
- 大吞吐量:单集群吞吐量可达 GB/s 级别,满足科学计算中大规模数据传输的要求;
- 兼容专业软件:可通过 POSIX 接口(CephFS)或 S3 API 与科学计算软件(如 ANSYS、ABAQUS)集成。
10. 物联网(IoT)数据存储
- 核心场景:存储 IoT 设备(如传感器、智能终端)产生的实时数据(如温度、位置、设备状态),用于后续分析或监控。
- 适配原因:
- 高扩展性:支持百万级 OSD 节点,可随 IoT 设备数量增长无限扩容,应对海量数据涌入;
- 轻量化接入:设备可通过 S3 API 或 MQTT 协议(结合中间件)快速上传数据,无需复杂适配;
- 低功耗存储:支持对小文件(IoT 设备多产生 KB/MB 级数据)的高效存储,避免存储资源浪费。
RADOS 网关部署
Ceph 使用 Ceph 编排器来部署(或删除) RADOS 网关服务,用于管理单个集群或多个集群。使用集中式配置数据库中的 client.rgw.* 部分来定义新 RADOS 网关守护进程的参数和特征。
对象存储网关部署流程:
-
创建对象存储域
-
创建对象网关
-
对象存储网关部署流程:
- 创建对象存储域
- 创建对象网关
创建对象存储域
# 创建 realm
[root@ceph1 ~]# radosgw-admin realm create --rgw-realm=webapp --default
{"id": "70326837-6548-47f7-9f08-9c0ca790cec3","name": "webapp","current_period": "02578a13-8360-45a3-9668-24d12f207da8","epoch": 1
}
[root@ceph1 ~]# radosgw-admin realm list
{"default_info": "70326837-6548-47f7-9f08-9c0ca790cec3","realms": ["webapp"]
}# 创建 zonegroup,并将其设置为 master
[root@ceph1 ~]# radosgw-admin zonegroup create --rgw-realm=webapp --rgw-zonegroup=video --master --default
{"id": "c845536a-5030-4b81-9d95-875b78301bc5","name": "video","api_name": "video","is_master": "true","endpoints": [],"hostnames": [],"hostnames_s3website": [],"master_zone": "","zones": [],"placement_targets": [],"default_placement": "","realm_id": "70326837-6548-47f7-9f08-9c0ca790cec3","sync_policy": {"groups": []}
}
[root@ceph1 ~]# radosgw-admin zonegroup list
{"default_info": "c845536a-5030-4b81-9d95-875b78301bc5","zonegroups": ["video"]
}# 创建 zone,并将其设置为 master
[root@ceph1 ~]# radosgw-admin zone create --rgw-realm=webapp --rgw-zonegroup=video --rgw-zone=storage --master --default
[root@ceph1 ~]# radosgw-admin zone list
{"default_info": "a8427a4f-3cc1-49f9-b558-1b64c13bc519","zones": ["storage"]
}# 提交配置
[root@ceph1 ~]# radosgw-admin period update --rgw-realm=webapp --commit
RADOS 网关部署
RADOS 网关部署-命令行
# 创建 rgw,并和已创建的 realm webapp 进行关联,数量为 3
[root@ceph1 ~]# ceph orch apply rgw webapp --placement="3 ceph1.yuxb.cloud ceph2.yuxb.cloud ceph3.yuxb.cloud" --realm=webapp --zone=storage --port=8080
Scheduled rgw.webapp update...# 查看服务
[root@ceph1 ~]# ceph orch ls rgw
NAME PORTS RUNNING REFRESHED AGE PLACEMENT
rgw.webapp ?:8080 0/3 - 4s ceph1.yuxb.cloud;ceph2.yuxb.cloud;ceph3.yuxb.cloud;count:3# 查看进程
[root@ceph1 ~]# ceph orch ps --daemon-type rgw| awk '{print $1,$4}'
NAME STATUS
rgw.webapp.ceph1.hfsvnr running
rgw.webapp.ceph2.wvcfpz running
rgw.webapp.ceph3.huypef running
验证对象存储是否可以访问
[root@ceph1 ~]# curl http://ceph1.yuxb.cloud:8080
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>anonymous</ID><DisplayName></DisplayName></Owner><Buckets></Buckets></ListAllMyBucketsResult>
[root@ceph1 ~]#
[root@ceph1 ~]#
[root@ceph1 ~]# curl http://ceph2.yuxb.cloud:8080
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>anonymous</ID><DisplayName></DisplayName></Owner><Buckets></Buckets></ListAllMyBucketsResult>
[root@ceph1 ~]#
[root@ceph1 ~]#
[root@ceph1 ~]# curl http://ceph3.yuxb.cloud:8080
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>anonymous</ID><DisplayName></DisplayName></Owner><Buckets></Buckets></ListAllMyBucketsResult>
[root@ceph1 ~]#
[root@ceph1 ~]#
RADOS 网关删除
删除 RADOS 网关服务,将删除 RADOS 网关对应所有进程。
[root@ceph1 ~]# ceph orch rm rgw.webapp
Removed service rgw.webapp
删除RADOS 网关,并不会删除池中数据。
删除对象存储域
# 删除 zone
[root@ceph1 ~]# radosgw-admin zone delete --rgw-zone=storage# 删除 zonegroup
[root@ceph1 ~]# radosgw-admin zonegroup delete --rgw-zonegroup=video# 删除 realm
[root@ceph1 ~]# radosgw-admin realm delete --rgw-realm=webapp
管理对象网关用户
创建用户
使用 radosgw-admin user create 命令来创建 RADOS 网关用户。
- 必选选项 --uid 和 --display-name ,指定唯一的帐户名和人性化显示名。
- 可选选项 --access-key 和 --secret,指定自定义 AWS 帐户和机密密钥。
示例:
[root@ceph1 ~]# radosgw-admin user create --uid="operator" --display-name="S3 Operator" --email="operator@example.com" --access_key="12345" --secret="67890"
{"user_id": "operator","display_name": "S3 Operator","email": "operator@example.com","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "operator","access_key": "12345","secret_key": "67890"}],"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": []
}# 列出当前用户
[root@ceph1 ~]# radosgw-admin user list
["operator"
]# 查看它的详细信息
[root@ceph1 ~]# radosgw-admin user info --uid=operator
{"user_id": "operator","display_name": "S3 Operator","email": "operator@example.com","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "operator","access_key": "12345","secret_key": "67890"}],"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": []
}
如果未指定访问密钥和机密密钥,则自动生成,并显示在输出中
[root@ceph1 ~]# radosgw-admin user create --uid=s3user --display-name="Amazon S3 API user"
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "9bABmcXWPVGtvWb1lMw7zQ713l1Mo6kjKZWeQnf7"}],"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": []
}access_key": "KVIUDNVY5EIBIXYMETSR",# radosgw-admin 命令自动生成的访问密钥和机密密钥可能包含 JSON 转义字符(\\)。客户端可能无法正确处理此字符。建议重新生成或手动指定密钥以避免此问题。
重新生成密钥
仅重新生成现有用户的机密密钥。
[root@ceph1 ~]# radosgw-admin key create --uid=s3user --access-key="KVIUDNVY5EIBIXYMETSR" --gen-secret
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "SGBjDI5EmZ7eIwaJK3FoADiaxII4CwCfdl2jDc2U"}],"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": []
}
添加用户访问密钥
若要为现有用户添加访问密钥,请使用 –gen-access-key 选项。创建额外的密钥可以方便地授予同一用户对需要不同或唯一密钥的多个应用的访问权限。
[root@ceph1 ~]# radosgw-admin key create --uid=s3user --gen-access-key
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "2YPPG1EQ18Y40LIYM0RY","secret_key": "gYEw7s6HSwOVpsqVfpZlBIjm2zQCjK168CSwXkOi"},{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "SGBjDI5EmZ7eIwaJK3FoADiaxII4CwCfdl2jDc2U"}],"swift_keys": [],"caps": [],"op_mask": "read, write, delete","default_placement": "","default_storage_class": "",
......
删除用户密钥
要从用户删除访问密钥和相关的机密密钥,请使用 radosgw-admin key rm --access-key 命令。此操作非常适用于删除单个应用访问权限,并且不会影响使用其他密钥的访问权限。
[root@ceph1 ~]# radosgw-admin key rm --uid=s3user --access-key=2YPPG1EQ18Y40LIYM0RY
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "SGBjDI5EmZ7eIwaJK3FoADiaxII4CwCfdl2jDc2U"}],"swift_keys": [],"caps": [],"op_mask": "read, write, delete","default_placement": "","default_storage_class": "","placement_tags": [],
......
临时禁用对象网关用户
使用 radosgw-admin user suspend 命令可临时禁用 RADOS 网关用户,用户的子用户也会暂停,无法与 RADOS 网关服务交互。
[root@ceph1 ~]# radosgw-admin user suspend --uid=s3user
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 1,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user",
......# suspended的值为1。
临时启用对象网关用户
使用 radosgw-admin user enable 命令可启用 RADOS 网关用户。
[root@ceph1 ~]# radosgw-admin user enable --uid=s3user
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "SGBjDI5EmZ7eIwaJK3FoADiaxII4CwCfdl2jDc2U"}],"swift_keys": [],
......# suspended的值为0。
修改用户信息
用户可修改用户信息,如电子邮件、显示名、密钥和访问控制级别。
[root@ceph1 ~]# radosgw-admin user modify --uid=s3user --access=full
{"user_id": "s3user","display_name": "Amazon S3 API user","email": "","suspended": 0,"max_buckets": 1000,"subusers": [],"keys": [{"user": "s3user","access_key": "KVIUDNVY5EIBIXYMETSR","secret_key": "SGBjDI5EmZ7eIwaJK3FoADiaxII4CwCfdl2jDc2U"}],"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": []
}# --access 选项用于控制**子用户**访问权限,控制级别有:read、write、 readwrite 和 full。full 访问级别包括 readwrite 级别和访问控制管理功能。
删除用户
若要移除用户,同时删除其对象和存储桶,需使用 --purge-data 选项。
[root@ceph1 ~]# radosgw-admin user list
["operator","s3user"
]
[root@ceph1 ~]# radosgw-admin user rm --uid=s3user --purge-data
[root@ceph1 ~]# radosgw-admin user list
["operator"
]
使用 Amazon S3 API 访问对象存储
Amazon S3 API 介绍
在混合云环境中,若需让应用通过统一 API 无缝混用私有企业资源、公共云资源及存储位置,Ceph 存储可通过支持 Amazon S3 API 接口 实现对象存储资源的管理,具体要点如下:
- 核心适配逻辑:Amazon S3 API 以 “存储桶(Bucket)” 作为命名空间,用于承载对象存储;应用若需通过该 API 管理 Ceph 中的对象与存储桶,需通过 RADOS 网关(RGW)用户 完成身份验证 —— 每个 RGW 用户会分配唯一的
access key
(用户标识)和secret key
(身份验证密钥),二者共同作为 API 调用的身份凭证。 - 对象与元数据大小限制:使用 Amazon S3 API 操作 Ceph 对象存储时,需遵守以下大小约束:
- 对象数据大小:单个对象大小范围为 0B ~ 5TB;
- 单次上传上限:直接单次上传操作的最大对象大小为 5GB;
- 分段上传场景:若对象大小超过 100MB,建议使用分段上传功能(将大对象拆分为多个片段依次上传,最终合并);
- 元数据大小:单个 HTTP 请求中携带的元数据(含系统元数据与用户元数据)最大容量为 16,000 字节。
安装 Amazon S3 API 客户端
Amazon S3 API 客户端有多个,例如 awscli、cloudberry、cyberduck 和 curl。
# aws# 准备 aliyun 源 pip 仓库
[root@client ~]# mkdir .pip
[root@client ~]# cat > .pip/pip.conf << 'EOF'
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/[install]
trusted-host=mirrors.aliyun.com
EOF# 安装软件包
[root@client ~]# pip3 install awscli
使用 Amazon S3 API 客户端
# aws 命令帮助信息
配置 AWS CLI 凭据
配置 AWS CLI 工具默认凭据:使用 operator 用户,输入 12345 作为访问密钥,67890 作为机密密钥。
[root@client ~]# aws configure
AWS Access Key ID [None]: 12345
AWS Secret Access Key [None]: 67890
Default region name [None]:
Default output format [None]:
配置信息
[root@client ~]# ls .aws
config credentials[root@client ~]# cat .aws/config
[default]
[root@client ~]# cat .aws/credentials
[default]
aws_access_key_id = 12345
aws_secret_access_key = 67890# aws 命令默认使用 default 中凭据
创建存储桶
通过选项 –profile 指定凭据,–endpoint 指定服务器位置。
[root@client ~]# aws --endpoint=http://ceph1.yuxb.cloud:8080 s3 mb s3://webapp
make_bucket: webapp
查看存储桶清单
[root@client ~]# aws --endpoint=http://ceph1.yuxb.cloud:8080 s3 ls
2025-09-30 16:59:07 webapp
radosgw-admin 命令也支持存储桶操作,例如使用 radosgw-admin bucket list 或 radosgw-admin bucket rm 命令。
[root@client ~]# radosgw-admin buckets list
["webapp"
]
上传对象到存储桶
cp 子命令支持三种复制方向:
<LocalPath> <S3Uri>
,将本地文件上传到对象存储中。<S3Uri> <LocalPath>
,下载对象存储中对象到本地。<S3Uri> <S3Uri>
,将对象存储中对象复制到对象存储中。
[root@client ~]# echo Hello World > Welcome-pub.html
[root@client ~]# echo Hello yuxb > Welcome-pri.html
[root@client ~]# aws --endpoint=http://ceph1.yuxb.cloud:8080 s3 cp Welcome-pub.html s3://webapp/ --acl=public-read-write
upload: ./Welcome-pub.html to s3://webapp/Welcome-pub.html
[root@client ~]# aws s3 cp Welcome-pri.html s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
upload: ./Welcome-pri.html to s3://webapp/Welcome-pri.html
查看存储桶中对象
[root@client ~]# aws s3 ls s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
2025-09-30 17:00:22 11 Welcome-pri.html
2025-09-30 17:00:21 12 Welcome-pub.html
下载存储桶中对象
# 下载单个
[root@client ~]# aws s3 cp s3://webapp/Welcome-pri.html /tmp --endpoint=http://ceph1.yuxb.cloud:8080
download: s3://webapp/Welcome-pri.html to ../tmp/Welcome-pri.html
[root@client ~]# ls /tmp/Welcome-pri.html
/tmp/Welcome-pri.html# 使用选项 --recursive 递归下载bucket中所有对象
[root@client ~]# aws s3 cp s3://webapp /tmp --recursive --endpoint=http://ceph1.yuxb.cloud:8080
download: s3://webapp/Welcome-pri.html to ../tmp/Welcome-pri.html
download: s3://webapp/Welcome-pub.html to ../tmp/Welcome-pub.html# 使用wget或者curl下载
[root@client ~]# wget http://ceph1.yuxb.cloud:8080/webapp/Welcome-pub.html # Welcome-pub.html
--2025-09-30 17:02:04-- http://ceph1.yuxb.cloud:8080/webapp/Welcome-pub.html
Resolving ceph1.yuxb.cloud (ceph1.yuxb.cloud)... 192.168.108.11
Connecting to ceph1.yuxb.cloud (ceph1.yuxb.cloud)|192.168.108.11|:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 12 [text/html]
Saving to: ‘Welcome-pub.html.1’Welcome-pub.html.1 100%[=========================>] 12 --.-KB/s in 0s2025-09-30 17:02:04 (1.51 MB/s) - ‘Welcome-pub.html.1’ saved [12/12][root@client ~]# wget http://ceph1.yuxb.cloud:8080/webapp/Welcome-pri.html # Welcome-pri.html
--2025-09-30 17:02:14-- http://ceph1.yuxb.cloud:8080/webapp/Welcome-pri.html
Resolving ceph1.yuxb.cloud (ceph1.yuxb.cloud)... 192.168.108.11
Connecting to ceph1.yuxb.cloud (ceph1.yuxb.cloud)|192.168.108.11|:8080... connected.
HTTP request sent, awaiting response... 403 Forbidden
2025-09-30 17:02:14 ERROR 403: Forbidden.
删除存储桶中对象
[root@client ~]# aws s3 rm s3://webapp/Welcome-pri.html --endpoint=http://ceph1.yuxb.cloud:8080
delete: s3://webapp/Welcome-pri.html[root@client ~]# aws s3 ls s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
2025-09-30 17:00:21 12 Welcome-pub.html
删除存储桶
# 非空的存储桶不能删除
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
remove_bucket failed: s3://webapp argument of type 'NoneType' is not iterable# 清空存储桶,再次删除
[root@client ~]# aws s3 rm s3://webapp --recursive --include "Welcome-*" --endpoint=http://ceph1.yuxb.cloud:8080
delete: s3://webapp/Welcome-pub.html
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
remove_bucket: webapp
html
download: s3://webapp/Welcome-pub.html to …/tmp/Welcome-pub.html
使用wget或者curl下载
[root@client ~]# wget http://ceph1.yuxb.cloud:8080/webapp/Welcome-pub.html # Welcome-pub.html
–2025-09-30 17:02:04-- http://ceph1.yuxb.cloud:8080/webapp/Welcome-pub.html
Resolving ceph1.yuxb.cloud (ceph1.yuxb.cloud)… 192.168.108.11
Connecting to ceph1.yuxb.cloud (ceph1.yuxb.cloud)|192.168.108.11|:8080… connected.
HTTP request sent, awaiting response… 200 OK
Length: 12 [text/html]
Saving to: ‘Welcome-pub.html.1’
Welcome-pub.html.1 100%[=========================>] 12 --.-KB/s in 0s
2025-09-30 17:02:04 (1.51 MB/s) - ‘Welcome-pub.html.1’ saved [12/12]
[root@client ~]# wget http://ceph1.yuxb.cloud:8080/webapp/Welcome-pri.html # Welcome-pri.html
–2025-09-30 17:02:14-- http://ceph1.yuxb.cloud:8080/webapp/Welcome-pri.html
Resolving ceph1.yuxb.cloud (ceph1.yuxb.cloud)… 192.168.108.11
Connecting to ceph1.yuxb.cloud (ceph1.yuxb.cloud)|192.168.108.11|:8080… connected.
HTTP request sent, awaiting response… 403 Forbidden
2025-09-30 17:02:14 ERROR 403: Forbidden.
#### 删除存储桶中对象```bash
[root@client ~]# aws s3 rm s3://webapp/Welcome-pri.html --endpoint=http://ceph1.yuxb.cloud:8080
delete: s3://webapp/Welcome-pri.html[root@client ~]# aws s3 ls s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
2025-09-30 17:00:21 12 Welcome-pub.html
删除存储桶
# 非空的存储桶不能删除
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
remove_bucket failed: s3://webapp argument of type 'NoneType' is not iterable# 清空存储桶,再次删除
[root@client ~]# aws s3 rm s3://webapp --recursive --include "Welcome-*" --endpoint=http://ceph1.yuxb.cloud:8080
delete: s3://webapp/Welcome-pub.html
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.yuxb.cloud:8080
remove_bucket: webapp